From 6681914b541d32f0dbd991498dc36d6b44674aa2 Mon Sep 17 00:00:00 2001 From: asquared31415 <34665709+asquared31415@users.noreply.github.com> Date: Tue, 28 Mar 2023 23:30:20 -0400 Subject: [PATCH 001/310] make cast_possible_wrap not lint on conversions for sizes that cannot wrap, and make it work correctly for 16 bit {u,i}size --- clippy_lints/src/casts/cast_possible_wrap.rs | 82 ++++++++++---- clippy_lints/src/casts/mod.rs | 7 +- tests/ui/cast.rs | 8 ++ tests/ui/cast.stderr | 112 ++++++++++++++++--- 4 files changed, 171 insertions(+), 38 deletions(-) diff --git a/clippy_lints/src/casts/cast_possible_wrap.rs b/clippy_lints/src/casts/cast_possible_wrap.rs index 28ecdea7ea0..e872d190c82 100644 --- a/clippy_lints/src/casts/cast_possible_wrap.rs +++ b/clippy_lints/src/casts/cast_possible_wrap.rs @@ -1,41 +1,81 @@ use clippy_utils::diagnostics::span_lint; -use clippy_utils::ty::is_isize_or_usize; use rustc_hir::Expr; use rustc_lint::LateContext; use rustc_middle::ty::Ty; use super::{utils, CAST_POSSIBLE_WRAP}; +// this should be kept in sync with the allowed bit widths of `usize` and `isize` +const ALLOWED_POINTER_SIZES: [u64; 3] = [16, 32, 64]; + +// whether the lint should be emitted, and the required pointer size, if it matters +enum EmitState { + NoLint, + LintAlways, + LintOnPtrSize(u64), +} + pub(super) fn check(cx: &LateContext<'_>, expr: &Expr<'_>, cast_from: Ty<'_>, cast_to: Ty<'_>) { if !(cast_from.is_integral() && cast_to.is_integral()) { return; } - let arch_64_suffix = " on targets with 64-bit wide pointers"; - let arch_32_suffix = " on targets with 32-bit wide pointers"; - let cast_unsigned_to_signed = !cast_from.is_signed() && cast_to.is_signed(); + // emit a lint if a cast is: + // 1. unsigned to signed + // and + // 2. either: + // 2a. between two types of constant size that are always the same size + // 2b. between one target-dependent size and one constant size integer, + // and the constant integer is in the allowed set of target dependent sizes + // (the ptr size could be chosen to be the same as the constant size) + + if cast_from.is_signed() || !cast_to.is_signed() { + return; + } + let from_nbits = utils::int_ty_to_nbits(cast_from, cx.tcx); let to_nbits = utils::int_ty_to_nbits(cast_to, cx.tcx); - let (should_lint, suffix) = match (is_isize_or_usize(cast_from), is_isize_or_usize(cast_to)) { - (true, true) | (false, false) => (to_nbits == from_nbits && cast_unsigned_to_signed, ""), - (true, false) => (to_nbits <= 32 && cast_unsigned_to_signed, arch_32_suffix), - (false, true) => ( - cast_unsigned_to_signed, - if from_nbits == 64 { - arch_64_suffix + let should_lint = match (cast_from.is_ptr_sized_integral(), cast_to.is_ptr_sized_integral()) { + (true, true) => { + // casts between two ptr sized integers are trivially always the same size + // so do not depend on any specific pointer size to be the same + EmitState::LintAlways + }, + (true, false) => { + // the first type is `usize` and the second is a constant sized signed integer + if ALLOWED_POINTER_SIZES.contains(&to_nbits) { + EmitState::LintOnPtrSize(to_nbits) } else { - arch_32_suffix - }, + EmitState::NoLint + } + }, + (false, true) => { + // the first type is a constant sized unsigned integer, and the second is `isize` + if ALLOWED_POINTER_SIZES.contains(&from_nbits) { + EmitState::LintOnPtrSize(from_nbits) + } else { + EmitState::NoLint + } + }, + (false, false) => { + // the types are both a constant known size + // and do not depend on any specific pointer size to be the same + if from_nbits == to_nbits { + EmitState::LintAlways + } else { + EmitState::NoLint + } + }, + }; + + let message = match should_lint { + EmitState::NoLint => return, + EmitState::LintAlways => format!("casting `{cast_from}` to `{cast_to}` may wrap around the value"), + EmitState::LintOnPtrSize(ptr_size) => format!( + "casting `{cast_from}` to `{cast_to}` may wrap around the value on targets with {ptr_size}-bit wide pointers", ), }; - if should_lint { - span_lint( - cx, - CAST_POSSIBLE_WRAP, - expr.span, - &format!("casting `{cast_from}` to `{cast_to}` may wrap around the value{suffix}",), - ); - } + span_lint(cx, CAST_POSSIBLE_WRAP, expr.span, message.as_str()); } diff --git a/clippy_lints/src/casts/mod.rs b/clippy_lints/src/casts/mod.rs index 362f70d12d1..877bee5e4d1 100644 --- a/clippy_lints/src/casts/mod.rs +++ b/clippy_lints/src/casts/mod.rs @@ -118,9 +118,10 @@ declare_clippy_lint! { declare_clippy_lint! { /// ### What it does /// Checks for casts from an unsigned type to a signed type of - /// the same size. Performing such a cast is a 'no-op' for the compiler, - /// i.e., nothing is changed at the bit level, and the binary representation of - /// the value is reinterpreted. This can cause wrapping if the value is too big + /// the same size, or possibly smaller due to target dependent integers. + /// Performing such a cast is a 'no-op' for the compiler, i.e., nothing is + /// changed at the bit level, and the binary representation of the value is + /// reinterpreted. This can cause wrapping if the value is too big /// for the target signed type. However, the cast works as defined, so this lint /// is `Allow` by default. /// diff --git a/tests/ui/cast.rs b/tests/ui/cast.rs index a86b85706a3..60a0eabf55b 100644 --- a/tests/ui/cast.rs +++ b/tests/ui/cast.rs @@ -41,6 +41,14 @@ fn main() { 1u32 as i32; 1u64 as i64; 1usize as isize; + 1usize as i8; // should not wrap, usize is never 8 bits + 1usize as i16; // wraps on 16 bit ptr size + 1usize as i32; // wraps on 32 bit ptr size + 1usize as i64; // wraps on 64 bit ptr size + 1u8 as isize; // should not wrap, isize is never 8 bits + 1u16 as isize; // wraps on 16 bit ptr size + 1u32 as isize; // wraps on 32 bit ptr size + 1u64 as isize; // wraps on 64 bit ptr size // Test clippy::cast_sign_loss 1i32 as u32; -1i32 as u32; diff --git a/tests/ui/cast.stderr b/tests/ui/cast.stderr index 65ecf1aa37a..a7d78a95d59 100644 --- a/tests/ui/cast.stderr +++ b/tests/ui/cast.stderr @@ -215,20 +215,104 @@ error: casting `usize` to `isize` may wrap around the value LL | 1usize as isize; | ^^^^^^^^^^^^^^^ -error: casting `i32` to `u32` may lose the sign of the value +error: casting `usize` to `i8` may truncate the value + --> $DIR/cast.rs:44:5 + | +LL | 1usize as i8; // should not wrap, usize is never 8 bits + | ^^^^^^^^^^^^ + | + = 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 | i8::try_from(1usize); // should not wrap, usize is never 8 bits + | ~~~~~~~~~~~~~~~~~~~~ + +error: casting `usize` to `i16` may truncate the value + --> $DIR/cast.rs:45:5 + | +LL | 1usize as i16; // wraps on 16 bit ptr size + | ^^^^^^^^^^^^^ + | + = 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 | i16::try_from(1usize); // wraps on 16 bit ptr size + | ~~~~~~~~~~~~~~~~~~~~~ + +error: casting `usize` to `i16` may wrap around the value on targets with 16-bit wide pointers + --> $DIR/cast.rs:45:5 + | +LL | 1usize as i16; // wraps on 16 bit ptr size + | ^^^^^^^^^^^^^ + +error: casting `usize` to `i32` may truncate the value on targets with 64-bit wide pointers --> $DIR/cast.rs:46:5 | +LL | 1usize as i32; // wraps on 32 bit ptr size + | ^^^^^^^^^^^^^ + | + = 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); // wraps on 32 bit ptr size + | ~~~~~~~~~~~~~~~~~~~~~ + +error: casting `usize` to `i32` may wrap around the value on targets with 32-bit wide pointers + --> $DIR/cast.rs:46:5 + | +LL | 1usize as i32; // wraps on 32 bit ptr size + | ^^^^^^^^^^^^^ + +error: casting `usize` to `i64` may wrap around the value on targets with 64-bit wide pointers + --> $DIR/cast.rs:47:5 + | +LL | 1usize as i64; // wraps on 64 bit ptr size + | ^^^^^^^^^^^^^ + +error: casting `u16` to `isize` may wrap around the value on targets with 16-bit wide pointers + --> $DIR/cast.rs:49:5 + | +LL | 1u16 as isize; // wraps on 16 bit ptr size + | ^^^^^^^^^^^^^ + +error: casting `u32` to `isize` may wrap around the value on targets with 32-bit wide pointers + --> $DIR/cast.rs:50:5 + | +LL | 1u32 as isize; // wraps on 32 bit ptr size + | ^^^^^^^^^^^^^ + +error: casting `u64` to `isize` may truncate the value on targets with 32-bit wide pointers + --> $DIR/cast.rs:51:5 + | +LL | 1u64 as isize; // wraps on 64 bit ptr size + | ^^^^^^^^^^^^^ + | + = 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); // wraps on 64 bit ptr size + | ~~~~~~~~~~~~~~~~~~~~~ + +error: casting `u64` to `isize` may wrap around the value on targets with 64-bit wide pointers + --> $DIR/cast.rs:51:5 + | +LL | 1u64 as isize; // wraps on 64 bit ptr size + | ^^^^^^^^^^^^^ + +error: casting `i32` to `u32` may lose the sign of the value + --> $DIR/cast.rs:54:5 + | LL | -1i32 as u32; | ^^^^^^^^^^^^ error: casting `isize` to `usize` may lose the sign of the value - --> $DIR/cast.rs:48:5 + --> $DIR/cast.rs:56:5 | LL | -1isize as usize; | ^^^^^^^^^^^^^^^^ error: casting `i64` to `i8` may truncate the value - --> $DIR/cast.rs:115:5 + --> $DIR/cast.rs:123:5 | LL | (-99999999999i64).min(1) as i8; // should be linted because signed | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -240,7 +324,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:127:5 + --> $DIR/cast.rs:135:5 | LL | 999999u64.clamp(0, 256) as u8; // should still be linted | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -252,7 +336,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:148:21 + --> $DIR/cast.rs:156:21 | LL | let _ = self as u8; | ^^^^^^^^^^ @@ -264,7 +348,7 @@ LL | let _ = u8::try_from(self); | ~~~~~~~~~~~~~~~~~~ error: casting `main::E2::B` to `u8` will truncate the value - --> $DIR/cast.rs:149:21 + --> $DIR/cast.rs:157:21 | LL | let _ = Self::B as u8; | ^^^^^^^^^^^^^ @@ -272,7 +356,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:185:21 + --> $DIR/cast.rs:193:21 | LL | let _ = self as i8; | ^^^^^^^^^^ @@ -284,13 +368,13 @@ LL | let _ = i8::try_from(self); | ~~~~~~~~~~~~~~~~~~ error: casting `main::E5::A` to `i8` will truncate the value - --> $DIR/cast.rs:186:21 + --> $DIR/cast.rs:194:21 | LL | let _ = Self::A as i8; | ^^^^^^^^^^^^^ error: casting `main::E6` to `i16` may truncate the value - --> $DIR/cast.rs:200:21 + --> $DIR/cast.rs:208:21 | LL | let _ = self as i16; | ^^^^^^^^^^^ @@ -302,7 +386,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:215:21 + --> $DIR/cast.rs:223:21 | LL | let _ = self as usize; | ^^^^^^^^^^^^^ @@ -314,7 +398,7 @@ LL | let _ = usize::try_from(self); | ~~~~~~~~~~~~~~~~~~~~~ error: casting `main::E10` to `u16` may truncate the value - --> $DIR/cast.rs:256:21 + --> $DIR/cast.rs:264:21 | LL | let _ = self as u16; | ^^^^^^^^^^^ @@ -326,7 +410,7 @@ LL | let _ = u16::try_from(self); | ~~~~~~~~~~~~~~~~~~~ error: casting `u32` to `u8` may truncate the value - --> $DIR/cast.rs:264:13 + --> $DIR/cast.rs:272:13 | LL | let c = (q >> 16) as u8; | ^^^^^^^^^^^^^^^ @@ -338,7 +422,7 @@ LL | let c = u8::try_from(q >> 16); | ~~~~~~~~~~~~~~~~~~~~~ error: casting `u32` to `u8` may truncate the value - --> $DIR/cast.rs:267:13 + --> $DIR/cast.rs:275:13 | LL | let c = (q / 1000) as u8; | ^^^^^^^^^^^^^^^^ @@ -349,5 +433,5 @@ help: ... or use `try_from` and handle the error accordingly LL | let c = u8::try_from(q / 1000); | ~~~~~~~~~~~~~~~~~~~~~~ -error: aborting due to 41 previous errors +error: aborting due to 51 previous errors From b4067660f6d15e31f28e06c983630dc011a24b97 Mon Sep 17 00:00:00 2001 From: Alex Macleod Date: Sun, 23 Apr 2023 14:20:55 +0000 Subject: [PATCH 002/310] Add a test that checks for old style test headers --- tests/headers.rs | 29 +++++++++++++++++++++++ tests/ui/crashes/ice-10645.rs | 2 +- tests/ui/crashes/ice-10645.stderr | 4 ++-- tests/ui/crashes/ice-4968.rs | 2 -- tests/ui/expect_tool_lint_rfc_2383.rs | 1 - tests/ui/expect_tool_lint_rfc_2383.stderr | 12 +++++----- 6 files changed, 38 insertions(+), 12 deletions(-) create mode 100644 tests/headers.rs diff --git a/tests/headers.rs b/tests/headers.rs new file mode 100644 index 00000000000..1d1e566cbf6 --- /dev/null +++ b/tests/headers.rs @@ -0,0 +1,29 @@ +use regex::Regex; +use std::fs; +use walkdir::WalkDir; + +#[test] +fn old_test_headers() { + let old_headers = Regex::new( + r"^//( ?\[\w+\])? ?((check|build|run|ignore|aux|only|needs|rustc|unset|no|normalize|run|compile)-|edition|incremental|revisions).*", + ) + .unwrap(); + let mut failed = false; + + for entry in WalkDir::new("tests") { + let entry = entry.unwrap(); + if !entry.file_type().is_file() { + continue; + } + + let file = fs::read_to_string(entry.path()).unwrap(); + + if let Some(header) = old_headers.find(&file) { + println!("Found header `{}` in {}", header.as_str(), entry.path().display()); + + failed = true; + } + } + + assert!(!failed, "use `//@foo` style test headers instead"); +} diff --git a/tests/ui/crashes/ice-10645.rs b/tests/ui/crashes/ice-10645.rs index 4d8698d383b..6e126aff751 100644 --- a/tests/ui/crashes/ice-10645.rs +++ b/tests/ui/crashes/ice-10645.rs @@ -1,4 +1,4 @@ -// compile-flags: --cap-lints=warn +//@compile-flags: --cap-lints=warn // https://github.com/rust-lang/rust-clippy/issues/10645 #![warn(clippy::future_not_send)] diff --git a/tests/ui/crashes/ice-10645.stderr b/tests/ui/crashes/ice-10645.stderr index fc084e30d7f..0055fe061e2 100644 --- a/tests/ui/crashes/ice-10645.stderr +++ b/tests/ui/crashes/ice-10645.stderr @@ -1,4 +1,4 @@ -error: future cannot be sent between threads safely +warning: future cannot be sent between threads safely --> $DIR/ice-10645.rs:5: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` -error: aborting due to previous error +warning: 1 warning emitted diff --git a/tests/ui/crashes/ice-4968.rs b/tests/ui/crashes/ice-4968.rs index ac724ac93e3..50473868005 100644 --- a/tests/ui/crashes/ice-4968.rs +++ b/tests/ui/crashes/ice-4968.rs @@ -1,5 +1,3 @@ -//@check-pass - // Test for https://github.com/rust-lang/rust-clippy/issues/4968 #![warn(clippy::unsound_collection_transmute)] diff --git a/tests/ui/expect_tool_lint_rfc_2383.rs b/tests/ui/expect_tool_lint_rfc_2383.rs index 018f875d60b..ca81808a863 100644 --- a/tests/ui/expect_tool_lint_rfc_2383.rs +++ b/tests/ui/expect_tool_lint_rfc_2383.rs @@ -1,4 +1,3 @@ -// check-pass #![feature(lint_reasons)] //! This file tests the `#[expect]` attribute implementation for tool lints. The same //! file is used to test clippy and rustdoc. Any changes to this file should be synced diff --git a/tests/ui/expect_tool_lint_rfc_2383.stderr b/tests/ui/expect_tool_lint_rfc_2383.stderr index 7ce9e855b5e..77210ca7a9d 100644 --- a/tests/ui/expect_tool_lint_rfc_2383.stderr +++ b/tests/ui/expect_tool_lint_rfc_2383.stderr @@ -1,5 +1,5 @@ error: this lint expectation is unfulfilled - --> $DIR/expect_tool_lint_rfc_2383.rs:35:14 + --> $DIR/expect_tool_lint_rfc_2383.rs:34:14 | LL | #[expect(dead_code)] | ^^^^^^^^^ @@ -7,31 +7,31 @@ LL | #[expect(dead_code)] = note: `-D unfulfilled-lint-expectations` implied by `-D warnings` error: this lint expectation is unfulfilled - --> $DIR/expect_tool_lint_rfc_2383.rs:39:18 + --> $DIR/expect_tool_lint_rfc_2383.rs:38:18 | LL | #[expect(illegal_floating_point_literal_pattern)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: this lint expectation is unfulfilled - --> $DIR/expect_tool_lint_rfc_2383.rs:113:14 + --> $DIR/expect_tool_lint_rfc_2383.rs:112:14 | LL | #[expect(clippy::almost_swapped)] | ^^^^^^^^^^^^^^^^^^^^^^ error: this lint expectation is unfulfilled - --> $DIR/expect_tool_lint_rfc_2383.rs:120:14 + --> $DIR/expect_tool_lint_rfc_2383.rs:119:14 | LL | #[expect(clippy::bytes_nth)] | ^^^^^^^^^^^^^^^^^ error: this lint expectation is unfulfilled - --> $DIR/expect_tool_lint_rfc_2383.rs:125:14 + --> $DIR/expect_tool_lint_rfc_2383.rs:124:14 | LL | #[expect(clippy::if_same_then_else)] | ^^^^^^^^^^^^^^^^^^^^^^^^^ error: this lint expectation is unfulfilled - --> $DIR/expect_tool_lint_rfc_2383.rs:130:14 + --> $DIR/expect_tool_lint_rfc_2383.rs:129:14 | LL | #[expect(clippy::overly_complex_bool_expr)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ From 9a61550e785b8e0d705948881112a80abe387998 Mon Sep 17 00:00:00 2001 From: Albert Larsan <74931857+albertlarsan68@users.noreply.github.com> Date: Wed, 4 Jan 2023 14:16:55 +0100 Subject: [PATCH 003/310] Make `{Arc,Rc,Weak}::ptr_eq` ignore pointer metadata --- clippy_lints/src/unnamed_address.rs | 4 +--- clippy_utils/src/paths.rs | 2 -- tests/ui/vtable_address_comparisons.rs | 12 ++++++------ tests/ui/vtable_address_comparisons.stderr | 18 +----------------- 4 files changed, 8 insertions(+), 28 deletions(-) diff --git a/clippy_lints/src/unnamed_address.rs b/clippy_lints/src/unnamed_address.rs index 0bcafde658a..0f5cdb6aaea 100644 --- a/clippy_lints/src/unnamed_address.rs +++ b/clippy_lints/src/unnamed_address.rs @@ -96,9 +96,7 @@ impl LateLintPass<'_> for UnnamedAddress { if let ExprKind::Call(func, [ref _left, ref _right]) = expr.kind; if let ExprKind::Path(ref func_qpath) = func.kind; if let Some(def_id) = cx.qpath_res(func_qpath, func.hir_id).opt_def_id(); - if match_def_path(cx, def_id, &paths::PTR_EQ) || - match_def_path(cx, def_id, &paths::RC_PTR_EQ) || - match_def_path(cx, def_id, &paths::ARC_PTR_EQ); + if match_def_path(cx, def_id, &paths::PTR_EQ); let ty_param = cx.typeck_results().node_substs(func.hir_id).type_at(0); if ty_param.is_trait(); then { diff --git a/clippy_utils/src/paths.rs b/clippy_utils/src/paths.rs index 9be2d0eae80..126356c9682 100644 --- a/clippy_utils/src/paths.rs +++ b/clippy_utils/src/paths.rs @@ -15,7 +15,6 @@ pub const APPLICABILITY_VALUES: [[&str; 3]; 4] = [ ]; #[cfg(feature = "internal")] pub const DIAGNOSTIC_BUILDER: [&str; 3] = ["rustc_errors", "diagnostic_builder", "DiagnosticBuilder"]; -pub const ARC_PTR_EQ: [&str; 4] = ["alloc", "sync", "Arc", "ptr_eq"]; pub const BTREEMAP_CONTAINS_KEY: [&str; 6] = ["alloc", "collections", "btree", "map", "BTreeMap", "contains_key"]; pub const BTREEMAP_INSERT: [&str; 6] = ["alloc", "collections", "btree", "map", "BTreeMap", "insert"]; pub const BTREESET_ITER: [&str; 6] = ["alloc", "collections", "btree", "set", "BTreeSet", "iter"]; @@ -93,7 +92,6 @@ pub const PTR_WRITE_UNALIGNED: [&str; 3] = ["core", "ptr", "write_unaligned"]; pub const PTR_WRITE_VOLATILE: [&str; 3] = ["core", "ptr", "write_volatile"]; pub const PUSH_STR: [&str; 4] = ["alloc", "string", "String", "push_str"]; pub const RANGE_ARGUMENT_TRAIT: [&str; 3] = ["core", "ops", "RangeBounds"]; -pub const RC_PTR_EQ: [&str; 4] = ["alloc", "rc", "Rc", "ptr_eq"]; pub const REFCELL_REF: [&str; 3] = ["core", "cell", "Ref"]; pub const REFCELL_REFMUT: [&str; 3] = ["core", "cell", "RefMut"]; pub const REGEX_BUILDER_NEW: [&str; 5] = ["regex", "re_builder", "unicode", "RegexBuilder", "new"]; diff --git a/tests/ui/vtable_address_comparisons.rs b/tests/ui/vtable_address_comparisons.rs index a9a4a0f5a6b..99c3f468f04 100644 --- a/tests/ui/vtable_address_comparisons.rs +++ b/tests/ui/vtable_address_comparisons.rs @@ -23,12 +23,6 @@ fn main() { let b = &1 as &dyn Debug; ptr::eq(a, b); - let a: Rc = Rc::new(1); - Rc::ptr_eq(&a, &a); - - let a: Arc = Arc::new(1); - Arc::ptr_eq(&a, &a); - // These should be fine: let a = &1; ptr::eq(a, a); @@ -39,6 +33,12 @@ fn main() { let a = Arc::new(1); Arc::ptr_eq(&a, &a); + let a: Rc = Rc::new(1); + Rc::ptr_eq(&a, &a); + + let a: Arc = Arc::new(1); + Arc::ptr_eq(&a, &a); + let a: &[u8] = b""; ptr::eq(a, a); } diff --git a/tests/ui/vtable_address_comparisons.stderr b/tests/ui/vtable_address_comparisons.stderr index 14748f583f0..7b866d274d5 100644 --- a/tests/ui/vtable_address_comparisons.stderr +++ b/tests/ui/vtable_address_comparisons.stderr @@ -63,21 +63,5 @@ LL | ptr::eq(a, b); | = help: consider extracting and comparing data pointers only -error: comparing trait object pointers compares a non-unique vtable address - --> $DIR/vtable_address_comparisons.rs:27:5 - | -LL | Rc::ptr_eq(&a, &a); - | ^^^^^^^^^^^^^^^^^^ - | - = help: consider extracting and comparing data pointers only - -error: comparing trait object pointers compares a non-unique vtable address - --> $DIR/vtable_address_comparisons.rs:30:5 - | -LL | Arc::ptr_eq(&a, &a); - | ^^^^^^^^^^^^^^^^^^^ - | - = help: consider extracting and comparing data pointers only - -error: aborting due to 10 previous errors +error: aborting due to 8 previous errors From b7a60547125fd1b0d06547ed038deb4a906afc67 Mon Sep 17 00:00:00 2001 From: blyxyas Date: Sun, 23 Apr 2023 01:42:32 +0200 Subject: [PATCH 004/310] Refresh Lint Configuration's looks --- book/src/lint_configuration.md | 494 ++++++++++-------- .../internal_lints/metadata_collector.rs | 10 +- clippy_lints/src/utils/mod.rs | 9 +- 3 files changed, 284 insertions(+), 229 deletions(-) diff --git a/book/src/lint_configuration.md b/book/src/lint_configuration.md index 5646c9b1520..4c888b63793 100644 --- a/book/src/lint_configuration.md +++ b/book/src/lint_configuration.md @@ -3,63 +3,14 @@ This file is generated by `cargo collect-metadata`. Please use that command to update the file and do not edit it by hand. --> -## Lint Configuration Options -|
Option
| Default Value | -|--|--| -| [arithmetic-side-effects-allowed](#arithmetic-side-effects-allowed) | `{}` | -| [arithmetic-side-effects-allowed-binary](#arithmetic-side-effects-allowed-binary) | `[]` | -| [arithmetic-side-effects-allowed-unary](#arithmetic-side-effects-allowed-unary) | `{}` | -| [avoid-breaking-exported-api](#avoid-breaking-exported-api) | `true` | -| [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` | -| [single-char-binding-names-threshold](#single-char-binding-names-threshold) | `4` | -| [too-large-for-stack](#too-large-for-stack) | `200` | -| [enum-variant-name-threshold](#enum-variant-name-threshold) | `3` | -| [enum-variant-size-threshold](#enum-variant-size-threshold) | `200` | -| [verbose-bit-mask-threshold](#verbose-bit-mask-threshold) | `1` | -| [literal-representation-threshold](#literal-representation-threshold) | `16384` | -| [trivial-copy-size-limit](#trivial-copy-size-limit) | `None` | -| [pass-by-value-size-limit](#pass-by-value-size-limit) | `256` | -| [too-many-lines-threshold](#too-many-lines-threshold) | `100` | -| [array-size-threshold](#array-size-threshold) | `512000` | -| [vec-box-size-threshold](#vec-box-size-threshold) | `4096` | -| [max-trait-bounds](#max-trait-bounds) | `3` | -| [max-struct-bools](#max-struct-bools) | `3` | -| [max-fn-params-bools](#max-fn-params-bools) | `3` | -| [warn-on-all-wildcard-imports](#warn-on-all-wildcard-imports) | `false` | -| [disallowed-macros](#disallowed-macros) | `[]` | -| [disallowed-methods](#disallowed-methods) | `[]` | -| [disallowed-types](#disallowed-types) | `[]` | -| [unreadable-literal-lint-fractions](#unreadable-literal-lint-fractions) | `true` | -| [upper-case-acronyms-aggressive](#upper-case-acronyms-aggressive) | `false` | -| [matches-for-let-else](#matches-for-let-else) | `WellKnownTypes` | -| [cargo-ignore-publish](#cargo-ignore-publish) | `false` | -| [standard-macro-braces](#standard-macro-braces) | `[]` | -| [enforced-import-renames](#enforced-import-renames) | `[]` | -| [allowed-scripts](#allowed-scripts) | `["Latin"]` | -| [enable-raw-pointer-heuristic-for-send](#enable-raw-pointer-heuristic-for-send) | `true` | -| [max-suggested-slice-pattern-length](#max-suggested-slice-pattern-length) | `3` | -| [await-holding-invalid-types](#await-holding-invalid-types) | `[]` | -| [max-include-file-size](#max-include-file-size) | `1000000` | -| [allow-expect-in-tests](#allow-expect-in-tests) | `false` | -| [allow-unwrap-in-tests](#allow-unwrap-in-tests) | `false` | -| [allow-dbg-in-tests](#allow-dbg-in-tests) | `false` | -| [allow-print-in-tests](#allow-print-in-tests) | `false` | -| [large-error-threshold](#large-error-threshold) | `128` | -| [ignore-interior-mutability](#ignore-interior-mutability) | `["bytes::Bytes"]` | -| [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` | -| [unnecessary-box-size](#unnecessary-box-size) | `128` | +# Lint Configuration Options -### arithmetic-side-effects-allowed +The following list shows each configuration option, along with a description, its default value, an example +and lints affected. + +--- + +## `arithmetic-side-effects-allowed` Suppress checking of the passed type names in all types of operations. If a specific operation is desired, consider using `arithmetic_side_effects_allowed_binary` or `arithmetic_side_effects_allowed_unary` instead. @@ -77,10 +28,12 @@ A type, say `SomeType`, listed in this configuration has the same behavior of **Default Value:** `{}` (`rustc_data_structures::fx::FxHashSet`) -* [arithmetic_side_effects](https://rust-lang.github.io/rust-clippy/master/index.html#arithmetic_side_effects) +--- +**Affected lints:** +* [`arithmetic_side_effects`](https://rust-lang.github.io/rust-clippy/master/index.html#arithmetic_side_effects) -### arithmetic-side-effects-allowed-binary +## `arithmetic-side-effects-allowed-binary` Suppress checking of the passed type pair names in binary operations like addition or multiplication. @@ -98,10 +51,12 @@ arithmetic-side-effects-allowed-binary = [["SomeType" , "f32"], ["AnotherType", **Default Value:** `[]` (`Vec<[String; 2]>`) -* [arithmetic_side_effects](https://rust-lang.github.io/rust-clippy/master/index.html#arithmetic_side_effects) +--- +**Affected lints:** +* [`arithmetic_side_effects`](https://rust-lang.github.io/rust-clippy/master/index.html#arithmetic_side_effects) -### arithmetic-side-effects-allowed-unary +## `arithmetic-side-effects-allowed-unary` Suppress checking of the passed type names in unary operations like "negation" (`-`). #### Example @@ -112,116 +67,130 @@ arithmetic-side-effects-allowed-unary = ["SomeType", "AnotherType"] **Default Value:** `{}` (`rustc_data_structures::fx::FxHashSet`) -* [arithmetic_side_effects](https://rust-lang.github.io/rust-clippy/master/index.html#arithmetic_side_effects) +--- +**Affected lints:** +* [`arithmetic_side_effects`](https://rust-lang.github.io/rust-clippy/master/index.html#arithmetic_side_effects) -### avoid-breaking-exported-api +## `avoid-breaking-exported-api` Suppress lints whenever the suggested change would cause breakage for other crates. **Default Value:** `true` (`bool`) -* [enum_variant_names](https://rust-lang.github.io/rust-clippy/master/index.html#enum_variant_names) -* [large_types_passed_by_value](https://rust-lang.github.io/rust-clippy/master/index.html#large_types_passed_by_value) -* [trivially_copy_pass_by_ref](https://rust-lang.github.io/rust-clippy/master/index.html#trivially_copy_pass_by_ref) -* [unnecessary_wraps](https://rust-lang.github.io/rust-clippy/master/index.html#unnecessary_wraps) -* [unused_self](https://rust-lang.github.io/rust-clippy/master/index.html#unused_self) -* [upper_case_acronyms](https://rust-lang.github.io/rust-clippy/master/index.html#upper_case_acronyms) -* [wrong_self_convention](https://rust-lang.github.io/rust-clippy/master/index.html#wrong_self_convention) -* [box_collection](https://rust-lang.github.io/rust-clippy/master/index.html#box_collection) -* [redundant_allocation](https://rust-lang.github.io/rust-clippy/master/index.html#redundant_allocation) -* [rc_buffer](https://rust-lang.github.io/rust-clippy/master/index.html#rc_buffer) -* [vec_box](https://rust-lang.github.io/rust-clippy/master/index.html#vec_box) -* [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) +--- +**Affected lints:** +* [`enum_variant_names`](https://rust-lang.github.io/rust-clippy/master/index.html#enum_variant_names) +* [`large_types_passed_by_value`](https://rust-lang.github.io/rust-clippy/master/index.html#large_types_passed_by_value) +* [`trivially_copy_pass_by_ref`](https://rust-lang.github.io/rust-clippy/master/index.html#trivially_copy_pass_by_ref) +* [`unnecessary_wraps`](https://rust-lang.github.io/rust-clippy/master/index.html#unnecessary_wraps) +* [`unused_self`](https://rust-lang.github.io/rust-clippy/master/index.html#unused_self) +* [`upper_case_acronyms`](https://rust-lang.github.io/rust-clippy/master/index.html#upper_case_acronyms) +* [`wrong_self_convention`](https://rust-lang.github.io/rust-clippy/master/index.html#wrong_self_convention) +* [`box_collection`](https://rust-lang.github.io/rust-clippy/master/index.html#box_collection) +* [`redundant_allocation`](https://rust-lang.github.io/rust-clippy/master/index.html#redundant_allocation) +* [`rc_buffer`](https://rust-lang.github.io/rust-clippy/master/index.html#rc_buffer) +* [`vec_box`](https://rust-lang.github.io/rust-clippy/master/index.html#vec_box) +* [`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 +## `msrv` The minimum rust version that the project supports **Default Value:** `None` (`Option`) -* [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) -* [cloned_instead_of_copied](https://rust-lang.github.io/rust-clippy/master/index.html#cloned_instead_of_copied) -* [redundant_field_names](https://rust-lang.github.io/rust-clippy/master/index.html#redundant_field_names) -* [redundant_static_lifetimes](https://rust-lang.github.io/rust-clippy/master/index.html#redundant_static_lifetimes) -* [filter_map_next](https://rust-lang.github.io/rust-clippy/master/index.html#filter_map_next) -* [checked_conversions](https://rust-lang.github.io/rust-clippy/master/index.html#checked_conversions) -* [manual_range_contains](https://rust-lang.github.io/rust-clippy/master/index.html#manual_range_contains) -* [use_self](https://rust-lang.github.io/rust-clippy/master/index.html#use_self) -* [mem_replace_with_default](https://rust-lang.github.io/rust-clippy/master/index.html#mem_replace_with_default) -* [manual_non_exhaustive](https://rust-lang.github.io/rust-clippy/master/index.html#manual_non_exhaustive) -* [option_as_ref_deref](https://rust-lang.github.io/rust-clippy/master/index.html#option_as_ref_deref) -* [map_unwrap_or](https://rust-lang.github.io/rust-clippy/master/index.html#map_unwrap_or) -* [match_like_matches_macro](https://rust-lang.github.io/rust-clippy/master/index.html#match_like_matches_macro) -* [manual_strip](https://rust-lang.github.io/rust-clippy/master/index.html#manual_strip) -* [missing_const_for_fn](https://rust-lang.github.io/rust-clippy/master/index.html#missing_const_for_fn) -* [unnested_or_patterns](https://rust-lang.github.io/rust-clippy/master/index.html#unnested_or_patterns) -* [from_over_into](https://rust-lang.github.io/rust-clippy/master/index.html#from_over_into) -* [ptr_as_ptr](https://rust-lang.github.io/rust-clippy/master/index.html#ptr_as_ptr) -* [if_then_some_else_none](https://rust-lang.github.io/rust-clippy/master/index.html#if_then_some_else_none) -* [approx_constant](https://rust-lang.github.io/rust-clippy/master/index.html#approx_constant) -* [deprecated_cfg_attr](https://rust-lang.github.io/rust-clippy/master/index.html#deprecated_cfg_attr) -* [index_refutable_slice](https://rust-lang.github.io/rust-clippy/master/index.html#index_refutable_slice) -* [map_clone](https://rust-lang.github.io/rust-clippy/master/index.html#map_clone) -* [borrow_as_ptr](https://rust-lang.github.io/rust-clippy/master/index.html#borrow_as_ptr) -* [manual_bits](https://rust-lang.github.io/rust-clippy/master/index.html#manual_bits) -* [err_expect](https://rust-lang.github.io/rust-clippy/master/index.html#err_expect) -* [cast_abs_to_unsigned](https://rust-lang.github.io/rust-clippy/master/index.html#cast_abs_to_unsigned) -* [uninlined_format_args](https://rust-lang.github.io/rust-clippy/master/index.html#uninlined_format_args) -* [manual_clamp](https://rust-lang.github.io/rust-clippy/master/index.html#manual_clamp) -* [manual_let_else](https://rust-lang.github.io/rust-clippy/master/index.html#manual_let_else) -* [unchecked_duration_subtraction](https://rust-lang.github.io/rust-clippy/master/index.html#unchecked_duration_subtraction) -* [collapsible_str_replace](https://rust-lang.github.io/rust-clippy/master/index.html#collapsible_str_replace) -* [seek_from_current](https://rust-lang.github.io/rust-clippy/master/index.html#seek_from_current) -* [seek_rewind](https://rust-lang.github.io/rust-clippy/master/index.html#seek_rewind) -* [unnecessary_lazy_evaluations](https://rust-lang.github.io/rust-clippy/master/index.html#unnecessary_lazy_evaluations) -* [transmute_ptr_to_ref](https://rust-lang.github.io/rust-clippy/master/index.html#transmute_ptr_to_ref) -* [almost_complete_range](https://rust-lang.github.io/rust-clippy/master/index.html#almost_complete_range) -* [needless_borrow](https://rust-lang.github.io/rust-clippy/master/index.html#needless_borrow) -* [derivable_impls](https://rust-lang.github.io/rust-clippy/master/index.html#derivable_impls) -* [manual_is_ascii_check](https://rust-lang.github.io/rust-clippy/master/index.html#manual_is_ascii_check) -* [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) +--- +**Affected lints:** +* [`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) +* [`cloned_instead_of_copied`](https://rust-lang.github.io/rust-clippy/master/index.html#cloned_instead_of_copied) +* [`redundant_field_names`](https://rust-lang.github.io/rust-clippy/master/index.html#redundant_field_names) +* [`redundant_static_lifetimes`](https://rust-lang.github.io/rust-clippy/master/index.html#redundant_static_lifetimes) +* [`filter_map_next`](https://rust-lang.github.io/rust-clippy/master/index.html#filter_map_next) +* [`checked_conversions`](https://rust-lang.github.io/rust-clippy/master/index.html#checked_conversions) +* [`manual_range_contains`](https://rust-lang.github.io/rust-clippy/master/index.html#manual_range_contains) +* [`use_self`](https://rust-lang.github.io/rust-clippy/master/index.html#use_self) +* [`mem_replace_with_default`](https://rust-lang.github.io/rust-clippy/master/index.html#mem_replace_with_default) +* [`manual_non_exhaustive`](https://rust-lang.github.io/rust-clippy/master/index.html#manual_non_exhaustive) +* [`option_as_ref_deref`](https://rust-lang.github.io/rust-clippy/master/index.html#option_as_ref_deref) +* [`map_unwrap_or`](https://rust-lang.github.io/rust-clippy/master/index.html#map_unwrap_or) +* [`match_like_matches_macro`](https://rust-lang.github.io/rust-clippy/master/index.html#match_like_matches_macro) +* [`manual_strip`](https://rust-lang.github.io/rust-clippy/master/index.html#manual_strip) +* [`missing_const_for_fn`](https://rust-lang.github.io/rust-clippy/master/index.html#missing_const_for_fn) +* [`unnested_or_patterns`](https://rust-lang.github.io/rust-clippy/master/index.html#unnested_or_patterns) +* [`from_over_into`](https://rust-lang.github.io/rust-clippy/master/index.html#from_over_into) +* [`ptr_as_ptr`](https://rust-lang.github.io/rust-clippy/master/index.html#ptr_as_ptr) +* [`if_then_some_else_none`](https://rust-lang.github.io/rust-clippy/master/index.html#if_then_some_else_none) +* [`approx_constant`](https://rust-lang.github.io/rust-clippy/master/index.html#approx_constant) +* [`deprecated_cfg_attr`](https://rust-lang.github.io/rust-clippy/master/index.html#deprecated_cfg_attr) +* [`index_refutable_slice`](https://rust-lang.github.io/rust-clippy/master/index.html#index_refutable_slice) +* [`map_clone`](https://rust-lang.github.io/rust-clippy/master/index.html#map_clone) +* [`borrow_as_ptr`](https://rust-lang.github.io/rust-clippy/master/index.html#borrow_as_ptr) +* [`manual_bits`](https://rust-lang.github.io/rust-clippy/master/index.html#manual_bits) +* [`err_expect`](https://rust-lang.github.io/rust-clippy/master/index.html#err_expect) +* [`cast_abs_to_unsigned`](https://rust-lang.github.io/rust-clippy/master/index.html#cast_abs_to_unsigned) +* [`uninlined_format_args`](https://rust-lang.github.io/rust-clippy/master/index.html#uninlined_format_args) +* [`manual_clamp`](https://rust-lang.github.io/rust-clippy/master/index.html#manual_clamp) +* [`manual_let_else`](https://rust-lang.github.io/rust-clippy/master/index.html#manual_let_else) +* [`unchecked_duration_subtraction`](https://rust-lang.github.io/rust-clippy/master/index.html#unchecked_duration_subtraction) +* [`collapsible_str_replace`](https://rust-lang.github.io/rust-clippy/master/index.html#collapsible_str_replace) +* [`seek_from_current`](https://rust-lang.github.io/rust-clippy/master/index.html#seek_from_current) +* [`seek_rewind`](https://rust-lang.github.io/rust-clippy/master/index.html#seek_rewind) +* [`unnecessary_lazy_evaluations`](https://rust-lang.github.io/rust-clippy/master/index.html#unnecessary_lazy_evaluations) +* [`transmute_ptr_to_ref`](https://rust-lang.github.io/rust-clippy/master/index.html#transmute_ptr_to_ref) +* [`almost_complete_range`](https://rust-lang.github.io/rust-clippy/master/index.html#almost_complete_range) +* [`needless_borrow`](https://rust-lang.github.io/rust-clippy/master/index.html#needless_borrow) +* [`derivable_impls`](https://rust-lang.github.io/rust-clippy/master/index.html#derivable_impls) +* [`manual_is_ascii_check`](https://rust-lang.github.io/rust-clippy/master/index.html#manual_is_ascii_check) +* [`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) -### cognitive-complexity-threshold +## `cognitive-complexity-threshold` The maximum cognitive complexity a function can have **Default Value:** `25` (`u64`) -* [cognitive_complexity](https://rust-lang.github.io/rust-clippy/master/index.html#cognitive_complexity) +--- +**Affected lints:** +* [`cognitive_complexity`](https://rust-lang.github.io/rust-clippy/master/index.html#cognitive_complexity) -### disallowed-names +## `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 Value:** `["foo", "baz", "quux"]` (`Vec`) -* [disallowed_names](https://rust-lang.github.io/rust-clippy/master/index.html#disallowed_names) +--- +**Affected lints:** +* [`disallowed_names`](https://rust-lang.github.io/rust-clippy/master/index.html#disallowed_names) -### semicolon-inside-block-ignore-singleline +## `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) +--- +**Affected lints:** +* [`semicolon_inside_block`](https://rust-lang.github.io/rust-clippy/master/index.html#semicolon_inside_block) -### semicolon-outside-block-ignore-multiline +## `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) +--- +**Affected lints:** +* [`semicolon_outside_block`](https://rust-lang.github.io/rust-clippy/master/index.html#semicolon_outside_block) -### doc-valid-idents +## `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 configuration will replace the default value. For example: @@ -232,205 +201,255 @@ Default list: **Default Value:** `["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"]` (`Vec`) -* [doc_markdown](https://rust-lang.github.io/rust-clippy/master/index.html#doc_markdown) +--- +**Affected lints:** +* [`doc_markdown`](https://rust-lang.github.io/rust-clippy/master/index.html#doc_markdown) -### too-many-arguments-threshold +## `too-many-arguments-threshold` The maximum number of argument a function or method can have **Default Value:** `7` (`u64`) -* [too_many_arguments](https://rust-lang.github.io/rust-clippy/master/index.html#too_many_arguments) +--- +**Affected lints:** +* [`too_many_arguments`](https://rust-lang.github.io/rust-clippy/master/index.html#too_many_arguments) -### type-complexity-threshold +## `type-complexity-threshold` The maximum complexity a type can have **Default Value:** `250` (`u64`) -* [type_complexity](https://rust-lang.github.io/rust-clippy/master/index.html#type_complexity) +--- +**Affected lints:** +* [`type_complexity`](https://rust-lang.github.io/rust-clippy/master/index.html#type_complexity) -### single-char-binding-names-threshold +## `single-char-binding-names-threshold` The maximum number of single char bindings a scope may have **Default Value:** `4` (`u64`) -* [many_single_char_names](https://rust-lang.github.io/rust-clippy/master/index.html#many_single_char_names) +--- +**Affected lints:** +* [`many_single_char_names`](https://rust-lang.github.io/rust-clippy/master/index.html#many_single_char_names) -### too-large-for-stack +## `too-large-for-stack` The maximum size of objects (in bytes) that will be linted. Larger objects are ok on the heap **Default Value:** `200` (`u64`) -* [boxed_local](https://rust-lang.github.io/rust-clippy/master/index.html#boxed_local) -* [useless_vec](https://rust-lang.github.io/rust-clippy/master/index.html#useless_vec) +--- +**Affected lints:** +* [`boxed_local`](https://rust-lang.github.io/rust-clippy/master/index.html#boxed_local) +* [`useless_vec`](https://rust-lang.github.io/rust-clippy/master/index.html#useless_vec) -### enum-variant-name-threshold +## `enum-variant-name-threshold` The minimum number of enum variants for the lints about variant names to trigger **Default Value:** `3` (`u64`) -* [enum_variant_names](https://rust-lang.github.io/rust-clippy/master/index.html#enum_variant_names) +--- +**Affected lints:** +* [`enum_variant_names`](https://rust-lang.github.io/rust-clippy/master/index.html#enum_variant_names) -### enum-variant-size-threshold +## `enum-variant-size-threshold` The maximum size of an enum's variant to avoid box suggestion **Default Value:** `200` (`u64`) -* [large_enum_variant](https://rust-lang.github.io/rust-clippy/master/index.html#large_enum_variant) +--- +**Affected lints:** +* [`large_enum_variant`](https://rust-lang.github.io/rust-clippy/master/index.html#large_enum_variant) -### verbose-bit-mask-threshold +## `verbose-bit-mask-threshold` The maximum allowed size of a bit mask before suggesting to use 'trailing_zeros' **Default Value:** `1` (`u64`) -* [verbose_bit_mask](https://rust-lang.github.io/rust-clippy/master/index.html#verbose_bit_mask) +--- +**Affected lints:** +* [`verbose_bit_mask`](https://rust-lang.github.io/rust-clippy/master/index.html#verbose_bit_mask) -### literal-representation-threshold +## `literal-representation-threshold` The lower bound for linting decimal literals **Default Value:** `16384` (`u64`) -* [decimal_literal_representation](https://rust-lang.github.io/rust-clippy/master/index.html#decimal_literal_representation) +--- +**Affected lints:** +* [`decimal_literal_representation`](https://rust-lang.github.io/rust-clippy/master/index.html#decimal_literal_representation) -### trivial-copy-size-limit +## `trivial-copy-size-limit` The maximum size (in bytes) to consider a `Copy` type for passing by value instead of by reference. **Default Value:** `None` (`Option`) -* [trivially_copy_pass_by_ref](https://rust-lang.github.io/rust-clippy/master/index.html#trivially_copy_pass_by_ref) +--- +**Affected lints:** +* [`trivially_copy_pass_by_ref`](https://rust-lang.github.io/rust-clippy/master/index.html#trivially_copy_pass_by_ref) -### pass-by-value-size-limit +## `pass-by-value-size-limit` The minimum size (in bytes) to consider a type for passing by reference instead of by value. **Default Value:** `256` (`u64`) -* [large_types_passed_by_value](https://rust-lang.github.io/rust-clippy/master/index.html#large_types_passed_by_value) +--- +**Affected lints:** +* [`large_types_passed_by_value`](https://rust-lang.github.io/rust-clippy/master/index.html#large_types_passed_by_value) -### too-many-lines-threshold +## `too-many-lines-threshold` The maximum number of lines a function or method can have **Default Value:** `100` (`u64`) -* [too_many_lines](https://rust-lang.github.io/rust-clippy/master/index.html#too_many_lines) +--- +**Affected lints:** +* [`too_many_lines`](https://rust-lang.github.io/rust-clippy/master/index.html#too_many_lines) -### array-size-threshold +## `array-size-threshold` The maximum allowed size for arrays on the stack **Default Value:** `512000` (`u64`) -* [large_stack_arrays](https://rust-lang.github.io/rust-clippy/master/index.html#large_stack_arrays) -* [large_const_arrays](https://rust-lang.github.io/rust-clippy/master/index.html#large_const_arrays) +--- +**Affected lints:** +* [`large_stack_arrays`](https://rust-lang.github.io/rust-clippy/master/index.html#large_stack_arrays) +* [`large_const_arrays`](https://rust-lang.github.io/rust-clippy/master/index.html#large_const_arrays) -### vec-box-size-threshold +## `vec-box-size-threshold` The size of the boxed type in bytes, where boxing in a `Vec` is allowed **Default Value:** `4096` (`u64`) -* [vec_box](https://rust-lang.github.io/rust-clippy/master/index.html#vec_box) +--- +**Affected lints:** +* [`vec_box`](https://rust-lang.github.io/rust-clippy/master/index.html#vec_box) -### max-trait-bounds +## `max-trait-bounds` The maximum number of bounds a trait can have to be linted **Default Value:** `3` (`u64`) -* [type_repetition_in_bounds](https://rust-lang.github.io/rust-clippy/master/index.html#type_repetition_in_bounds) +--- +**Affected lints:** +* [`type_repetition_in_bounds`](https://rust-lang.github.io/rust-clippy/master/index.html#type_repetition_in_bounds) -### max-struct-bools +## `max-struct-bools` The maximum number of bool fields a struct can have **Default Value:** `3` (`u64`) -* [struct_excessive_bools](https://rust-lang.github.io/rust-clippy/master/index.html#struct_excessive_bools) +--- +**Affected lints:** +* [`struct_excessive_bools`](https://rust-lang.github.io/rust-clippy/master/index.html#struct_excessive_bools) -### max-fn-params-bools +## `max-fn-params-bools` The maximum number of bool parameters a function can have **Default Value:** `3` (`u64`) -* [fn_params_excessive_bools](https://rust-lang.github.io/rust-clippy/master/index.html#fn_params_excessive_bools) +--- +**Affected lints:** +* [`fn_params_excessive_bools`](https://rust-lang.github.io/rust-clippy/master/index.html#fn_params_excessive_bools) -### warn-on-all-wildcard-imports +## `warn-on-all-wildcard-imports` Whether to allow certain wildcard imports (prelude, super in tests). **Default Value:** `false` (`bool`) -* [wildcard_imports](https://rust-lang.github.io/rust-clippy/master/index.html#wildcard_imports) +--- +**Affected lints:** +* [`wildcard_imports`](https://rust-lang.github.io/rust-clippy/master/index.html#wildcard_imports) -### disallowed-macros +## `disallowed-macros` The list of disallowed macros, written as fully qualified paths. **Default Value:** `[]` (`Vec`) -* [disallowed_macros](https://rust-lang.github.io/rust-clippy/master/index.html#disallowed_macros) +--- +**Affected lints:** +* [`disallowed_macros`](https://rust-lang.github.io/rust-clippy/master/index.html#disallowed_macros) -### disallowed-methods +## `disallowed-methods` The list of disallowed methods, written as fully qualified paths. **Default Value:** `[]` (`Vec`) -* [disallowed_methods](https://rust-lang.github.io/rust-clippy/master/index.html#disallowed_methods) +--- +**Affected lints:** +* [`disallowed_methods`](https://rust-lang.github.io/rust-clippy/master/index.html#disallowed_methods) -### disallowed-types +## `disallowed-types` The list of disallowed types, written as fully qualified paths. **Default Value:** `[]` (`Vec`) -* [disallowed_types](https://rust-lang.github.io/rust-clippy/master/index.html#disallowed_types) +--- +**Affected lints:** +* [`disallowed_types`](https://rust-lang.github.io/rust-clippy/master/index.html#disallowed_types) -### unreadable-literal-lint-fractions +## `unreadable-literal-lint-fractions` Should the fraction of a decimal be linted to include separators. **Default Value:** `true` (`bool`) -* [unreadable_literal](https://rust-lang.github.io/rust-clippy/master/index.html#unreadable_literal) +--- +**Affected lints:** +* [`unreadable_literal`](https://rust-lang.github.io/rust-clippy/master/index.html#unreadable_literal) -### upper-case-acronyms-aggressive +## `upper-case-acronyms-aggressive` Enables verbose mode. Triggers if there is more than one uppercase char next to each other **Default Value:** `false` (`bool`) -* [upper_case_acronyms](https://rust-lang.github.io/rust-clippy/master/index.html#upper_case_acronyms) +--- +**Affected lints:** +* [`upper_case_acronyms`](https://rust-lang.github.io/rust-clippy/master/index.html#upper_case_acronyms) -### matches-for-let-else +## `matches-for-let-else` Whether the matches should be considered by the lint, and whether there should be filtering for common types. **Default Value:** `WellKnownTypes` (`crate::manual_let_else::MatchLintBehaviour`) -* [manual_let_else](https://rust-lang.github.io/rust-clippy/master/index.html#manual_let_else) +--- +**Affected lints:** +* [`manual_let_else`](https://rust-lang.github.io/rust-clippy/master/index.html#manual_let_else) -### cargo-ignore-publish +## `cargo-ignore-publish` For internal testing only, ignores the current `publish` settings in the Cargo manifest. **Default Value:** `false` (`bool`) -* [_cargo_common_metadata](https://rust-lang.github.io/rust-clippy/master/index.html#_cargo_common_metadata) +--- +**Affected lints:** +* [`_cargo_common_metadata`](https://rust-lang.github.io/rust-clippy/master/index.html#_cargo_common_metadata) -### standard-macro-braces +## `standard-macro-braces` Enforce the named macros always use the braces specified. A `MacroMatcher` can be added like so `{ name = "macro_name", brace = "(" }`. If the macro @@ -439,119 +458,147 @@ could be used with a full path two `MacroMatcher`s have to be added one with the **Default Value:** `[]` (`Vec`) -* [nonstandard_macro_braces](https://rust-lang.github.io/rust-clippy/master/index.html#nonstandard_macro_braces) +--- +**Affected lints:** +* [`nonstandard_macro_braces`](https://rust-lang.github.io/rust-clippy/master/index.html#nonstandard_macro_braces) -### enforced-import-renames +## `enforced-import-renames` The list of imports to always rename, a fully qualified path followed by the rename. **Default Value:** `[]` (`Vec`) -* [missing_enforced_import_renames](https://rust-lang.github.io/rust-clippy/master/index.html#missing_enforced_import_renames) +--- +**Affected lints:** +* [`missing_enforced_import_renames`](https://rust-lang.github.io/rust-clippy/master/index.html#missing_enforced_import_renames) -### allowed-scripts +## `allowed-scripts` The list of unicode scripts allowed to be used in the scope. **Default Value:** `["Latin"]` (`Vec`) -* [disallowed_script_idents](https://rust-lang.github.io/rust-clippy/master/index.html#disallowed_script_idents) +--- +**Affected lints:** +* [`disallowed_script_idents`](https://rust-lang.github.io/rust-clippy/master/index.html#disallowed_script_idents) -### enable-raw-pointer-heuristic-for-send +## `enable-raw-pointer-heuristic-for-send` Whether to apply the raw pointer heuristic to determine if a type is `Send`. **Default Value:** `true` (`bool`) -* [non_send_fields_in_send_ty](https://rust-lang.github.io/rust-clippy/master/index.html#non_send_fields_in_send_ty) +--- +**Affected lints:** +* [`non_send_fields_in_send_ty`](https://rust-lang.github.io/rust-clippy/master/index.html#non_send_fields_in_send_ty) -### max-suggested-slice-pattern-length +## `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 are necessary, the lint is suppressed. For example, `[_, _, _, e, ..]` is a slice pattern with 4 elements. **Default Value:** `3` (`u64`) -* [index_refutable_slice](https://rust-lang.github.io/rust-clippy/master/index.html#index_refutable_slice) +--- +**Affected lints:** +* [`index_refutable_slice`](https://rust-lang.github.io/rust-clippy/master/index.html#index_refutable_slice) -### await-holding-invalid-types +## `await-holding-invalid-types` **Default Value:** `[]` (`Vec`) -* [await_holding_invalid_type](https://rust-lang.github.io/rust-clippy/master/index.html#await_holding_invalid_type) +--- +**Affected lints:** +* [`await_holding_invalid_type`](https://rust-lang.github.io/rust-clippy/master/index.html#await_holding_invalid_type) -### max-include-file-size +## `max-include-file-size` The maximum size of a file included via `include_bytes!()` or `include_str!()`, in bytes **Default Value:** `1000000` (`u64`) -* [large_include_file](https://rust-lang.github.io/rust-clippy/master/index.html#large_include_file) +--- +**Affected lints:** +* [`large_include_file`](https://rust-lang.github.io/rust-clippy/master/index.html#large_include_file) -### allow-expect-in-tests +## `allow-expect-in-tests` Whether `expect` should be allowed in test functions or `#[cfg(test)]` **Default Value:** `false` (`bool`) -* [expect_used](https://rust-lang.github.io/rust-clippy/master/index.html#expect_used) +--- +**Affected lints:** +* [`expect_used`](https://rust-lang.github.io/rust-clippy/master/index.html#expect_used) -### allow-unwrap-in-tests +## `allow-unwrap-in-tests` Whether `unwrap` should be allowed in test functions or `#[cfg(test)]` **Default Value:** `false` (`bool`) -* [unwrap_used](https://rust-lang.github.io/rust-clippy/master/index.html#unwrap_used) +--- +**Affected lints:** +* [`unwrap_used`](https://rust-lang.github.io/rust-clippy/master/index.html#unwrap_used) -### allow-dbg-in-tests +## `allow-dbg-in-tests` Whether `dbg!` should be allowed in test functions or `#[cfg(test)]` **Default Value:** `false` (`bool`) -* [dbg_macro](https://rust-lang.github.io/rust-clippy/master/index.html#dbg_macro) +--- +**Affected lints:** +* [`dbg_macro`](https://rust-lang.github.io/rust-clippy/master/index.html#dbg_macro) -### allow-print-in-tests +## `allow-print-in-tests` Whether print macros (ex. `println!`) should be allowed in test functions or `#[cfg(test)]` **Default Value:** `false` (`bool`) -* [print_stdout](https://rust-lang.github.io/rust-clippy/master/index.html#print_stdout) -* [print_stderr](https://rust-lang.github.io/rust-clippy/master/index.html#print_stderr) +--- +**Affected lints:** +* [`print_stdout`](https://rust-lang.github.io/rust-clippy/master/index.html#print_stdout) +* [`print_stderr`](https://rust-lang.github.io/rust-clippy/master/index.html#print_stderr) -### large-error-threshold +## `large-error-threshold` The maximum size of the `Err`-variant in a `Result` returned from a function **Default Value:** `128` (`u64`) -* [result_large_err](https://rust-lang.github.io/rust-clippy/master/index.html#result_large_err) +--- +**Affected lints:** +* [`result_large_err`](https://rust-lang.github.io/rust-clippy/master/index.html#result_large_err) -### ignore-interior-mutability +## `ignore-interior-mutability` A list of paths to types that should be treated like `Arc`, i.e. ignored but for the generic parameters for determining interior mutability **Default Value:** `["bytes::Bytes"]` (`Vec`) -* [mutable_key_type](https://rust-lang.github.io/rust-clippy/master/index.html#mutable_key_type) -* [ifs_same_cond](https://rust-lang.github.io/rust-clippy/master/index.html#ifs_same_cond) +--- +**Affected lints:** +* [`mutable_key_type`](https://rust-lang.github.io/rust-clippy/master/index.html#mutable_key_type) +* [`ifs_same_cond`](https://rust-lang.github.io/rust-clippy/master/index.html#ifs_same_cond) -### allow-mixed-uninlined-format-args +## `allow-mixed-uninlined-format-args` Whether to allow mixed uninlined format args, e.g. `format!("{} {}", a, foo.bar)` **Default Value:** `true` (`bool`) -* [uninlined_format_args](https://rust-lang.github.io/rust-clippy/master/index.html#uninlined_format_args) +--- +**Affected lints:** +* [`uninlined_format_args`](https://rust-lang.github.io/rust-clippy/master/index.html#uninlined_format_args) -### suppress-restriction-lint-in-const +## `suppress-restriction-lint-in-const` Whether to suppress a restriction lint in constant code. In same cases the restructured operation might not be unavoidable, as the suggested counterparts are unavailable in constant code. This @@ -560,32 +607,39 @@ if no suggestion can be made. **Default Value:** `false` (`bool`) -* [indexing_slicing](https://rust-lang.github.io/rust-clippy/master/index.html#indexing_slicing) +--- +**Affected lints:** +* [`indexing_slicing`](https://rust-lang.github.io/rust-clippy/master/index.html#indexing_slicing) -### missing-docs-in-crate-items +## `missing-docs-in-crate-items` Whether to **only** check for missing documentation in items visible within the current crate. For example, `pub(crate)` items. **Default Value:** `false` (`bool`) -* [missing_docs_in_private_items](https://rust-lang.github.io/rust-clippy/master/index.html#missing_docs_in_private_items) +--- +**Affected lints:** +* [`missing_docs_in_private_items`](https://rust-lang.github.io/rust-clippy/master/index.html#missing_docs_in_private_items) -### future-size-threshold +## `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) +--- +**Affected lints:** +* [`large_futures`](https://rust-lang.github.io/rust-clippy/master/index.html#large_futures) -### unnecessary-box-size +## `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) - +--- +**Affected lints:** +* [`unnecessary_box_returns`](https://rust-lang.github.io/rust-clippy/master/index.html#unnecessary_box_returns) diff --git a/clippy_lints/src/utils/internal_lints/metadata_collector.rs b/clippy_lints/src/utils/internal_lints/metadata_collector.rs index 7a1cd3effae..2a9aba0a116 100644 --- a/clippy_lints/src/utils/internal_lints/metadata_collector.rs +++ b/clippy_lints/src/utils/internal_lints/metadata_collector.rs @@ -195,8 +195,14 @@ This lint has the following configuration variables: fn get_markdown_docs(&self) -> String { format!( - "## Lint Configuration Options\n|
Option
| Default Value |\n|--|--|\n{}\n\n{}\n", - self.configs_to_markdown(ClippyConfiguration::to_markdown_table_entry), + r#"# Lint Configuration Options + +The following list shows each configuration option, along with a description, its default value, an example +and lints affected. + +--- + +{}"#, self.configs_to_markdown(ClippyConfiguration::to_markdown_paragraph), ) } diff --git a/clippy_lints/src/utils/mod.rs b/clippy_lints/src/utils/mod.rs index d3ea7cafa80..884edec2d79 100644 --- a/clippy_lints/src/utils/mod.rs +++ b/clippy_lints/src/utils/mod.rs @@ -51,7 +51,7 @@ impl ClippyConfiguration { #[cfg(feature = "internal")] fn to_markdown_paragraph(&self) -> String { format!( - "### {}\n{}\n\n**Default Value:** `{}` (`{}`)\n\n{}\n\n", + "## `{}`\n{}\n\n**Default Value:** `{}` (`{}`)\n\n---\n**Affected lints:**\n{}\n\n", self.name, self.doc .lines() @@ -62,15 +62,10 @@ impl ClippyConfiguration { self.lints .iter() .map(|name| name.to_string().split_whitespace().next().unwrap().to_string()) - .map(|name| format!("* [{name}](https://rust-lang.github.io/rust-clippy/master/index.html#{name})")) + .map(|name| format!("* [`{name}`](https://rust-lang.github.io/rust-clippy/master/index.html#{name})")) .join("\n"), ) } - - #[cfg(feature = "internal")] - fn to_markdown_table_entry(&self) -> String { - format!("| [{}](#{}) | `{}` |", self.name, self.name, self.default) - } } #[cfg(feature = "internal")] From f4b02aa3741299b8226f50ba63ec1f4e27a64d14 Mon Sep 17 00:00:00 2001 From: Centri3 <114838443+Centri3@users.noreply.github.com> Date: Mon, 15 May 2023 11:20:04 -0500 Subject: [PATCH 005/310] fix #10776 --- .../src/mixed_read_write_in_expression.rs | 6 +-- tests/ui/diverging_sub_expression.rs | 4 ++ tests/ui/diverging_sub_expression.stderr | 40 ------------------- 3 files changed, 6 insertions(+), 44 deletions(-) diff --git a/clippy_lints/src/mixed_read_write_in_expression.rs b/clippy_lints/src/mixed_read_write_in_expression.rs index f0be7771bb1..2dfab259915 100644 --- a/clippy_lints/src/mixed_read_write_in_expression.rs +++ b/clippy_lints/src/mixed_read_write_in_expression.rs @@ -1,7 +1,7 @@ use clippy_utils::diagnostics::{span_lint, span_lint_and_note}; use clippy_utils::{get_parent_expr, path_to_local, path_to_local_id}; use if_chain::if_chain; -use rustc_hir::intravisit::{walk_expr, Visitor}; +use rustc_hir::intravisit::{walk_block, walk_expr, Visitor}; use rustc_hir::{BinOpKind, Block, Expr, ExprKind, Guard, HirId, Local, Node, Stmt, StmtKind}; use rustc_lint::{LateContext, LateLintPass}; use rustc_middle::ty; @@ -155,6 +155,7 @@ impl<'a, 'tcx> Visitor<'tcx> for DivergenceVisitor<'a, 'tcx> { self.report_diverging_sub_expr(e); } }, + ExprKind::Block(block, ..) => walk_block(self, block), _ => { // do not lint expressions referencing objects of type `!`, as that required a // diverging expression @@ -163,9 +164,6 @@ impl<'a, 'tcx> Visitor<'tcx> for DivergenceVisitor<'a, 'tcx> { } self.maybe_walk_expr(e); } - fn visit_block(&mut self, _: &'tcx Block<'_>) { - // don't continue over blocks, LateLintPass already does that - } } /// Walks up the AST from the given write expression (`vis.write_expr`) looking diff --git a/tests/ui/diverging_sub_expression.rs b/tests/ui/diverging_sub_expression.rs index e8f992e6dde..1dd3f3b8bc4 100644 --- a/tests/ui/diverging_sub_expression.rs +++ b/tests/ui/diverging_sub_expression.rs @@ -1,5 +1,6 @@ #![warn(clippy::diverging_sub_expression)] #![allow(clippy::match_same_arms, clippy::overly_complex_bool_expr)] +#![allow(clippy::nonminimal_bool)] #[allow(clippy::empty_loop)] fn diverge() -> ! { loop {} @@ -35,6 +36,9 @@ fn foobar() { 99 => return, _ => true || panic!("boo"), }, + // lint blocks as well + 15 => true || { return; }, + 16 => false || { return; }, _ => true || break, }; } diff --git a/tests/ui/diverging_sub_expression.stderr b/tests/ui/diverging_sub_expression.stderr index 51a3b0d972e..e69de29bb2d 100644 --- a/tests/ui/diverging_sub_expression.stderr +++ b/tests/ui/diverging_sub_expression.stderr @@ -1,40 +0,0 @@ -error: sub-expression diverges - --> $DIR/diverging_sub_expression.rs:19:10 - | -LL | b || diverge(); - | ^^^^^^^^^ - | - = note: `-D clippy::diverging-sub-expression` implied by `-D warnings` - -error: sub-expression diverges - --> $DIR/diverging_sub_expression.rs:20:10 - | -LL | b || A.foo(); - | ^^^^^^^ - -error: sub-expression diverges - --> $DIR/diverging_sub_expression.rs:29:26 - | -LL | 6 => true || return, - | ^^^^^^ - -error: sub-expression diverges - --> $DIR/diverging_sub_expression.rs:30:26 - | -LL | 7 => true || continue, - | ^^^^^^^^ - -error: sub-expression diverges - --> $DIR/diverging_sub_expression.rs:33:26 - | -LL | 3 => true || diverge(), - | ^^^^^^^^^ - -error: sub-expression diverges - --> $DIR/diverging_sub_expression.rs:38:26 - | -LL | _ => true || break, - | ^^^^^ - -error: aborting due to 6 previous errors - From 5825b9e3e29c98ca0b8ae74cc5ece8a05747a416 Mon Sep 17 00:00:00 2001 From: Centri3 <114838443+Centri3@users.noreply.github.com> Date: Mon, 15 May 2023 14:46:24 -0500 Subject: [PATCH 006/310] actually fix it --- .../src/mixed_read_write_in_expression.rs | 18 +++++++++++++++--- tests/ui/diverging_sub_expression.rs | 1 + tests/ui/never_loop.stderr | 10 +++++++++- 3 files changed, 25 insertions(+), 4 deletions(-) diff --git a/clippy_lints/src/mixed_read_write_in_expression.rs b/clippy_lints/src/mixed_read_write_in_expression.rs index 2dfab259915..942453498cd 100644 --- a/clippy_lints/src/mixed_read_write_in_expression.rs +++ b/clippy_lints/src/mixed_read_write_in_expression.rs @@ -1,7 +1,7 @@ use clippy_utils::diagnostics::{span_lint, span_lint_and_note}; use clippy_utils::{get_parent_expr, path_to_local, path_to_local_id}; use if_chain::if_chain; -use rustc_hir::intravisit::{walk_block, walk_expr, Visitor}; +use rustc_hir::intravisit::{walk_expr, Visitor}; use rustc_hir::{BinOpKind, Block, Expr, ExprKind, Guard, HirId, Local, Node, Stmt, StmtKind}; use rustc_lint::{LateContext, LateLintPass}; use rustc_middle::ty; @@ -114,7 +114,7 @@ struct DivergenceVisitor<'a, 'tcx> { impl<'a, 'tcx> DivergenceVisitor<'a, 'tcx> { fn maybe_walk_expr(&mut self, e: &'tcx Expr<'_>) { match e.kind { - ExprKind::Closure { .. } => {}, + ExprKind::Closure(..) | ExprKind::If(..) | ExprKind::Loop(..) => {}, ExprKind::Match(e, arms, _) => { self.visit_expr(e); for arm in arms { @@ -128,6 +128,7 @@ impl<'a, 'tcx> DivergenceVisitor<'a, 'tcx> { _ => walk_expr(self, e), } } + fn report_diverging_sub_expr(&mut self, e: &Expr<'_>) { span_lint(self.cx, DIVERGING_SUB_EXPRESSION, e.span, "sub-expression diverges"); } @@ -136,6 +137,15 @@ impl<'a, 'tcx> DivergenceVisitor<'a, 'tcx> { impl<'a, 'tcx> Visitor<'tcx> for DivergenceVisitor<'a, 'tcx> { fn visit_expr(&mut self, e: &'tcx Expr<'_>) { match e.kind { + // fix #10776 + ExprKind::Block(block, ..) => { + if let Some(stmt) = block.stmts.first() && block.stmts.len() == 1 { + match stmt.kind { + StmtKind::Expr(e) | StmtKind::Semi(e) => self.visit_expr(e), + _ => {}, + } + } + }, ExprKind::Continue(_) | ExprKind::Break(_, _) | ExprKind::Ret(_) => self.report_diverging_sub_expr(e), ExprKind::Call(func, _) => { let typ = self.cx.typeck_results().expr_ty(func); @@ -155,7 +165,6 @@ impl<'a, 'tcx> Visitor<'tcx> for DivergenceVisitor<'a, 'tcx> { self.report_diverging_sub_expr(e); } }, - ExprKind::Block(block, ..) => walk_block(self, block), _ => { // do not lint expressions referencing objects of type `!`, as that required a // diverging expression @@ -164,6 +173,9 @@ impl<'a, 'tcx> Visitor<'tcx> for DivergenceVisitor<'a, 'tcx> { } self.maybe_walk_expr(e); } + fn visit_block(&mut self, _: &'tcx Block<'_>) { + // don't continue over blocks, LateLintPass already does that + } } /// Walks up the AST from the given write expression (`vis.write_expr`) looking diff --git a/tests/ui/diverging_sub_expression.rs b/tests/ui/diverging_sub_expression.rs index 1dd3f3b8bc4..510eca21f71 100644 --- a/tests/ui/diverging_sub_expression.rs +++ b/tests/ui/diverging_sub_expression.rs @@ -22,6 +22,7 @@ fn main() { } #[allow(dead_code, unused_variables)] +#[rustfmt::skip] fn foobar() { loop { let x = match 5 { diff --git a/tests/ui/never_loop.stderr b/tests/ui/never_loop.stderr index 704d448644e..b2eafb345e3 100644 --- a/tests/ui/never_loop.stderr +++ b/tests/ui/never_loop.stderr @@ -126,6 +126,14 @@ LL | | } LL | | } | |_____^ +error: sub-expression diverges + --> $DIR/never_loop.rs:247:17 + | +LL | break 'a; + | ^^^^^^^^ + | + = note: `-D clippy::diverging-sub-expression` implied by `-D warnings` + error: this loop never actually loops --> $DIR/never_loop.rs:278:13 | @@ -139,5 +147,5 @@ help: if you need the first element of the iterator, try writing LL | if let Some(_) = (0..20).next() { | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -error: aborting due to 12 previous errors +error: aborting due to 13 previous errors From 516f4f6aef224137a84f4033935f5e9cb359b273 Mon Sep 17 00:00:00 2001 From: y21 <30553356+y21@users.noreply.github.com> Date: Mon, 22 May 2023 23:52:37 +0200 Subject: [PATCH 007/310] new lint: `explicit_into_iter_fn_arg` --- CHANGELOG.md | 1 + clippy_lints/src/declared_lints.rs | 1 + clippy_lints/src/explicit_into_iter_fn_arg.rs | 144 ++++++++++++++++++ clippy_lints/src/lib.rs | 2 + tests/ui/explicit_into_iter_fn_arg.fixed | 24 +++ tests/ui/explicit_into_iter_fn_arg.rs | 24 +++ tests/ui/explicit_into_iter_fn_arg.stderr | 39 +++++ 7 files changed, 235 insertions(+) create mode 100644 clippy_lints/src/explicit_into_iter_fn_arg.rs create mode 100644 tests/ui/explicit_into_iter_fn_arg.fixed create mode 100644 tests/ui/explicit_into_iter_fn_arg.rs create mode 100644 tests/ui/explicit_into_iter_fn_arg.stderr diff --git a/CHANGELOG.md b/CHANGELOG.md index a2648d9faa6..7a127c08197 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4642,6 +4642,7 @@ Released 2018-09-13 [`explicit_auto_deref`]: https://rust-lang.github.io/rust-clippy/master/index.html#explicit_auto_deref [`explicit_counter_loop`]: https://rust-lang.github.io/rust-clippy/master/index.html#explicit_counter_loop [`explicit_deref_methods`]: https://rust-lang.github.io/rust-clippy/master/index.html#explicit_deref_methods +[`explicit_into_iter_fn_arg`]: https://rust-lang.github.io/rust-clippy/master/index.html#explicit_into_iter_fn_arg [`explicit_into_iter_loop`]: https://rust-lang.github.io/rust-clippy/master/index.html#explicit_into_iter_loop [`explicit_iter_loop`]: https://rust-lang.github.io/rust-clippy/master/index.html#explicit_iter_loop [`explicit_write`]: https://rust-lang.github.io/rust-clippy/master/index.html#explicit_write diff --git a/clippy_lints/src/declared_lints.rs b/clippy_lints/src/declared_lints.rs index 4ade25e1257..fceb6e4b2ae 100644 --- a/clippy_lints/src/declared_lints.rs +++ b/clippy_lints/src/declared_lints.rs @@ -157,6 +157,7 @@ pub(crate) static LINTS: &[&crate::LintInfo] = &[ crate::exhaustive_items::EXHAUSTIVE_ENUMS_INFO, crate::exhaustive_items::EXHAUSTIVE_STRUCTS_INFO, crate::exit::EXIT_INFO, + crate::explicit_into_iter_fn_arg::EXPLICIT_INTO_ITER_FN_ARG_INFO, crate::explicit_write::EXPLICIT_WRITE_INFO, crate::extra_unused_type_parameters::EXTRA_UNUSED_TYPE_PARAMETERS_INFO, crate::fallible_impl_from::FALLIBLE_IMPL_FROM_INFO, diff --git a/clippy_lints/src/explicit_into_iter_fn_arg.rs b/clippy_lints/src/explicit_into_iter_fn_arg.rs new file mode 100644 index 00000000000..007a3f43449 --- /dev/null +++ b/clippy_lints/src/explicit_into_iter_fn_arg.rs @@ -0,0 +1,144 @@ +use clippy_utils::diagnostics::span_lint_and_then; +use clippy_utils::source::snippet; +use clippy_utils::{get_parent_expr, is_trait_method}; +use rustc_errors::Applicability; +use rustc_hir::def_id::DefId; +use rustc_hir::*; +use rustc_lint::{LateContext, LateLintPass}; +use rustc_middle::ty; +use rustc_session::{declare_lint_pass, declare_tool_lint}; +use rustc_span::sym; +use rustc_span::Span; + +declare_clippy_lint! { + /// ### What it does + /// Checks for calls to [`IntoIterator::into_iter`](https://doc.rust-lang.org/stable/std/iter/trait.IntoIterator.html#tymethod.into_iter) + /// in a call argument that accepts `IntoIterator`. + /// + /// ### Why is this bad? + /// If a function has a generic parameter with an `IntoIterator` trait bound, it means that the function + /// will *have* to call `.into_iter()` to get an iterator out of it, thereby making the call to `.into_iter()` + /// at call site redundant. + /// + /// Consider this example: + /// ```rs,ignore + /// fn foo>(iter: T) { + /// let it = iter.into_iter(); + /// ^^^^^^^^^^^^ the function has to call `.into_iter()` to get the iterator + /// } + /// + /// foo(vec![1, 2, 3].into_iter()); + /// ^^^^^^^^^^^^ ... making this `.into_iter()` call redundant. + /// ``` + /// + /// The reason for why calling `.into_iter()` twice (once at call site and again inside of the function) works in the first place + /// is because there is a blanket implementation of `IntoIterator` for all types that implement `Iterator` in the standard library, + /// in which it simply returns itself, effectively making the second call to `.into_iter()` a "no-op": + /// ```rust,ignore + /// impl IntoIterator for I { + /// type Item = I::Item; + /// type IntoIter = I; + /// + /// fn into_iter(self) -> I { + /// self + /// } + /// } + /// ``` + /// + /// ### Example + /// ```rust + /// fn even_sum>(iter: I) -> u32 { + /// iter.into_iter().filter(|&x| x % 2 == 0).sum() + /// } + /// + /// let _ = even_sum(vec![1, 2, 3].into_iter()); + /// ``` + /// Use instead: + /// ```rust + /// fn even_sum>(iter: I) -> u32 { + /// iter.into_iter().filter(|&x| x % 2 == 0).sum() + /// } + /// + /// let _ = even_sum(vec![1, 2, 3]); + /// ``` + #[clippy::version = "1.71.0"] + pub EXPLICIT_INTO_ITER_FN_ARG, + pedantic, + "explicit call to `.into_iter()` in function argument accepting `IntoIterator`" +} +declare_lint_pass!(ExplicitIntoIterFnArg => [EXPLICIT_INTO_ITER_FN_ARG]); + +enum MethodOrFunction { + Method, + Function, +} + +/// Returns the span of the `IntoIterator` trait bound in the function pointed to by `fn_did` +fn into_iter_bound(cx: &LateContext<'_>, fn_did: DefId, param_index: u32) -> Option { + if let Some(into_iter_did) = cx.tcx.get_diagnostic_item(sym::IntoIterator) { + cx.tcx + .predicates_of(fn_did) + .predicates + .iter() + .find_map(|&(ref pred, span)| { + if let ty::PredicateKind::Clause(ty::Clause::Trait(tr)) = pred.kind().skip_binder() + && tr.def_id() == into_iter_did + && tr.self_ty().is_param(param_index) + { + Some(span) + } else { + None + } + }) + } else { + None + } +} + +impl<'tcx> LateLintPass<'tcx> for ExplicitIntoIterFnArg { + fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) { + if expr.span.from_expansion() { + return; + } + + if let ExprKind::MethodCall(name, recv, ..) = expr.kind + && is_trait_method(cx, expr, sym::IntoIterator) + && name.ident.name == sym::into_iter + && let Some(parent_expr) = get_parent_expr(cx, expr) + { + let parent_expr = match parent_expr.kind { + ExprKind::Call(recv, args) if let ExprKind::Path(ref qpath) = recv.kind => { + cx.qpath_res(qpath, recv.hir_id).opt_def_id() + .map(|did| (did, args, MethodOrFunction::Function)) + } + ExprKind::MethodCall(.., args, _) => { + cx.typeck_results().type_dependent_def_id(parent_expr.hir_id) + .map(|did| (did, args, MethodOrFunction::Method)) + } + _ => None, + }; + + if let Some((parent_fn_did, args, kind)) = parent_expr + && let sig = cx.tcx.fn_sig(parent_fn_did).skip_binder().skip_binder() + && let Some(arg_pos) = args.iter().position(|x| x.hir_id == expr.hir_id) + && let Some(&into_iter_param) = sig.inputs().get(match kind { + MethodOrFunction::Function => arg_pos, + MethodOrFunction::Method => arg_pos + 1, // skip self arg + }) + && let ty::Param(param) = into_iter_param.kind() + && let Some(span) = into_iter_bound(cx, parent_fn_did, param.index) + { + let sugg = snippet(cx, recv.span.source_callsite(), "").into_owned(); + span_lint_and_then(cx, EXPLICIT_INTO_ITER_FN_ARG, expr.span, "explicit call to `.into_iter()` in function argument accepting `IntoIterator`", |diag| { + diag.span_suggestion( + expr.span, + "consider removing `.into_iter()`", + sugg, + Applicability::MachineApplicable, + ); + diag.span_note(span, "this parameter accepts any `IntoIterator`, so you don't need to call `.into_iter()`"); + }); + } + } + } +} diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index 10404d51ba5..bfe52e182b2 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -123,6 +123,7 @@ mod eta_reduction; mod excessive_bools; mod exhaustive_items; mod exit; +mod explicit_into_iter_fn_arg; mod explicit_write; mod extra_unused_type_parameters; mod fallible_impl_from; @@ -994,6 +995,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: store.register_early_pass(|| Box::new(ref_patterns::RefPatterns)); store.register_late_pass(|_| Box::new(default_constructed_unit_structs::DefaultConstructedUnitStructs)); store.register_early_pass(|| Box::new(needless_else::NeedlessElse)); + store.register_late_pass(|_| Box::new(explicit_into_iter_fn_arg::ExplicitIntoIterFnArg)); // add lints here, do not remove this comment, it's used in `new_lint` } diff --git a/tests/ui/explicit_into_iter_fn_arg.fixed b/tests/ui/explicit_into_iter_fn_arg.fixed new file mode 100644 index 00000000000..219b60bd051 --- /dev/null +++ b/tests/ui/explicit_into_iter_fn_arg.fixed @@ -0,0 +1,24 @@ +//@run-rustfix + +#![allow(unused)] +#![warn(clippy::explicit_into_iter_fn_arg)] + +fn a(_: T) {} +fn b>(_: T) {} +fn c(_: impl IntoIterator) {} +fn d(_: T) +where + T: IntoIterator, +{ +} +fn e>(_: T) {} +fn f(_: std::vec::IntoIter) {} + +fn main() { + a(vec![1, 2].into_iter()); + b(vec![1, 2]); + c(vec![1, 2]); + d(vec![1, 2]); + e([&1, &2, &3].into_iter().cloned()); + f(vec![1, 2].into_iter()); +} diff --git a/tests/ui/explicit_into_iter_fn_arg.rs b/tests/ui/explicit_into_iter_fn_arg.rs new file mode 100644 index 00000000000..358f4bc661d --- /dev/null +++ b/tests/ui/explicit_into_iter_fn_arg.rs @@ -0,0 +1,24 @@ +//@run-rustfix + +#![allow(unused)] +#![warn(clippy::explicit_into_iter_fn_arg)] + +fn a(_: T) {} +fn b>(_: T) {} +fn c(_: impl IntoIterator) {} +fn d(_: T) +where + T: IntoIterator, +{ +} +fn e>(_: T) {} +fn f(_: std::vec::IntoIter) {} + +fn main() { + a(vec![1, 2].into_iter()); + b(vec![1, 2].into_iter()); + c(vec![1, 2].into_iter()); + d(vec![1, 2].into_iter()); + e([&1, &2, &3].into_iter().cloned()); + f(vec![1, 2].into_iter()); +} diff --git a/tests/ui/explicit_into_iter_fn_arg.stderr b/tests/ui/explicit_into_iter_fn_arg.stderr new file mode 100644 index 00000000000..a0bd81c21ea --- /dev/null +++ b/tests/ui/explicit_into_iter_fn_arg.stderr @@ -0,0 +1,39 @@ +error: explicit call to `.into_iter()` in function argument accepting `IntoIterator` + --> $DIR/explicit_into_iter_fn_arg.rs:19:7 + | +LL | b(vec![1, 2].into_iter()); + | ^^^^^^^^^^^^^^^^^^^^^^ help: consider removing `.into_iter()`: `vec![1, 2]` + | +note: this parameter accepts any `IntoIterator`, so you don't need to call `.into_iter()` + --> $DIR/explicit_into_iter_fn_arg.rs:7:9 + | +LL | fn b>(_: T) {} + | ^^^^^^^^^^^^^^^^^^^^^^^^ + = note: `-D clippy::explicit-into-iter-fn-arg` implied by `-D warnings` + +error: explicit call to `.into_iter()` in function argument accepting `IntoIterator` + --> $DIR/explicit_into_iter_fn_arg.rs:20:7 + | +LL | c(vec![1, 2].into_iter()); + | ^^^^^^^^^^^^^^^^^^^^^^ help: consider removing `.into_iter()`: `vec![1, 2]` + | +note: this parameter accepts any `IntoIterator`, so you don't need to call `.into_iter()` + --> $DIR/explicit_into_iter_fn_arg.rs:8:14 + | +LL | fn c(_: impl IntoIterator) {} + | ^^^^^^^^^^^^^^^^^^^^^^^^ + +error: explicit call to `.into_iter()` in function argument accepting `IntoIterator` + --> $DIR/explicit_into_iter_fn_arg.rs:21:7 + | +LL | d(vec![1, 2].into_iter()); + | ^^^^^^^^^^^^^^^^^^^^^^ help: consider removing `.into_iter()`: `vec![1, 2]` + | +note: this parameter accepts any `IntoIterator`, so you don't need to call `.into_iter()` + --> $DIR/explicit_into_iter_fn_arg.rs:11:8 + | +LL | T: IntoIterator, + | ^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 3 previous errors + From 0181d772a4a9702c3ef2fbe5b1b0bf0d94b8fcd7 Mon Sep 17 00:00:00 2001 From: y21 <30553356+y21@users.noreply.github.com> Date: Tue, 23 May 2023 16:56:13 +0200 Subject: [PATCH 008/310] dogfood --- clippy_lints/src/booleans.rs | 2 +- clippy_lints/src/explicit_into_iter_fn_arg.rs | 2 +- clippy_lints/src/loops/manual_memcpy.rs | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/clippy_lints/src/booleans.rs b/clippy_lints/src/booleans.rs index 455f0df7cd0..a08113bf9e6 100644 --- a/clippy_lints/src/booleans.rs +++ b/clippy_lints/src/booleans.rs @@ -441,7 +441,7 @@ impl<'a, 'tcx> NonminimalBoolVisitor<'a, 'tcx> { diag.span_suggestions( e.span, "try", - suggestions.into_iter(), + suggestions, // nonminimal_bool can produce minimal but // not human readable expressions (#3141) Applicability::Unspecified, diff --git a/clippy_lints/src/explicit_into_iter_fn_arg.rs b/clippy_lints/src/explicit_into_iter_fn_arg.rs index 007a3f43449..a56d72f0dea 100644 --- a/clippy_lints/src/explicit_into_iter_fn_arg.rs +++ b/clippy_lints/src/explicit_into_iter_fn_arg.rs @@ -3,7 +3,7 @@ use clippy_utils::source::snippet; use clippy_utils::{get_parent_expr, is_trait_method}; use rustc_errors::Applicability; use rustc_hir::def_id::DefId; -use rustc_hir::*; +use rustc_hir::{Expr, ExprKind}; use rustc_lint::{LateContext, LateLintPass}; use rustc_middle::ty; use rustc_session::{declare_lint_pass, declare_tool_lint}; diff --git a/clippy_lints/src/loops/manual_memcpy.rs b/clippy_lints/src/loops/manual_memcpy.rs index d4c3f76b864..7d1f8ef29c8 100644 --- a/clippy_lints/src/loops/manual_memcpy.rs +++ b/clippy_lints/src/loops/manual_memcpy.rs @@ -51,7 +51,7 @@ pub(super) fn check<'tcx>( iter_b = Some(get_assignment(body)); } - let assignments = iter_a.into_iter().flatten().chain(iter_b.into_iter()); + let assignments = iter_a.into_iter().flatten().chain(iter_b); let big_sugg = assignments // The only statements in the for loops can be indexed assignments from @@ -402,7 +402,7 @@ fn get_assignments<'a, 'tcx>( StmtKind::Local(..) | StmtKind::Item(..) => None, StmtKind::Expr(e) | StmtKind::Semi(e) => Some(e), }) - .chain((*expr).into_iter()) + .chain(*expr) .filter(move |e| { if let ExprKind::AssignOp(_, place, _) = e.kind { path_to_local(place).map_or(false, |id| { From 6a76101d3a46fb1dc21b2ee3044dfac30e3d9a1d Mon Sep 17 00:00:00 2001 From: y21 <30553356+y21@users.noreply.github.com> Date: Wed, 24 May 2023 15:56:28 +0200 Subject: [PATCH 009/310] update docs, simplify arg->param map, dont lint on chain --- clippy_lints/src/explicit_into_iter_fn_arg.rs | 124 +++++++++--------- tests/ui/explicit_into_iter_fn_arg.fixed | 17 ++- tests/ui/explicit_into_iter_fn_arg.rs | 17 ++- tests/ui/explicit_into_iter_fn_arg.stderr | 6 +- 4 files changed, 90 insertions(+), 74 deletions(-) diff --git a/clippy_lints/src/explicit_into_iter_fn_arg.rs b/clippy_lints/src/explicit_into_iter_fn_arg.rs index a56d72f0dea..ff4144df9b9 100644 --- a/clippy_lints/src/explicit_into_iter_fn_arg.rs +++ b/clippy_lints/src/explicit_into_iter_fn_arg.rs @@ -1,5 +1,5 @@ use clippy_utils::diagnostics::span_lint_and_then; -use clippy_utils::source::snippet; +use clippy_utils::source::snippet_with_applicability; use clippy_utils::{get_parent_expr, is_trait_method}; use rustc_errors::Applicability; use rustc_hir::def_id::DefId; @@ -16,50 +16,26 @@ declare_clippy_lint! { /// in a call argument that accepts `IntoIterator`. /// /// ### Why is this bad? - /// If a function has a generic parameter with an `IntoIterator` trait bound, it means that the function - /// will *have* to call `.into_iter()` to get an iterator out of it, thereby making the call to `.into_iter()` - /// at call site redundant. - /// - /// Consider this example: - /// ```rs,ignore - /// fn foo>(iter: T) { - /// let it = iter.into_iter(); - /// ^^^^^^^^^^^^ the function has to call `.into_iter()` to get the iterator - /// } - /// - /// foo(vec![1, 2, 3].into_iter()); - /// ^^^^^^^^^^^^ ... making this `.into_iter()` call redundant. - /// ``` - /// - /// The reason for why calling `.into_iter()` twice (once at call site and again inside of the function) works in the first place - /// is because there is a blanket implementation of `IntoIterator` for all types that implement `Iterator` in the standard library, - /// in which it simply returns itself, effectively making the second call to `.into_iter()` a "no-op": - /// ```rust,ignore - /// impl IntoIterator for I { - /// type Item = I::Item; - /// type IntoIter = I; - /// - /// fn into_iter(self) -> I { - /// self - /// } - /// } - /// ``` + /// If a generic parameter has an `IntoIterator` bound, there is no need to call `.into_iter()` at call site. + /// Calling `IntoIterator::into_iter()` on a value implies that its type already implements `IntoIterator`, + /// so you can just pass the value as is. /// /// ### Example /// ```rust - /// fn even_sum>(iter: I) -> u32 { + /// fn even_sum>(iter: I) -> i32 { /// iter.into_iter().filter(|&x| x % 2 == 0).sum() /// } /// - /// let _ = even_sum(vec![1, 2, 3].into_iter()); + /// let _ = even_sum([1, 2, 3].into_iter()); + /// // ^^^^^^^^^^^^ redundant. `[i32; 3]` implements `IntoIterator` /// ``` /// Use instead: /// ```rust - /// fn even_sum>(iter: I) -> u32 { + /// fn even_sum>(iter: I) -> i32 { /// iter.into_iter().filter(|&x| x % 2 == 0).sum() /// } /// - /// let _ = even_sum(vec![1, 2, 3]); + /// let _ = even_sum([1, 2, 3]); /// ``` #[clippy::version = "1.71.0"] pub EXPLICIT_INTO_ITER_FN_ARG, @@ -73,23 +49,41 @@ enum MethodOrFunction { Function, } +impl MethodOrFunction { + /// Maps the argument position in `pos` to the parameter position. + /// For methods, `self` is skipped. + fn param_pos(self, pos: usize) -> usize { + match self { + MethodOrFunction::Method => pos + 1, + MethodOrFunction::Function => pos, + } + } +} + /// Returns the span of the `IntoIterator` trait bound in the function pointed to by `fn_did` -fn into_iter_bound(cx: &LateContext<'_>, fn_did: DefId, param_index: u32) -> Option { - if let Some(into_iter_did) = cx.tcx.get_diagnostic_item(sym::IntoIterator) { - cx.tcx - .predicates_of(fn_did) - .predicates - .iter() - .find_map(|&(ref pred, span)| { - if let ty::PredicateKind::Clause(ty::Clause::Trait(tr)) = pred.kind().skip_binder() - && tr.def_id() == into_iter_did - && tr.self_ty().is_param(param_index) - { - Some(span) - } else { - None - } - }) +fn into_iter_bound(cx: &LateContext<'_>, fn_did: DefId, into_iter_did: DefId, param_index: u32) -> Option { + cx.tcx + .predicates_of(fn_did) + .predicates + .iter() + .find_map(|&(ref pred, span)| { + if let ty::PredicateKind::Clause(ty::Clause::Trait(tr)) = pred.kind().skip_binder() + && tr.def_id() == into_iter_did + && tr.self_ty().is_param(param_index) + { + Some(span) + } else { + None + } + }) +} + +fn into_iter_call<'hir>(cx: &LateContext<'_>, expr: &'hir Expr<'hir>) -> Option<&'hir Expr<'hir>> { + if let ExprKind::MethodCall(name, recv, _, _) = expr.kind + && is_trait_method(cx, expr, sym::IntoIterator) + && name.ident.name == sym::into_iter + { + Some(recv) } else { None } @@ -101,40 +95,44 @@ impl<'tcx> LateLintPass<'tcx> for ExplicitIntoIterFnArg { return; } - if let ExprKind::MethodCall(name, recv, ..) = expr.kind - && is_trait_method(cx, expr, sym::IntoIterator) - && name.ident.name == sym::into_iter - && let Some(parent_expr) = get_parent_expr(cx, expr) + if let Some(recv) = into_iter_call(cx, expr) + && let Some(parent) = get_parent_expr(cx, expr) + // Make sure that this is not a chained into_iter call (i.e. `x.into_iter().into_iter()`) + // That case is already covered by `useless_conversion` and we don't want to lint twice + // with two contradicting suggestions. + && into_iter_call(cx, parent).is_none() + && into_iter_call(cx, recv).is_none() + && let Some(into_iter_did) = cx.tcx.get_diagnostic_item(sym::IntoIterator) { - let parent_expr = match parent_expr.kind { + + let parent = match parent.kind { ExprKind::Call(recv, args) if let ExprKind::Path(ref qpath) = recv.kind => { cx.qpath_res(qpath, recv.hir_id).opt_def_id() .map(|did| (did, args, MethodOrFunction::Function)) } ExprKind::MethodCall(.., args, _) => { - cx.typeck_results().type_dependent_def_id(parent_expr.hir_id) + cx.typeck_results().type_dependent_def_id(parent.hir_id) .map(|did| (did, args, MethodOrFunction::Method)) } _ => None, }; - if let Some((parent_fn_did, args, kind)) = parent_expr + if let Some((parent_fn_did, args, kind)) = parent && let sig = cx.tcx.fn_sig(parent_fn_did).skip_binder().skip_binder() && let Some(arg_pos) = args.iter().position(|x| x.hir_id == expr.hir_id) - && let Some(&into_iter_param) = sig.inputs().get(match kind { - MethodOrFunction::Function => arg_pos, - MethodOrFunction::Method => arg_pos + 1, // skip self arg - }) + && let Some(&into_iter_param) = sig.inputs().get(kind.param_pos(arg_pos)) && let ty::Param(param) = into_iter_param.kind() - && let Some(span) = into_iter_bound(cx, parent_fn_did, param.index) + && let Some(span) = into_iter_bound(cx, parent_fn_did, into_iter_did, param.index) { - let sugg = snippet(cx, recv.span.source_callsite(), "").into_owned(); + let mut applicability = Applicability::MachineApplicable; + let sugg = snippet_with_applicability(cx, recv.span.source_callsite(), "", &mut applicability).into_owned(); + span_lint_and_then(cx, EXPLICIT_INTO_ITER_FN_ARG, expr.span, "explicit call to `.into_iter()` in function argument accepting `IntoIterator`", |diag| { diag.span_suggestion( expr.span, "consider removing `.into_iter()`", sugg, - Applicability::MachineApplicable, + applicability, ); diag.span_note(span, "this parameter accepts any `IntoIterator`, so you don't need to call `.into_iter()`"); }); diff --git a/tests/ui/explicit_into_iter_fn_arg.fixed b/tests/ui/explicit_into_iter_fn_arg.fixed index 219b60bd051..9d778faf8e0 100644 --- a/tests/ui/explicit_into_iter_fn_arg.fixed +++ b/tests/ui/explicit_into_iter_fn_arg.fixed @@ -1,6 +1,6 @@ //@run-rustfix -#![allow(unused)] +#![allow(unused, clippy::useless_conversion)] #![warn(clippy::explicit_into_iter_fn_arg)] fn a(_: T) {} @@ -11,7 +11,6 @@ where T: IntoIterator, { } -fn e>(_: T) {} fn f(_: std::vec::IntoIter) {} fn main() { @@ -19,6 +18,16 @@ fn main() { b(vec![1, 2]); c(vec![1, 2]); d(vec![1, 2]); - e([&1, &2, &3].into_iter().cloned()); - f(vec![1, 2].into_iter()); + b([&1, &2, &3].into_iter().cloned()); + + // Don't lint chained `.into_iter().into_iter()` calls. Covered by useless_conversion. + b(vec![1, 2].into_iter().into_iter()); + b(vec![1, 2].into_iter().into_iter().into_iter()); + + macro_rules! macro_generated { + () => { + vec![1, 2].into_iter() + }; + } + b(macro_generated!()); } diff --git a/tests/ui/explicit_into_iter_fn_arg.rs b/tests/ui/explicit_into_iter_fn_arg.rs index 358f4bc661d..1e051fd06ec 100644 --- a/tests/ui/explicit_into_iter_fn_arg.rs +++ b/tests/ui/explicit_into_iter_fn_arg.rs @@ -1,6 +1,6 @@ //@run-rustfix -#![allow(unused)] +#![allow(unused, clippy::useless_conversion)] #![warn(clippy::explicit_into_iter_fn_arg)] fn a(_: T) {} @@ -11,7 +11,6 @@ where T: IntoIterator, { } -fn e>(_: T) {} fn f(_: std::vec::IntoIter) {} fn main() { @@ -19,6 +18,16 @@ fn main() { b(vec![1, 2].into_iter()); c(vec![1, 2].into_iter()); d(vec![1, 2].into_iter()); - e([&1, &2, &3].into_iter().cloned()); - f(vec![1, 2].into_iter()); + b([&1, &2, &3].into_iter().cloned()); + + // Don't lint chained `.into_iter().into_iter()` calls. Covered by useless_conversion. + b(vec![1, 2].into_iter().into_iter()); + b(vec![1, 2].into_iter().into_iter().into_iter()); + + macro_rules! macro_generated { + () => { + vec![1, 2].into_iter() + }; + } + b(macro_generated!()); } diff --git a/tests/ui/explicit_into_iter_fn_arg.stderr b/tests/ui/explicit_into_iter_fn_arg.stderr index a0bd81c21ea..14b95fb097a 100644 --- a/tests/ui/explicit_into_iter_fn_arg.stderr +++ b/tests/ui/explicit_into_iter_fn_arg.stderr @@ -1,5 +1,5 @@ error: explicit call to `.into_iter()` in function argument accepting `IntoIterator` - --> $DIR/explicit_into_iter_fn_arg.rs:19:7 + --> $DIR/explicit_into_iter_fn_arg.rs:18:7 | LL | b(vec![1, 2].into_iter()); | ^^^^^^^^^^^^^^^^^^^^^^ help: consider removing `.into_iter()`: `vec![1, 2]` @@ -12,7 +12,7 @@ LL | fn b>(_: T) {} = note: `-D clippy::explicit-into-iter-fn-arg` implied by `-D warnings` error: explicit call to `.into_iter()` in function argument accepting `IntoIterator` - --> $DIR/explicit_into_iter_fn_arg.rs:20:7 + --> $DIR/explicit_into_iter_fn_arg.rs:19:7 | LL | c(vec![1, 2].into_iter()); | ^^^^^^^^^^^^^^^^^^^^^^ help: consider removing `.into_iter()`: `vec![1, 2]` @@ -24,7 +24,7 @@ LL | fn c(_: impl IntoIterator) {} | ^^^^^^^^^^^^^^^^^^^^^^^^ error: explicit call to `.into_iter()` in function argument accepting `IntoIterator` - --> $DIR/explicit_into_iter_fn_arg.rs:21:7 + --> $DIR/explicit_into_iter_fn_arg.rs:20:7 | LL | d(vec![1, 2].into_iter()); | ^^^^^^^^^^^^^^^^^^^^^^ help: consider removing `.into_iter()`: `vec![1, 2]` From 7f7979f80b9ff1d886701f2efccd72aa9921c9fa Mon Sep 17 00:00:00 2001 From: Centri3 <114838443+Centri3@users.noreply.github.com> Date: Wed, 24 May 2023 10:53:31 -0500 Subject: [PATCH 010/310] emit `unnecessary_cast` on raw pointers as well --- clippy_lints/src/casts/mod.rs | 4 +- clippy_lints/src/casts/unnecessary_cast.rs | 38 +++++++++-- tests/ui/as_ptr_cast_mut.stderr | 16 ++++- tests/ui/cast_slice_different_sizes.rs | 2 +- tests/ui/crashes/ice-1782.rs | 1 + tests/ui/from_raw_with_void_ptr.rs | 1 + tests/ui/from_raw_with_void_ptr.stderr | 20 +++--- tests/ui/transmute_ptr_to_ref.fixed | 2 +- tests/ui/transmute_ptr_to_ref.rs | 2 +- tests/ui/unnecessary_cast.fixed | 14 ++++ tests/ui/unnecessary_cast.rs | 14 ++++ tests/ui/unnecessary_cast.stderr | 76 +++++++++++++--------- 12 files changed, 138 insertions(+), 52 deletions(-) diff --git a/clippy_lints/src/casts/mod.rs b/clippy_lints/src/casts/mod.rs index d62639caca1..bf38aab94a9 100644 --- a/clippy_lints/src/casts/mod.rs +++ b/clippy_lints/src/casts/mod.rs @@ -175,8 +175,8 @@ declare_clippy_lint! { declare_clippy_lint! { /// ### What it does - /// Checks for casts to the same type, casts of int literals to integer types - /// and casts of float literals to float types. + /// Checks for casts to the same type, casts of int literals to integer types, casts of float + /// literals to float types and casts between raw pointers without changing type or constness. /// /// ### Why is this bad? /// It's just unnecessary. diff --git a/clippy_lints/src/casts/unnecessary_cast.rs b/clippy_lints/src/casts/unnecessary_cast.rs index 804ae841100..08ed8a63e1a 100644 --- a/clippy_lints/src/casts/unnecessary_cast.rs +++ b/clippy_lints/src/casts/unnecessary_cast.rs @@ -1,7 +1,7 @@ use clippy_utils::diagnostics::span_lint_and_sugg; use clippy_utils::numeric_literal::NumericLiteral; use clippy_utils::source::snippet_opt; -use clippy_utils::{get_parent_expr, path_to_local}; +use clippy_utils::{get_parent_expr, is_ty_alias, path_to_local}; use if_chain::if_chain; use rustc_ast::{LitFloatType, LitIntType, LitKind}; use rustc_errors::Applicability; @@ -20,6 +20,38 @@ pub(super) fn check<'tcx>( cast_from: Ty<'tcx>, cast_to: Ty<'tcx>, ) -> bool { + let cast_str = snippet_opt(cx, cast_expr.span).unwrap_or_default(); + + if_chain! { + if let ty::RawPtr(..) = cast_from.kind(); + // check both mutability and type are the same + if cast_from.kind() == cast_to.kind(); + if let ExprKind::Cast(_, cast_to_hir) = expr.kind; + then { + if_chain! { + if let TyKind::Path(qpath) = cast_to_hir.kind; + if is_ty_alias(&qpath); + then { + return false; + } + } + + if let TyKind::Infer = cast_to_hir.kind { + return false; + } + + span_lint_and_sugg( + cx, + UNNECESSARY_CAST, + expr.span, + &format!("casting raw pointers to the same type and constness is unnecessary (`{cast_from}` -> `{cast_to}`)"), + "try", + cast_str.clone(), + Applicability::MachineApplicable, + ); + } + } + // skip non-primitive type cast if_chain! { if let ExprKind::Cast(_, cast_to) = expr.kind; @@ -27,12 +59,10 @@ pub(super) fn check<'tcx>( if let Res::PrimTy(_) = path.res; then {} else { - return false + return false; } } - let cast_str = snippet_opt(cx, cast_expr.span).unwrap_or_default(); - if let Some(lit) = get_numeric_literal(cast_expr) { let literal_str = &cast_str; diff --git a/tests/ui/as_ptr_cast_mut.stderr b/tests/ui/as_ptr_cast_mut.stderr index 2189c3d2f85..c45d669fd73 100644 --- a/tests/ui/as_ptr_cast_mut.stderr +++ b/tests/ui/as_ptr_cast_mut.stderr @@ -12,5 +12,19 @@ error: casting the result of `as_ptr` to *mut i8 LL | let _: *mut i8 = string.as_ptr() as *mut _; | ^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace with: `string.as_mut_ptr()` -error: aborting due to 2 previous errors +error: casting raw pointers to the same type and constness is unnecessary (`*mut u8` -> `*mut u8`) + --> $DIR/as_ptr_cast_mut.rs:25:13 + | +LL | let _ = string.as_mut_ptr() as *mut u8; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `string.as_mut_ptr()` + | + = note: `-D clippy::unnecessary-cast` implied by `-D warnings` + +error: casting raw pointers to the same type and constness is unnecessary (`*mut u8` -> `*mut u8`) + --> $DIR/as_ptr_cast_mut.rs:29:13 + | +LL | let _ = nn.as_ptr() as *mut u8; + | ^^^^^^^^^^^^^^^^^^^^^^ help: try: `nn.as_ptr()` + +error: aborting due to 4 previous errors diff --git a/tests/ui/cast_slice_different_sizes.rs b/tests/ui/cast_slice_different_sizes.rs index b77f01883bf..27e03ebb719 100644 --- a/tests/ui/cast_slice_different_sizes.rs +++ b/tests/ui/cast_slice_different_sizes.rs @@ -1,4 +1,4 @@ -#![allow(clippy::let_unit_value)] +#![allow(clippy::let_unit_value, clippy::unnecessary_cast)] fn main() { let x: [i32; 3] = [1_i32, 2, 3]; diff --git a/tests/ui/crashes/ice-1782.rs b/tests/ui/crashes/ice-1782.rs index 81af88962a6..19ab03418ee 100644 --- a/tests/ui/crashes/ice-1782.rs +++ b/tests/ui/crashes/ice-1782.rs @@ -1,4 +1,5 @@ #![allow(dead_code, unused_variables)] +#![allow(clippy::unnecessary_cast)] /// Should not trigger an ICE in `SpanlessEq` / `consts::constant` /// diff --git a/tests/ui/from_raw_with_void_ptr.rs b/tests/ui/from_raw_with_void_ptr.rs index 8484da2415a..95ef6425fad 100644 --- a/tests/ui/from_raw_with_void_ptr.rs +++ b/tests/ui/from_raw_with_void_ptr.rs @@ -1,4 +1,5 @@ #![warn(clippy::from_raw_with_void_ptr)] +#![allow(clippy::unnecessary_cast)] use std::ffi::c_void; use std::rc::Rc; diff --git a/tests/ui/from_raw_with_void_ptr.stderr b/tests/ui/from_raw_with_void_ptr.stderr index 96e4af12ba3..1963d08014b 100644 --- a/tests/ui/from_raw_with_void_ptr.stderr +++ b/tests/ui/from_raw_with_void_ptr.stderr @@ -1,60 +1,60 @@ error: creating a `Box` from a void raw pointer - --> $DIR/from_raw_with_void_ptr.rs:10:22 + --> $DIR/from_raw_with_void_ptr.rs:11:22 | LL | let _ = unsafe { Box::from_raw(ptr) }; | ^^^^^^^^^^^^^^^^^^ | help: cast this to a pointer of the appropriate type - --> $DIR/from_raw_with_void_ptr.rs:10:36 + --> $DIR/from_raw_with_void_ptr.rs:11:36 | LL | let _ = unsafe { Box::from_raw(ptr) }; | ^^^ = note: `-D clippy::from-raw-with-void-ptr` implied by `-D warnings` error: creating a `Rc` from a void raw pointer - --> $DIR/from_raw_with_void_ptr.rs:21:22 + --> $DIR/from_raw_with_void_ptr.rs:22:22 | LL | let _ = unsafe { Rc::from_raw(ptr) }; | ^^^^^^^^^^^^^^^^^ | help: cast this to a pointer of the appropriate type - --> $DIR/from_raw_with_void_ptr.rs:21:35 + --> $DIR/from_raw_with_void_ptr.rs:22:35 | LL | let _ = unsafe { Rc::from_raw(ptr) }; | ^^^ error: creating a `Arc` from a void raw pointer - --> $DIR/from_raw_with_void_ptr.rs:25:22 + --> $DIR/from_raw_with_void_ptr.rs:26:22 | LL | let _ = unsafe { Arc::from_raw(ptr) }; | ^^^^^^^^^^^^^^^^^^ | help: cast this to a pointer of the appropriate type - --> $DIR/from_raw_with_void_ptr.rs:25:36 + --> $DIR/from_raw_with_void_ptr.rs:26:36 | LL | let _ = unsafe { Arc::from_raw(ptr) }; | ^^^ error: creating a `Weak` from a void raw pointer - --> $DIR/from_raw_with_void_ptr.rs:29:22 + --> $DIR/from_raw_with_void_ptr.rs:30:22 | LL | let _ = unsafe { std::rc::Weak::from_raw(ptr) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | help: cast this to a pointer of the appropriate type - --> $DIR/from_raw_with_void_ptr.rs:29:46 + --> $DIR/from_raw_with_void_ptr.rs:30:46 | LL | let _ = unsafe { std::rc::Weak::from_raw(ptr) }; | ^^^ error: creating a `Weak` from a void raw pointer - --> $DIR/from_raw_with_void_ptr.rs:33:22 + --> $DIR/from_raw_with_void_ptr.rs:34:22 | LL | let _ = unsafe { std::sync::Weak::from_raw(ptr) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | help: cast this to a pointer of the appropriate type - --> $DIR/from_raw_with_void_ptr.rs:33:48 + --> $DIR/from_raw_with_void_ptr.rs:34:48 | LL | let _ = unsafe { std::sync::Weak::from_raw(ptr) }; | ^^^ diff --git a/tests/ui/transmute_ptr_to_ref.fixed b/tests/ui/transmute_ptr_to_ref.fixed index 575dadde906..215f0ac1842 100644 --- a/tests/ui/transmute_ptr_to_ref.fixed +++ b/tests/ui/transmute_ptr_to_ref.fixed @@ -1,7 +1,7 @@ //@run-rustfix #![warn(clippy::transmute_ptr_to_ref)] -#![allow(clippy::match_single_binding)] +#![allow(clippy::match_single_binding, clippy::unnecessary_cast)] unsafe fn _ptr_to_ref(p: *const T, m: *mut T, o: *const U, om: *mut U) { let _: &T = &*p; diff --git a/tests/ui/transmute_ptr_to_ref.rs b/tests/ui/transmute_ptr_to_ref.rs index 4238ff80478..3528e137903 100644 --- a/tests/ui/transmute_ptr_to_ref.rs +++ b/tests/ui/transmute_ptr_to_ref.rs @@ -1,7 +1,7 @@ //@run-rustfix #![warn(clippy::transmute_ptr_to_ref)] -#![allow(clippy::match_single_binding)] +#![allow(clippy::match_single_binding, clippy::unnecessary_cast)] unsafe fn _ptr_to_ref(p: *const T, m: *mut T, o: *const U, om: *mut U) { let _: &T = std::mem::transmute(p); diff --git a/tests/ui/unnecessary_cast.fixed b/tests/ui/unnecessary_cast.fixed index bcc231ea7bc..7038a2915cb 100644 --- a/tests/ui/unnecessary_cast.fixed +++ b/tests/ui/unnecessary_cast.fixed @@ -8,6 +8,9 @@ clippy::unnecessary_operation )] +type PtrConstU8 = *const u8; +type PtrMutU8 = *mut u8; + #[rustfmt::skip] fn main() { // Test cast_unnecessary @@ -22,6 +25,17 @@ fn main() { 1_i32; 1_f32; + [1u8, 2].as_ptr(); + [1u8, 2].as_ptr() as *mut u8; + [1u8, 2].as_mut_ptr(); + [1u8, 2].as_mut_ptr() as *const u8; + [1u8, 2].as_ptr() as PtrConstU8; + [1u8, 2].as_ptr() as PtrMutU8; + [1u8, 2].as_mut_ptr() as PtrMutU8; + [1u8, 2].as_mut_ptr() as PtrConstU8; + let _: *const u8 = [1u8, 2].as_ptr() as _; + let _: *mut u8 = [1u8, 2].as_mut_ptr() as _; + // macro version macro_rules! foo { ($a:ident, $b:ident) => { diff --git a/tests/ui/unnecessary_cast.rs b/tests/ui/unnecessary_cast.rs index 282b2f1283e..5e766405809 100644 --- a/tests/ui/unnecessary_cast.rs +++ b/tests/ui/unnecessary_cast.rs @@ -8,6 +8,9 @@ clippy::unnecessary_operation )] +type PtrConstU8 = *const u8; +type PtrMutU8 = *mut u8; + #[rustfmt::skip] fn main() { // Test cast_unnecessary @@ -22,6 +25,17 @@ fn main() { 1_i32 as i32; 1_f32 as f32; + [1u8, 2].as_ptr() as *const u8; + [1u8, 2].as_ptr() as *mut u8; + [1u8, 2].as_mut_ptr() as *mut u8; + [1u8, 2].as_mut_ptr() as *const u8; + [1u8, 2].as_ptr() as PtrConstU8; + [1u8, 2].as_ptr() as PtrMutU8; + [1u8, 2].as_mut_ptr() as PtrMutU8; + [1u8, 2].as_mut_ptr() as PtrConstU8; + let _: *const u8 = [1u8, 2].as_ptr() as _; + let _: *mut u8 = [1u8, 2].as_mut_ptr() as _; + // macro version macro_rules! foo { ($a:ident, $b:ident) => { diff --git a/tests/ui/unnecessary_cast.stderr b/tests/ui/unnecessary_cast.stderr index fcee4ee2a65..077274c2337 100644 --- a/tests/ui/unnecessary_cast.stderr +++ b/tests/ui/unnecessary_cast.stderr @@ -1,5 +1,5 @@ error: casting integer literal to `i32` is unnecessary - --> $DIR/unnecessary_cast.rs:14:5 + --> $DIR/unnecessary_cast.rs:17:5 | LL | 1i32 as i32; | ^^^^^^^^^^^ help: try: `1_i32` @@ -7,184 +7,196 @@ LL | 1i32 as i32; = note: `-D clippy::unnecessary-cast` implied by `-D warnings` error: casting float literal to `f32` is unnecessary - --> $DIR/unnecessary_cast.rs:15:5 + --> $DIR/unnecessary_cast.rs:18:5 | LL | 1f32 as f32; | ^^^^^^^^^^^ help: try: `1_f32` error: casting to the same type is unnecessary (`bool` -> `bool`) - --> $DIR/unnecessary_cast.rs:16:5 + --> $DIR/unnecessary_cast.rs:19:5 | LL | false as bool; | ^^^^^^^^^^^^^ help: try: `false` error: casting integer literal to `i32` is unnecessary - --> $DIR/unnecessary_cast.rs:19:5 + --> $DIR/unnecessary_cast.rs:22:5 | LL | -1_i32 as i32; | ^^^^^^^^^^^^^ help: try: `-1_i32` error: casting integer literal to `i32` is unnecessary - --> $DIR/unnecessary_cast.rs:20:5 + --> $DIR/unnecessary_cast.rs:23:5 | LL | - 1_i32 as i32; | ^^^^^^^^^^^^^^ help: try: `- 1_i32` error: casting float literal to `f32` is unnecessary - --> $DIR/unnecessary_cast.rs:21:5 + --> $DIR/unnecessary_cast.rs:24:5 | LL | -1f32 as f32; | ^^^^^^^^^^^^ help: try: `-1_f32` error: casting integer literal to `i32` is unnecessary - --> $DIR/unnecessary_cast.rs:22:5 + --> $DIR/unnecessary_cast.rs:25:5 | LL | 1_i32 as i32; | ^^^^^^^^^^^^ help: try: `1_i32` error: casting float literal to `f32` is unnecessary - --> $DIR/unnecessary_cast.rs:23:5 + --> $DIR/unnecessary_cast.rs:26:5 | LL | 1_f32 as f32; | ^^^^^^^^^^^^ help: try: `1_f32` +error: casting raw pointers to the same type and constness is unnecessary (`*const u8` -> `*const u8`) + --> $DIR/unnecessary_cast.rs:28:5 + | +LL | [1u8, 2].as_ptr() as *const u8; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `[1u8, 2].as_ptr()` + +error: casting raw pointers to the same type and constness is unnecessary (`*mut u8` -> `*mut u8`) + --> $DIR/unnecessary_cast.rs:30:5 + | +LL | [1u8, 2].as_mut_ptr() as *mut u8; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `[1u8, 2].as_mut_ptr()` + error: casting integer literal to `f32` is unnecessary - --> $DIR/unnecessary_cast.rs:64:9 + --> $DIR/unnecessary_cast.rs:78:9 | LL | 100 as f32; | ^^^^^^^^^^ help: try: `100_f32` error: casting integer literal to `f64` is unnecessary - --> $DIR/unnecessary_cast.rs:65:9 + --> $DIR/unnecessary_cast.rs:79:9 | LL | 100 as f64; | ^^^^^^^^^^ help: try: `100_f64` error: casting integer literal to `f64` is unnecessary - --> $DIR/unnecessary_cast.rs:66:9 + --> $DIR/unnecessary_cast.rs:80:9 | LL | 100_i32 as f64; | ^^^^^^^^^^^^^^ help: try: `100_f64` error: casting integer literal to `f32` is unnecessary - --> $DIR/unnecessary_cast.rs:67:17 + --> $DIR/unnecessary_cast.rs:81:17 | LL | let _ = -100 as f32; | ^^^^^^^^^^^ help: try: `-100_f32` error: casting integer literal to `f64` is unnecessary - --> $DIR/unnecessary_cast.rs:68:17 + --> $DIR/unnecessary_cast.rs:82:17 | LL | let _ = -100 as f64; | ^^^^^^^^^^^ help: try: `-100_f64` error: casting integer literal to `f64` is unnecessary - --> $DIR/unnecessary_cast.rs:69:17 + --> $DIR/unnecessary_cast.rs:83:17 | LL | let _ = -100_i32 as f64; | ^^^^^^^^^^^^^^^ help: try: `-100_f64` error: casting float literal to `f32` is unnecessary - --> $DIR/unnecessary_cast.rs:70:9 + --> $DIR/unnecessary_cast.rs:84:9 | LL | 100. as f32; | ^^^^^^^^^^^ help: try: `100_f32` error: casting float literal to `f64` is unnecessary - --> $DIR/unnecessary_cast.rs:71:9 + --> $DIR/unnecessary_cast.rs:85:9 | LL | 100. as f64; | ^^^^^^^^^^^ help: try: `100_f64` error: casting integer literal to `u32` is unnecessary - --> $DIR/unnecessary_cast.rs:83:9 + --> $DIR/unnecessary_cast.rs:97:9 | LL | 1 as u32; | ^^^^^^^^ help: try: `1_u32` error: casting integer literal to `i32` is unnecessary - --> $DIR/unnecessary_cast.rs:84:9 + --> $DIR/unnecessary_cast.rs:98:9 | LL | 0x10 as i32; | ^^^^^^^^^^^ help: try: `0x10_i32` error: casting integer literal to `usize` is unnecessary - --> $DIR/unnecessary_cast.rs:85:9 + --> $DIR/unnecessary_cast.rs:99:9 | LL | 0b10 as usize; | ^^^^^^^^^^^^^ help: try: `0b10_usize` error: casting integer literal to `u16` is unnecessary - --> $DIR/unnecessary_cast.rs:86:9 + --> $DIR/unnecessary_cast.rs:100:9 | LL | 0o73 as u16; | ^^^^^^^^^^^ help: try: `0o73_u16` error: casting integer literal to `u32` is unnecessary - --> $DIR/unnecessary_cast.rs:87:9 + --> $DIR/unnecessary_cast.rs:101:9 | LL | 1_000_000_000 as u32; | ^^^^^^^^^^^^^^^^^^^^ help: try: `1_000_000_000_u32` error: casting float literal to `f64` is unnecessary - --> $DIR/unnecessary_cast.rs:89:9 + --> $DIR/unnecessary_cast.rs:103:9 | LL | 1.0 as f64; | ^^^^^^^^^^ help: try: `1.0_f64` error: casting float literal to `f32` is unnecessary - --> $DIR/unnecessary_cast.rs:90:9 + --> $DIR/unnecessary_cast.rs:104:9 | LL | 0.5 as f32; | ^^^^^^^^^^ help: try: `0.5_f32` error: casting integer literal to `i32` is unnecessary - --> $DIR/unnecessary_cast.rs:94:17 + --> $DIR/unnecessary_cast.rs:108:17 | LL | let _ = -1 as i32; | ^^^^^^^^^ help: try: `-1_i32` error: casting float literal to `f32` is unnecessary - --> $DIR/unnecessary_cast.rs:95:17 + --> $DIR/unnecessary_cast.rs:109:17 | LL | let _ = -1.0 as f32; | ^^^^^^^^^^^ help: try: `-1.0_f32` error: casting to the same type is unnecessary (`i32` -> `i32`) - --> $DIR/unnecessary_cast.rs:101:18 + --> $DIR/unnecessary_cast.rs:115:18 | LL | let _ = &(x as i32); | ^^^^^^^^^^ help: try: `{ x }` error: casting integer literal to `i32` is unnecessary - --> $DIR/unnecessary_cast.rs:107:22 + --> $DIR/unnecessary_cast.rs:121:22 | LL | let _: i32 = -(1) as i32; | ^^^^^^^^^^^ help: try: `-1_i32` error: casting integer literal to `i64` is unnecessary - --> $DIR/unnecessary_cast.rs:109:22 + --> $DIR/unnecessary_cast.rs:123:22 | LL | let _: i64 = -(1) as i64; | ^^^^^^^^^^^ help: try: `-1_i64` error: casting float literal to `f64` is unnecessary - --> $DIR/unnecessary_cast.rs:116:22 + --> $DIR/unnecessary_cast.rs:130:22 | LL | let _: f64 = (-8.0 as f64).exp(); | ^^^^^^^^^^^^^ help: try: `(-8.0_f64)` error: casting float literal to `f64` is unnecessary - --> $DIR/unnecessary_cast.rs:118:23 + --> $DIR/unnecessary_cast.rs:132:23 | LL | let _: f64 = -(8.0 as f64).exp(); // should suggest `-8.0_f64.exp()` here not to change code behavior | ^^^^^^^^^^^^ help: try: `8.0_f64` error: casting to the same type is unnecessary (`f32` -> `f32`) - --> $DIR/unnecessary_cast.rs:126:20 + --> $DIR/unnecessary_cast.rs:140:20 | LL | let _num = foo() as f32; | ^^^^^^^^^^^^ help: try: `foo()` -error: aborting due to 31 previous errors +error: aborting due to 33 previous errors From 5adb270c8d9aa8d32acbb2a2ba343102d1bb1c76 Mon Sep 17 00:00:00 2001 From: Centri3 <114838443+Centri3@users.noreply.github.com> Date: Wed, 24 May 2023 11:02:35 -0500 Subject: [PATCH 011/310] ok --- tests/ui/as_ptr_cast_mut.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/ui/as_ptr_cast_mut.rs b/tests/ui/as_ptr_cast_mut.rs index 0d1d9258433..9389426238c 100644 --- a/tests/ui/as_ptr_cast_mut.rs +++ b/tests/ui/as_ptr_cast_mut.rs @@ -1,3 +1,4 @@ +//@run-rustfix #![allow(unused)] #![warn(clippy::as_ptr_cast_mut)] #![allow(clippy::wrong_self_convention)] From 94e586e85d8ecc278ed8766ffafdc39d41583b4e Mon Sep 17 00:00:00 2001 From: Centri3 <114838443+Centri3@users.noreply.github.com> Date: Wed, 24 May 2023 11:06:56 -0500 Subject: [PATCH 012/310] actually appease CI I should always run cargo test before committing :sweat_smile: --- tests/ui/as_ptr_cast_mut.rs | 3 +-- tests/ui/as_ptr_cast_mut.stderr | 16 +--------------- 2 files changed, 2 insertions(+), 17 deletions(-) diff --git a/tests/ui/as_ptr_cast_mut.rs b/tests/ui/as_ptr_cast_mut.rs index 9389426238c..7d71947e428 100644 --- a/tests/ui/as_ptr_cast_mut.rs +++ b/tests/ui/as_ptr_cast_mut.rs @@ -1,7 +1,6 @@ -//@run-rustfix #![allow(unused)] #![warn(clippy::as_ptr_cast_mut)] -#![allow(clippy::wrong_self_convention)] +#![allow(clippy::wrong_self_convention, clippy::unnecessary_cast)] struct MutPtrWrapper(Vec); impl MutPtrWrapper { diff --git a/tests/ui/as_ptr_cast_mut.stderr b/tests/ui/as_ptr_cast_mut.stderr index c45d669fd73..2189c3d2f85 100644 --- a/tests/ui/as_ptr_cast_mut.stderr +++ b/tests/ui/as_ptr_cast_mut.stderr @@ -12,19 +12,5 @@ error: casting the result of `as_ptr` to *mut i8 LL | let _: *mut i8 = string.as_ptr() as *mut _; | ^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace with: `string.as_mut_ptr()` -error: casting raw pointers to the same type and constness is unnecessary (`*mut u8` -> `*mut u8`) - --> $DIR/as_ptr_cast_mut.rs:25:13 - | -LL | let _ = string.as_mut_ptr() as *mut u8; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `string.as_mut_ptr()` - | - = note: `-D clippy::unnecessary-cast` implied by `-D warnings` - -error: casting raw pointers to the same type and constness is unnecessary (`*mut u8` -> `*mut u8`) - --> $DIR/as_ptr_cast_mut.rs:29:13 - | -LL | let _ = nn.as_ptr() as *mut u8; - | ^^^^^^^^^^^^^^^^^^^^^^ help: try: `nn.as_ptr()` - -error: aborting due to 4 previous errors +error: aborting due to 2 previous errors From d2de5769a134eb71f3481e93db31aaf0eeba1af7 Mon Sep 17 00:00:00 2001 From: Centri3 <114838443+Centri3@users.noreply.github.com> Date: Thu, 25 May 2023 04:05:13 -0500 Subject: [PATCH 013/310] add generics in test --- tests/ui/unnecessary_cast.fixed | 15 ++++- tests/ui/unnecessary_cast.rs | 15 ++++- tests/ui/unnecessary_cast.stderr | 98 ++++++++++++++++++++------------ 3 files changed, 89 insertions(+), 39 deletions(-) diff --git a/tests/ui/unnecessary_cast.fixed b/tests/ui/unnecessary_cast.fixed index 7038a2915cb..42fcb6ef411 100644 --- a/tests/ui/unnecessary_cast.fixed +++ b/tests/ui/unnecessary_cast.fixed @@ -1,7 +1,7 @@ //@run-rustfix #![warn(clippy::unnecessary_cast)] #![allow( - unused_must_use, + unused, clippy::borrow_as_ptr, clippy::no_effect, clippy::nonstandard_macro_braces, @@ -11,6 +11,14 @@ type PtrConstU8 = *const u8; type PtrMutU8 = *mut u8; +fn owo(ptr: *const T) -> *const T { + ptr +} + +fn uwu(ptr: *const T) -> *const U { + ptr as *const U +} + #[rustfmt::skip] fn main() { // Test cast_unnecessary @@ -25,6 +33,8 @@ fn main() { 1_i32; 1_f32; + let _: *mut u8 = [1u8, 2].as_ptr() as *mut u8; + [1u8, 2].as_ptr(); [1u8, 2].as_ptr() as *mut u8; [1u8, 2].as_mut_ptr(); @@ -36,6 +46,9 @@ fn main() { let _: *const u8 = [1u8, 2].as_ptr() as _; let _: *mut u8 = [1u8, 2].as_mut_ptr() as _; + owo::([1u32].as_ptr()); + uwu::([1u32].as_ptr()); + // macro version macro_rules! foo { ($a:ident, $b:ident) => { diff --git a/tests/ui/unnecessary_cast.rs b/tests/ui/unnecessary_cast.rs index 5e766405809..2daf2e9938f 100644 --- a/tests/ui/unnecessary_cast.rs +++ b/tests/ui/unnecessary_cast.rs @@ -1,7 +1,7 @@ //@run-rustfix #![warn(clippy::unnecessary_cast)] #![allow( - unused_must_use, + unused, clippy::borrow_as_ptr, clippy::no_effect, clippy::nonstandard_macro_braces, @@ -11,6 +11,14 @@ type PtrConstU8 = *const u8; type PtrMutU8 = *mut u8; +fn owo(ptr: *const T) -> *const T { + ptr as *const T +} + +fn uwu(ptr: *const T) -> *const U { + ptr as *const U +} + #[rustfmt::skip] fn main() { // Test cast_unnecessary @@ -25,6 +33,8 @@ fn main() { 1_i32 as i32; 1_f32 as f32; + let _: *mut u8 = [1u8, 2].as_ptr() as *const u8 as *mut u8; + [1u8, 2].as_ptr() as *const u8; [1u8, 2].as_ptr() as *mut u8; [1u8, 2].as_mut_ptr() as *mut u8; @@ -36,6 +46,9 @@ fn main() { let _: *const u8 = [1u8, 2].as_ptr() as _; let _: *mut u8 = [1u8, 2].as_mut_ptr() as _; + owo::([1u32].as_ptr()) as *const u32; + uwu::([1u32].as_ptr()) as *const u8; + // macro version macro_rules! foo { ($a:ident, $b:ident) => { diff --git a/tests/ui/unnecessary_cast.stderr b/tests/ui/unnecessary_cast.stderr index 077274c2337..61e165e2ddd 100644 --- a/tests/ui/unnecessary_cast.stderr +++ b/tests/ui/unnecessary_cast.stderr @@ -1,202 +1,226 @@ -error: casting integer literal to `i32` is unnecessary - --> $DIR/unnecessary_cast.rs:17:5 +error: casting raw pointers to the same type and constness is unnecessary (`*const T` -> `*const T`) + --> $DIR/unnecessary_cast.rs:15:5 | -LL | 1i32 as i32; - | ^^^^^^^^^^^ help: try: `1_i32` +LL | ptr as *const T + | ^^^^^^^^^^^^^^^ help: try: `ptr` | = note: `-D clippy::unnecessary-cast` implied by `-D warnings` +error: casting integer literal to `i32` is unnecessary + --> $DIR/unnecessary_cast.rs:25:5 + | +LL | 1i32 as i32; + | ^^^^^^^^^^^ help: try: `1_i32` + error: casting float literal to `f32` is unnecessary - --> $DIR/unnecessary_cast.rs:18:5 + --> $DIR/unnecessary_cast.rs:26:5 | LL | 1f32 as f32; | ^^^^^^^^^^^ help: try: `1_f32` error: casting to the same type is unnecessary (`bool` -> `bool`) - --> $DIR/unnecessary_cast.rs:19:5 + --> $DIR/unnecessary_cast.rs:27:5 | LL | false as bool; | ^^^^^^^^^^^^^ help: try: `false` error: casting integer literal to `i32` is unnecessary - --> $DIR/unnecessary_cast.rs:22:5 + --> $DIR/unnecessary_cast.rs:30:5 | LL | -1_i32 as i32; | ^^^^^^^^^^^^^ help: try: `-1_i32` error: casting integer literal to `i32` is unnecessary - --> $DIR/unnecessary_cast.rs:23:5 + --> $DIR/unnecessary_cast.rs:31:5 | LL | - 1_i32 as i32; | ^^^^^^^^^^^^^^ help: try: `- 1_i32` error: casting float literal to `f32` is unnecessary - --> $DIR/unnecessary_cast.rs:24:5 + --> $DIR/unnecessary_cast.rs:32:5 | LL | -1f32 as f32; | ^^^^^^^^^^^^ help: try: `-1_f32` error: casting integer literal to `i32` is unnecessary - --> $DIR/unnecessary_cast.rs:25:5 + --> $DIR/unnecessary_cast.rs:33:5 | LL | 1_i32 as i32; | ^^^^^^^^^^^^ help: try: `1_i32` error: casting float literal to `f32` is unnecessary - --> $DIR/unnecessary_cast.rs:26:5 + --> $DIR/unnecessary_cast.rs:34:5 | LL | 1_f32 as f32; | ^^^^^^^^^^^^ help: try: `1_f32` error: casting raw pointers to the same type and constness is unnecessary (`*const u8` -> `*const u8`) - --> $DIR/unnecessary_cast.rs:28:5 + --> $DIR/unnecessary_cast.rs:36:22 + | +LL | let _: *mut u8 = [1u8, 2].as_ptr() as *const u8 as *mut u8; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `[1u8, 2].as_ptr()` + +error: casting raw pointers to the same type and constness is unnecessary (`*const u8` -> `*const u8`) + --> $DIR/unnecessary_cast.rs:38:5 | LL | [1u8, 2].as_ptr() as *const u8; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `[1u8, 2].as_ptr()` error: casting raw pointers to the same type and constness is unnecessary (`*mut u8` -> `*mut u8`) - --> $DIR/unnecessary_cast.rs:30:5 + --> $DIR/unnecessary_cast.rs:40:5 | LL | [1u8, 2].as_mut_ptr() as *mut u8; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `[1u8, 2].as_mut_ptr()` +error: casting raw pointers to the same type and constness is unnecessary (`*const u32` -> `*const u32`) + --> $DIR/unnecessary_cast.rs:49:5 + | +LL | owo::([1u32].as_ptr()) as *const u32; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `owo::([1u32].as_ptr())` + +error: casting raw pointers to the same type and constness is unnecessary (`*const u8` -> `*const u8`) + --> $DIR/unnecessary_cast.rs:50:5 + | +LL | uwu::([1u32].as_ptr()) as *const u8; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `uwu::([1u32].as_ptr())` + error: casting integer literal to `f32` is unnecessary - --> $DIR/unnecessary_cast.rs:78:9 + --> $DIR/unnecessary_cast.rs:91:9 | LL | 100 as f32; | ^^^^^^^^^^ help: try: `100_f32` error: casting integer literal to `f64` is unnecessary - --> $DIR/unnecessary_cast.rs:79:9 + --> $DIR/unnecessary_cast.rs:92:9 | LL | 100 as f64; | ^^^^^^^^^^ help: try: `100_f64` error: casting integer literal to `f64` is unnecessary - --> $DIR/unnecessary_cast.rs:80:9 + --> $DIR/unnecessary_cast.rs:93:9 | LL | 100_i32 as f64; | ^^^^^^^^^^^^^^ help: try: `100_f64` error: casting integer literal to `f32` is unnecessary - --> $DIR/unnecessary_cast.rs:81:17 + --> $DIR/unnecessary_cast.rs:94:17 | LL | let _ = -100 as f32; | ^^^^^^^^^^^ help: try: `-100_f32` error: casting integer literal to `f64` is unnecessary - --> $DIR/unnecessary_cast.rs:82:17 + --> $DIR/unnecessary_cast.rs:95:17 | LL | let _ = -100 as f64; | ^^^^^^^^^^^ help: try: `-100_f64` error: casting integer literal to `f64` is unnecessary - --> $DIR/unnecessary_cast.rs:83:17 + --> $DIR/unnecessary_cast.rs:96:17 | LL | let _ = -100_i32 as f64; | ^^^^^^^^^^^^^^^ help: try: `-100_f64` error: casting float literal to `f32` is unnecessary - --> $DIR/unnecessary_cast.rs:84:9 + --> $DIR/unnecessary_cast.rs:97:9 | LL | 100. as f32; | ^^^^^^^^^^^ help: try: `100_f32` error: casting float literal to `f64` is unnecessary - --> $DIR/unnecessary_cast.rs:85:9 + --> $DIR/unnecessary_cast.rs:98:9 | LL | 100. as f64; | ^^^^^^^^^^^ help: try: `100_f64` error: casting integer literal to `u32` is unnecessary - --> $DIR/unnecessary_cast.rs:97:9 + --> $DIR/unnecessary_cast.rs:110:9 | LL | 1 as u32; | ^^^^^^^^ help: try: `1_u32` error: casting integer literal to `i32` is unnecessary - --> $DIR/unnecessary_cast.rs:98:9 + --> $DIR/unnecessary_cast.rs:111:9 | LL | 0x10 as i32; | ^^^^^^^^^^^ help: try: `0x10_i32` error: casting integer literal to `usize` is unnecessary - --> $DIR/unnecessary_cast.rs:99:9 + --> $DIR/unnecessary_cast.rs:112:9 | LL | 0b10 as usize; | ^^^^^^^^^^^^^ help: try: `0b10_usize` error: casting integer literal to `u16` is unnecessary - --> $DIR/unnecessary_cast.rs:100:9 + --> $DIR/unnecessary_cast.rs:113:9 | LL | 0o73 as u16; | ^^^^^^^^^^^ help: try: `0o73_u16` error: casting integer literal to `u32` is unnecessary - --> $DIR/unnecessary_cast.rs:101:9 + --> $DIR/unnecessary_cast.rs:114:9 | LL | 1_000_000_000 as u32; | ^^^^^^^^^^^^^^^^^^^^ help: try: `1_000_000_000_u32` error: casting float literal to `f64` is unnecessary - --> $DIR/unnecessary_cast.rs:103:9 + --> $DIR/unnecessary_cast.rs:116:9 | LL | 1.0 as f64; | ^^^^^^^^^^ help: try: `1.0_f64` error: casting float literal to `f32` is unnecessary - --> $DIR/unnecessary_cast.rs:104:9 + --> $DIR/unnecessary_cast.rs:117:9 | LL | 0.5 as f32; | ^^^^^^^^^^ help: try: `0.5_f32` error: casting integer literal to `i32` is unnecessary - --> $DIR/unnecessary_cast.rs:108:17 + --> $DIR/unnecessary_cast.rs:121:17 | LL | let _ = -1 as i32; | ^^^^^^^^^ help: try: `-1_i32` error: casting float literal to `f32` is unnecessary - --> $DIR/unnecessary_cast.rs:109:17 + --> $DIR/unnecessary_cast.rs:122:17 | LL | let _ = -1.0 as f32; | ^^^^^^^^^^^ help: try: `-1.0_f32` error: casting to the same type is unnecessary (`i32` -> `i32`) - --> $DIR/unnecessary_cast.rs:115:18 + --> $DIR/unnecessary_cast.rs:128:18 | LL | let _ = &(x as i32); | ^^^^^^^^^^ help: try: `{ x }` error: casting integer literal to `i32` is unnecessary - --> $DIR/unnecessary_cast.rs:121:22 + --> $DIR/unnecessary_cast.rs:134:22 | LL | let _: i32 = -(1) as i32; | ^^^^^^^^^^^ help: try: `-1_i32` error: casting integer literal to `i64` is unnecessary - --> $DIR/unnecessary_cast.rs:123:22 + --> $DIR/unnecessary_cast.rs:136:22 | LL | let _: i64 = -(1) as i64; | ^^^^^^^^^^^ help: try: `-1_i64` error: casting float literal to `f64` is unnecessary - --> $DIR/unnecessary_cast.rs:130:22 + --> $DIR/unnecessary_cast.rs:143:22 | LL | let _: f64 = (-8.0 as f64).exp(); | ^^^^^^^^^^^^^ help: try: `(-8.0_f64)` error: casting float literal to `f64` is unnecessary - --> $DIR/unnecessary_cast.rs:132:23 + --> $DIR/unnecessary_cast.rs:145:23 | LL | let _: f64 = -(8.0 as f64).exp(); // should suggest `-8.0_f64.exp()` here not to change code behavior | ^^^^^^^^^^^^ help: try: `8.0_f64` error: casting to the same type is unnecessary (`f32` -> `f32`) - --> $DIR/unnecessary_cast.rs:140:20 + --> $DIR/unnecessary_cast.rs:153:20 | LL | let _num = foo() as f32; | ^^^^^^^^^^^^ help: try: `foo()` -error: aborting due to 33 previous errors +error: aborting due to 37 previous errors From d7a98f507a7b15c9298c2c7a3056340377008544 Mon Sep 17 00:00:00 2001 From: Centri3 <114838443+Centri3@users.noreply.github.com> Date: Thu, 25 May 2023 04:17:36 -0500 Subject: [PATCH 014/310] also ensure generics with the same type are linted --- tests/ui/unnecessary_cast.fixed | 2 ++ tests/ui/unnecessary_cast.rs | 2 ++ tests/ui/unnecessary_cast.stderr | 54 ++++++++++++++++++-------------- 3 files changed, 34 insertions(+), 24 deletions(-) diff --git a/tests/ui/unnecessary_cast.fixed b/tests/ui/unnecessary_cast.fixed index 42fcb6ef411..0fd49e7c815 100644 --- a/tests/ui/unnecessary_cast.fixed +++ b/tests/ui/unnecessary_cast.fixed @@ -48,6 +48,8 @@ fn main() { owo::([1u32].as_ptr()); uwu::([1u32].as_ptr()); + // this will not lint in the function body even though they have the same type, instead here + uwu::([1u32].as_ptr()); // macro version macro_rules! foo { diff --git a/tests/ui/unnecessary_cast.rs b/tests/ui/unnecessary_cast.rs index 2daf2e9938f..27669492329 100644 --- a/tests/ui/unnecessary_cast.rs +++ b/tests/ui/unnecessary_cast.rs @@ -48,6 +48,8 @@ fn main() { owo::([1u32].as_ptr()) as *const u32; uwu::([1u32].as_ptr()) as *const u8; + // this will not lint in the function body even though they have the same type, instead here + uwu::([1u32].as_ptr()) as *const u32; // macro version macro_rules! foo { diff --git a/tests/ui/unnecessary_cast.stderr b/tests/ui/unnecessary_cast.stderr index 61e165e2ddd..0e511fb4c7a 100644 --- a/tests/ui/unnecessary_cast.stderr +++ b/tests/ui/unnecessary_cast.stderr @@ -84,143 +84,149 @@ error: casting raw pointers to the same type and constness is unnecessary (`*con LL | uwu::([1u32].as_ptr()) as *const u8; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `uwu::([1u32].as_ptr())` +error: casting raw pointers to the same type and constness is unnecessary (`*const u32` -> `*const u32`) + --> $DIR/unnecessary_cast.rs:52:5 + | +LL | uwu::([1u32].as_ptr()) as *const u32; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `uwu::([1u32].as_ptr())` + error: casting integer literal to `f32` is unnecessary - --> $DIR/unnecessary_cast.rs:91:9 + --> $DIR/unnecessary_cast.rs:93:9 | LL | 100 as f32; | ^^^^^^^^^^ help: try: `100_f32` error: casting integer literal to `f64` is unnecessary - --> $DIR/unnecessary_cast.rs:92:9 + --> $DIR/unnecessary_cast.rs:94:9 | LL | 100 as f64; | ^^^^^^^^^^ help: try: `100_f64` error: casting integer literal to `f64` is unnecessary - --> $DIR/unnecessary_cast.rs:93:9 + --> $DIR/unnecessary_cast.rs:95:9 | LL | 100_i32 as f64; | ^^^^^^^^^^^^^^ help: try: `100_f64` error: casting integer literal to `f32` is unnecessary - --> $DIR/unnecessary_cast.rs:94:17 + --> $DIR/unnecessary_cast.rs:96:17 | LL | let _ = -100 as f32; | ^^^^^^^^^^^ help: try: `-100_f32` error: casting integer literal to `f64` is unnecessary - --> $DIR/unnecessary_cast.rs:95:17 + --> $DIR/unnecessary_cast.rs:97:17 | LL | let _ = -100 as f64; | ^^^^^^^^^^^ help: try: `-100_f64` error: casting integer literal to `f64` is unnecessary - --> $DIR/unnecessary_cast.rs:96:17 + --> $DIR/unnecessary_cast.rs:98:17 | LL | let _ = -100_i32 as f64; | ^^^^^^^^^^^^^^^ help: try: `-100_f64` error: casting float literal to `f32` is unnecessary - --> $DIR/unnecessary_cast.rs:97:9 + --> $DIR/unnecessary_cast.rs:99:9 | LL | 100. as f32; | ^^^^^^^^^^^ help: try: `100_f32` error: casting float literal to `f64` is unnecessary - --> $DIR/unnecessary_cast.rs:98:9 + --> $DIR/unnecessary_cast.rs:100:9 | LL | 100. as f64; | ^^^^^^^^^^^ help: try: `100_f64` error: casting integer literal to `u32` is unnecessary - --> $DIR/unnecessary_cast.rs:110:9 + --> $DIR/unnecessary_cast.rs:112:9 | LL | 1 as u32; | ^^^^^^^^ help: try: `1_u32` error: casting integer literal to `i32` is unnecessary - --> $DIR/unnecessary_cast.rs:111:9 + --> $DIR/unnecessary_cast.rs:113:9 | LL | 0x10 as i32; | ^^^^^^^^^^^ help: try: `0x10_i32` error: casting integer literal to `usize` is unnecessary - --> $DIR/unnecessary_cast.rs:112:9 + --> $DIR/unnecessary_cast.rs:114:9 | LL | 0b10 as usize; | ^^^^^^^^^^^^^ help: try: `0b10_usize` error: casting integer literal to `u16` is unnecessary - --> $DIR/unnecessary_cast.rs:113:9 + --> $DIR/unnecessary_cast.rs:115:9 | LL | 0o73 as u16; | ^^^^^^^^^^^ help: try: `0o73_u16` error: casting integer literal to `u32` is unnecessary - --> $DIR/unnecessary_cast.rs:114:9 + --> $DIR/unnecessary_cast.rs:116:9 | LL | 1_000_000_000 as u32; | ^^^^^^^^^^^^^^^^^^^^ help: try: `1_000_000_000_u32` error: casting float literal to `f64` is unnecessary - --> $DIR/unnecessary_cast.rs:116:9 + --> $DIR/unnecessary_cast.rs:118:9 | LL | 1.0 as f64; | ^^^^^^^^^^ help: try: `1.0_f64` error: casting float literal to `f32` is unnecessary - --> $DIR/unnecessary_cast.rs:117:9 + --> $DIR/unnecessary_cast.rs:119:9 | LL | 0.5 as f32; | ^^^^^^^^^^ help: try: `0.5_f32` error: casting integer literal to `i32` is unnecessary - --> $DIR/unnecessary_cast.rs:121:17 + --> $DIR/unnecessary_cast.rs:123:17 | LL | let _ = -1 as i32; | ^^^^^^^^^ help: try: `-1_i32` error: casting float literal to `f32` is unnecessary - --> $DIR/unnecessary_cast.rs:122:17 + --> $DIR/unnecessary_cast.rs:124:17 | LL | let _ = -1.0 as f32; | ^^^^^^^^^^^ help: try: `-1.0_f32` error: casting to the same type is unnecessary (`i32` -> `i32`) - --> $DIR/unnecessary_cast.rs:128:18 + --> $DIR/unnecessary_cast.rs:130:18 | LL | let _ = &(x as i32); | ^^^^^^^^^^ help: try: `{ x }` error: casting integer literal to `i32` is unnecessary - --> $DIR/unnecessary_cast.rs:134:22 + --> $DIR/unnecessary_cast.rs:136:22 | LL | let _: i32 = -(1) as i32; | ^^^^^^^^^^^ help: try: `-1_i32` error: casting integer literal to `i64` is unnecessary - --> $DIR/unnecessary_cast.rs:136:22 + --> $DIR/unnecessary_cast.rs:138:22 | LL | let _: i64 = -(1) as i64; | ^^^^^^^^^^^ help: try: `-1_i64` error: casting float literal to `f64` is unnecessary - --> $DIR/unnecessary_cast.rs:143:22 + --> $DIR/unnecessary_cast.rs:145:22 | LL | let _: f64 = (-8.0 as f64).exp(); | ^^^^^^^^^^^^^ help: try: `(-8.0_f64)` error: casting float literal to `f64` is unnecessary - --> $DIR/unnecessary_cast.rs:145:23 + --> $DIR/unnecessary_cast.rs:147:23 | LL | let _: f64 = -(8.0 as f64).exp(); // should suggest `-8.0_f64.exp()` here not to change code behavior | ^^^^^^^^^^^^ help: try: `8.0_f64` error: casting to the same type is unnecessary (`f32` -> `f32`) - --> $DIR/unnecessary_cast.rs:153:20 + --> $DIR/unnecessary_cast.rs:155:20 | LL | let _num = foo() as f32; | ^^^^^^^^^^^^ help: try: `foo()` -error: aborting due to 37 previous errors +error: aborting due to 38 previous errors From 5be2b27ed6a6b347342e11a46b74e104aac36cd4 Mon Sep 17 00:00:00 2001 From: Brian Hetro Date: Thu, 25 May 2023 21:05:47 -0400 Subject: [PATCH 015/310] Use URL parameters for filter states This retains the settings during browser navigation and allows sharing links with additional configuration. --- util/gh-pages/index.html | 3 +- util/gh-pages/script.js | 174 +++++++++++++++++++++++++++++++++------ 2 files changed, 153 insertions(+), 24 deletions(-) diff --git a/util/gh-pages/index.html b/util/gh-pages/index.html index 8791debad72..1b4677a3c0e 100644 --- a/util/gh-pages/index.html +++ b/util/gh-pages/index.html @@ -517,7 +517,8 @@ Otherwise, have a great day =^.^=

{{lint.id}} - + 📋 diff --git a/util/gh-pages/script.js b/util/gh-pages/script.js index 1c16ecd6b0b..3aaf455e12f 100644 --- a/util/gh-pages/script.js +++ b/util/gh-pages/script.js @@ -24,9 +24,9 @@ target.scrollIntoView(); } - function scrollToLintByURL($scope) { - var removeListener = $scope.$on('ngRepeatFinished', function(ngRepeatFinishedEvent) { - scrollToLint(window.location.hash.slice(1)); + function scrollToLintByURL($scope, $location) { + var removeListener = $scope.$on('ngRepeatFinished', function (ngRepeatFinishedEvent) { + scrollToLint($location.path().substring(1)); removeListener(); }); } @@ -106,10 +106,10 @@ } }; }) - .controller("lintList", function ($scope, $http, $timeout) { + .controller("lintList", function ($scope, $http, $location) { // Level filter var LEVEL_FILTERS_DEFAULT = {allow: true, warn: true, deny: true, none: true}; - $scope.levels = LEVEL_FILTERS_DEFAULT; + $scope.levels = { ...LEVEL_FILTERS_DEFAULT }; $scope.byLevels = function (lint) { return $scope.levels[lint.level]; }; @@ -146,6 +146,137 @@ "=": {enabled: false, minorVersion: null }, }; + // Map the versionFilters to the query parameters in a way that is easier to work with in a URL + const versionFilterKeyMap = { + "≥": "gte", + "≤": "lte", + "=": "eq" + }; + const reverseVersionFilterKeyMap = Object.fromEntries( + Object.entries(versionFilterKeyMap).map(([key, value]) => [value, key]) + ); + + // loadFromURLParameters retrieves filter settings from the URL parameters and assigns them + // to corresponding $scope variables. + function loadFromURLParameters() { + // Extract parameters from URL + const urlParameters = $location.search(); + + // Define a helper function that assigns URL parameters to a provided scope variable + const handleParameter = (parameter, scopeVariable) => { + if (urlParameters[parameter]) { + const items = urlParameters[parameter].split(','); + for (const key in scopeVariable) { + if (scopeVariable.hasOwnProperty(key)) { + scopeVariable[key] = items.includes(key); + } + } + } + }; + + handleParameter('levels', $scope.levels); + handleParameter('groups', $scope.groups); + + // Handle 'versions' parameter separately because it needs additional processing + if (urlParameters.versions) { + const versionFilters = urlParameters.versions.split(','); + for (const versionFilter of versionFilters) { + const [key, minorVersion] = versionFilter.split(':'); + const parsedMinorVersion = parseInt(minorVersion); + + // Map the key from the URL parameter to its original form + const originalKey = reverseVersionFilterKeyMap[key]; + + if (originalKey in $scope.versionFilters && !isNaN(parsedMinorVersion)) { + $scope.versionFilters[originalKey].enabled = true; + $scope.versionFilters[originalKey].minorVersion = parsedMinorVersion; + } + } + } + + // Load the search parameter from the URL path + const searchParameter = $location.path().substring(1); // Remove the leading slash + if (searchParameter) { + $scope.search = searchParameter; + $scope.open[searchParameter] = true; + scrollToLintByURL($scope, $location); + } + + // If there are any filters in the URL, mark that the filters have been changed + if (urlParameters.levels || urlParameters.groups || urlParameters.versions) { + $scope.filtersChanged = true; + } + } + + // updateURLParameter updates the URL parameter with the given key to the given value + function updateURLParameter(filterObj, urlKey, processFilter = filter => filter) { + const parameter = Object.keys(filterObj) + .filter(filter => filterObj[filter]) + .map(processFilter) + .filter(Boolean) // Filters out any falsy values, including null + .join(','); + + $location.search(urlKey, parameter || null); + } + + // updateVersionURLParameter updates the version URL parameter with the given version filters + function updateVersionURLParameter(versionFilters) { + updateURLParameter( + versionFilters, + 'versions', + versionFilter => versionFilters[versionFilter].enabled && versionFilters[versionFilter].minorVersion != null + ? `${versionFilterKeyMap[versionFilter]}:${versionFilters[versionFilter].minorVersion}` + : null + ); + } + + // updateAllURLParameters updates all the URL parameters with the current filter settings + function updateAllURLParameters() { + updateURLParameter($scope.levels, 'levels'); + updateURLParameter($scope.groups, 'groups'); + updateVersionURLParameter($scope.versionFilters); + } + + // Add $watches to automatically update URL parameters when the data changes + $scope.$watch('levels', function (newVal, oldVal) { + if (newVal !== oldVal) { + $scope.filtersChanged = true; + updateURLParameter(newVal, 'levels'); + } + }, true); + + $scope.$watch('groups', function (newVal, oldVal) { + if (newVal !== oldVal) { + $scope.filtersChanged = true; + updateURLParameter(newVal, 'groups'); + } + }, true); + + $scope.$watch('versionFilters', function (newVal, oldVal) { + if (newVal !== oldVal) { + $scope.filtersChanged = true; + updateVersionURLParameter(newVal); + } + }, true); + + $scope.$watch('search', function (newVal, oldVal) { + if (newVal !== oldVal) { + $location.path(newVal); + } + }); + + // Watch for changes in the URL path and update the search and lint display + $scope.$watch(function () { + return $location.path(); + }, function (newPath) { + const searchParameter = newPath.substring(1); + if ($scope.search !== searchParameter) { + $scope.search = searchParameter; + $scope.open[searchParameter] = true; + scrollToLintByURL($scope, $location); + } + }); + $scope.selectTheme = function (theme) { setTheme(theme, true); } @@ -272,6 +403,16 @@ return true; } + // Show details for one lint + $scope.openLint = function (lint) { + $scope.open[lint.id] = true; + $location.path(lint.id); + if ($scope.filtersChanged) { + updateAllURLParameters(); + $scope.filtersChanged = false; + } + }; + $scope.copyToClipboard = function (lint) { const clipboard = document.getElementById("clipboard-" + lint.id); if (clipboard) { @@ -296,14 +437,13 @@ // Get data $scope.open = {}; $scope.loading = true; + $scope.filtersChanged = false; + // This will be used to jump into the source code of the version that this documentation is for. $scope.docVersion = window.location.pathname.split('/')[2] || "master"; - if (window.location.hash.length > 1) { - $scope.search = window.location.hash.slice(1); - $scope.open[window.location.hash.slice(1)] = true; - scrollToLintByURL($scope); - } + // Set up the filters from the URL parameters before we start loading the data + loadFromURLParameters(); $http.get('./lints.json') .success(function (data) { @@ -315,7 +455,7 @@ selectGroup($scope, selectedGroup.toLowerCase()); } - scrollToLintByURL($scope); + scrollToLintByURL($scope, $location); setTimeout(function () { var el = document.getElementById('filter-input'); @@ -326,18 +466,6 @@ $scope.error = data; $scope.loading = false; }); - - window.addEventListener('hashchange', function () { - // trigger re-render - $timeout(function () { - $scope.levels = LEVEL_FILTERS_DEFAULT; - $scope.search = window.location.hash.slice(1); - $scope.open[window.location.hash.slice(1)] = true; - - scrollToLintByURL($scope); - }); - return true; - }, false); }); })(); From 7c1bca4be8974e3e1ff694fec06747aa53fdf337 Mon Sep 17 00:00:00 2001 From: Brian Hetro Date: Fri, 26 May 2023 20:24:29 -0400 Subject: [PATCH 016/310] Handle back/forward when using URL parameters for filter states --- util/gh-pages/script.js | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/util/gh-pages/script.js b/util/gh-pages/script.js index 3aaf455e12f..868b63a27df 100644 --- a/util/gh-pages/script.js +++ b/util/gh-pages/script.js @@ -163,7 +163,7 @@ const urlParameters = $location.search(); // Define a helper function that assigns URL parameters to a provided scope variable - const handleParameter = (parameter, scopeVariable) => { + const handleParameter = (parameter, scopeVariable, defaultValues) => { if (urlParameters[parameter]) { const items = urlParameters[parameter].split(','); for (const key in scopeVariable) { @@ -171,11 +171,17 @@ scopeVariable[key] = items.includes(key); } } + } else if (defaultValues) { + for (const key in defaultValues) { + if (scopeVariable.hasOwnProperty(key)) { + scopeVariable[key] = defaultValues[key]; + } + } } }; - handleParameter('levels', $scope.levels); - handleParameter('groups', $scope.groups); + handleParameter('levels', $scope.levels, LEVEL_FILTERS_DEFAULT); + handleParameter('groups', $scope.groups, GROUPS_FILTER_DEFAULT); // Handle 'versions' parameter separately because it needs additional processing if (urlParameters.versions) { @@ -277,6 +283,12 @@ } }); + $scope.$watch(function () { + return $location.search(); + }, function (newParameters) { + loadFromURLParameters(); + }); + $scope.selectTheme = function (theme) { setTheme(theme, true); } From a865d8432c89fa442e046e22c6439f2483ff9d4c Mon Sep 17 00:00:00 2001 From: Brian Hetro Date: Sat, 27 May 2023 13:50:56 -0400 Subject: [PATCH 017/310] Clippy Lints page - Delay updating of the URL in response to search input Update on blur, enter keypress, and a debounced delay of 1000 ms. This keeps the URL updated, but not distractingly so. --- util/gh-pages/index.html | 6 ++++-- util/gh-pages/script.js | 29 ++++++++++++++++++++++------- 2 files changed, 26 insertions(+), 9 deletions(-) diff --git a/util/gh-pages/index.html b/util/gh-pages/index.html index 1b4677a3c0e..99e211654d1 100644 --- a/util/gh-pages/index.html +++ b/util/gh-pages/index.html @@ -501,9 +501,11 @@ Otherwise, have a great day =^.^=
- + - diff --git a/util/gh-pages/script.js b/util/gh-pages/script.js index 868b63a27df..fd32225dabc 100644 --- a/util/gh-pages/script.js +++ b/util/gh-pages/script.js @@ -106,7 +106,7 @@ } }; }) - .controller("lintList", function ($scope, $http, $location) { + .controller("lintList", function ($scope, $http, $location, $timeout) { // Level filter var LEVEL_FILTERS_DEFAULT = {allow: true, warn: true, deny: true, none: true}; $scope.levels = { ...LEVEL_FILTERS_DEFAULT }; @@ -265,12 +265,6 @@ } }, true); - $scope.$watch('search', function (newVal, oldVal) { - if (newVal !== oldVal) { - $location.path(newVal); - } - }); - // Watch for changes in the URL path and update the search and lint display $scope.$watch(function () { return $location.path(); @@ -283,12 +277,33 @@ } }); + let debounceTimeout; + $scope.$watch('search', function (newVal, oldVal) { + if (newVal !== oldVal) { + if (debounceTimeout) { + $timeout.cancel(debounceTimeout); + } + + debounceTimeout = $timeout(function () { + $location.path(newVal); + }, 1000); + } + }); + $scope.$watch(function () { return $location.search(); }, function (newParameters) { loadFromURLParameters(); }); + $scope.updatePath = function () { + if (debounceTimeout) { + $timeout.cancel(debounceTimeout); + } + + $location.path($scope.search); + } + $scope.selectTheme = function (theme) { setTheme(theme, true); } From f2e6a99a08c86821da6219e3662c868dc1665266 Mon Sep 17 00:00:00 2001 From: Brian Hetro Date: Sat, 27 May 2023 18:40:20 -0400 Subject: [PATCH 018/310] Clippy Lints page - Do not show groups in URL parameters if reset to defaults --- util/gh-pages/script.js | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/util/gh-pages/script.js b/util/gh-pages/script.js index fd32225dabc..bd4293662a0 100644 --- a/util/gh-pages/script.js +++ b/util/gh-pages/script.js @@ -156,6 +156,10 @@ Object.entries(versionFilterKeyMap).map(([key, value]) => [value, key]) ); + // An internal URL change occurs when we are modifying the URL parameters in a way + // that should not reload parameters from the URL + let internalURLChange = false; + // loadFromURLParameters retrieves filter settings from the URL parameters and assigns them // to corresponding $scope variables. function loadFromURLParameters() { @@ -266,9 +270,7 @@ }, true); // Watch for changes in the URL path and update the search and lint display - $scope.$watch(function () { - return $location.path(); - }, function (newPath) { + $scope.$watch($location.path, function (newPath) { const searchParameter = newPath.substring(1); if ($scope.search !== searchParameter) { $scope.search = searchParameter; @@ -290,10 +292,11 @@ } }); - $scope.$watch(function () { - return $location.search(); - }, function (newParameters) { - loadFromURLParameters(); + $scope.$watch($location.search, function (newParameters) { + if (!internalURLChange) { + loadFromURLParameters(); + } + internalURLChange = false; }); $scope.updatePath = function () { @@ -331,6 +334,8 @@ for (const [key, value] of Object.entries(GROUPS_FILTER_DEFAULT)) { groups[key] = value; } + internalURLChange = true; + $location.search('groups', null); }; $scope.selectedValuesCount = function (obj) { From c10876e6c569ec33c4e4c9db14ffec46435e0300 Mon Sep 17 00:00:00 2001 From: Alex Macleod Date: Sun, 28 May 2023 21:50:08 +0000 Subject: [PATCH 019/310] from_over_into: Show suggestions for non-Self expanded paths --- clippy_lints/src/from_over_into.rs | 3 ++- tests/ui/from_over_into.fixed | 9 +++++++++ tests/ui/from_over_into.rs | 9 +++++++++ tests/ui/from_over_into.stderr | 18 ++++++++++++++++-- tests/ui/from_over_into_unfixable.rs | 6 +++--- 5 files changed, 39 insertions(+), 6 deletions(-) diff --git a/clippy_lints/src/from_over_into.rs b/clippy_lints/src/from_over_into.rs index 10ce2a0f0c7..eb967e3f95e 100644 --- a/clippy_lints/src/from_over_into.rs +++ b/clippy_lints/src/from_over_into.rs @@ -134,9 +134,10 @@ impl<'a, 'tcx> Visitor<'tcx> for SelfFinder<'a, 'tcx> { kw::SelfUpper => self.upper.push(segment.ident.span), _ => continue, } + + self.invalid |= segment.ident.span.from_expansion(); } - self.invalid |= path.span.from_expansion(); if !self.invalid { walk_path(self, path); } diff --git a/tests/ui/from_over_into.fixed b/tests/ui/from_over_into.fixed index d18f9387565..00895e594f6 100644 --- a/tests/ui/from_over_into.fixed +++ b/tests/ui/from_over_into.fixed @@ -60,6 +60,15 @@ impl From for A { } } +struct PathInExpansion; + +impl From for String { + fn from(val: PathInExpansion) -> Self { + // non self/Self paths in expansions are fine + panic!() + } +} + #[clippy::msrv = "1.40"] fn msrv_1_40() { struct FromOverInto(Vec); diff --git a/tests/ui/from_over_into.rs b/tests/ui/from_over_into.rs index de8ff0b06bd..7f8c76693fd 100644 --- a/tests/ui/from_over_into.rs +++ b/tests/ui/from_over_into.rs @@ -60,6 +60,15 @@ impl From for A { } } +struct PathInExpansion; + +impl Into for PathInExpansion { + fn into(self) -> String { + // non self/Self paths in expansions are fine + panic!() + } +} + #[clippy::msrv = "1.40"] fn msrv_1_40() { struct FromOverInto(Vec); diff --git a/tests/ui/from_over_into.stderr b/tests/ui/from_over_into.stderr index 6039f86fe67..498b00de5ad 100644 --- a/tests/ui/from_over_into.stderr +++ b/tests/ui/from_over_into.stderr @@ -59,7 +59,21 @@ LL ~ val.0 | error: an implementation of `From` is preferred since it gives you `Into<_>` for free where the reverse isn't true - --> $DIR/from_over_into.rs:78:5 + --> $DIR/from_over_into.rs:65:1 + | +LL | impl Into for PathInExpansion { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = 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` implementation with `From` + | +LL ~ impl From for String { +LL ~ fn from(val: PathInExpansion) -> Self { + | + +error: an implementation of `From` is preferred since it gives you `Into<_>` for free where the reverse isn't true + --> $DIR/from_over_into.rs:87:5 | LL | impl Into> for Vec { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -71,5 +85,5 @@ LL ~ fn from(val: Vec) -> Self { LL ~ FromOverInto(val) | -error: aborting due to 5 previous errors +error: aborting due to 6 previous errors diff --git a/tests/ui/from_over_into_unfixable.rs b/tests/ui/from_over_into_unfixable.rs index 3b280b7488a..7303b805673 100644 --- a/tests/ui/from_over_into_unfixable.rs +++ b/tests/ui/from_over_into_unfixable.rs @@ -3,14 +3,14 @@ struct InMacro(String); macro_rules! in_macro { - ($e:ident) => { - $e + () => { + Self::new() }; } impl Into for String { fn into(self) -> InMacro { - InMacro(in_macro!(self)) + InMacro(in_macro!()) } } From de1f410018b6ec176a5584896ce017ab3f3edf91 Mon Sep 17 00:00:00 2001 From: y21 <30553356+y21@users.noreply.github.com> Date: Tue, 30 May 2023 22:32:26 +0200 Subject: [PATCH 020/310] merge `explicit_into_iter_fn_arg` into `useless_conversion` --- CHANGELOG.md | 1 - clippy_lints/src/declared_lints.rs | 1 - clippy_lints/src/explicit_into_iter_fn_arg.rs | 142 ------------------ clippy_lints/src/lib.rs | 2 - clippy_lints/src/useless_conversion.rs | 121 ++++++++++++++- tests/ui/explicit_into_iter_fn_arg.fixed | 33 ---- tests/ui/explicit_into_iter_fn_arg.rs | 33 ---- tests/ui/explicit_into_iter_fn_arg.stderr | 39 ----- tests/ui/useless_conversion.fixed | 29 ++++ tests/ui/useless_conversion.rs | 29 ++++ tests/ui/useless_conversion.stderr | 62 +++++++- 11 files changed, 234 insertions(+), 258 deletions(-) delete mode 100644 clippy_lints/src/explicit_into_iter_fn_arg.rs delete mode 100644 tests/ui/explicit_into_iter_fn_arg.fixed delete mode 100644 tests/ui/explicit_into_iter_fn_arg.rs delete mode 100644 tests/ui/explicit_into_iter_fn_arg.stderr diff --git a/CHANGELOG.md b/CHANGELOG.md index 7a127c08197..a2648d9faa6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4642,7 +4642,6 @@ Released 2018-09-13 [`explicit_auto_deref`]: https://rust-lang.github.io/rust-clippy/master/index.html#explicit_auto_deref [`explicit_counter_loop`]: https://rust-lang.github.io/rust-clippy/master/index.html#explicit_counter_loop [`explicit_deref_methods`]: https://rust-lang.github.io/rust-clippy/master/index.html#explicit_deref_methods -[`explicit_into_iter_fn_arg`]: https://rust-lang.github.io/rust-clippy/master/index.html#explicit_into_iter_fn_arg [`explicit_into_iter_loop`]: https://rust-lang.github.io/rust-clippy/master/index.html#explicit_into_iter_loop [`explicit_iter_loop`]: https://rust-lang.github.io/rust-clippy/master/index.html#explicit_iter_loop [`explicit_write`]: https://rust-lang.github.io/rust-clippy/master/index.html#explicit_write diff --git a/clippy_lints/src/declared_lints.rs b/clippy_lints/src/declared_lints.rs index fceb6e4b2ae..4ade25e1257 100644 --- a/clippy_lints/src/declared_lints.rs +++ b/clippy_lints/src/declared_lints.rs @@ -157,7 +157,6 @@ pub(crate) static LINTS: &[&crate::LintInfo] = &[ crate::exhaustive_items::EXHAUSTIVE_ENUMS_INFO, crate::exhaustive_items::EXHAUSTIVE_STRUCTS_INFO, crate::exit::EXIT_INFO, - crate::explicit_into_iter_fn_arg::EXPLICIT_INTO_ITER_FN_ARG_INFO, crate::explicit_write::EXPLICIT_WRITE_INFO, crate::extra_unused_type_parameters::EXTRA_UNUSED_TYPE_PARAMETERS_INFO, crate::fallible_impl_from::FALLIBLE_IMPL_FROM_INFO, diff --git a/clippy_lints/src/explicit_into_iter_fn_arg.rs b/clippy_lints/src/explicit_into_iter_fn_arg.rs deleted file mode 100644 index ff4144df9b9..00000000000 --- a/clippy_lints/src/explicit_into_iter_fn_arg.rs +++ /dev/null @@ -1,142 +0,0 @@ -use clippy_utils::diagnostics::span_lint_and_then; -use clippy_utils::source::snippet_with_applicability; -use clippy_utils::{get_parent_expr, is_trait_method}; -use rustc_errors::Applicability; -use rustc_hir::def_id::DefId; -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::sym; -use rustc_span::Span; - -declare_clippy_lint! { - /// ### What it does - /// Checks for calls to [`IntoIterator::into_iter`](https://doc.rust-lang.org/stable/std/iter/trait.IntoIterator.html#tymethod.into_iter) - /// in a call argument that accepts `IntoIterator`. - /// - /// ### Why is this bad? - /// If a generic parameter has an `IntoIterator` bound, there is no need to call `.into_iter()` at call site. - /// Calling `IntoIterator::into_iter()` on a value implies that its type already implements `IntoIterator`, - /// so you can just pass the value as is. - /// - /// ### Example - /// ```rust - /// fn even_sum>(iter: I) -> i32 { - /// iter.into_iter().filter(|&x| x % 2 == 0).sum() - /// } - /// - /// let _ = even_sum([1, 2, 3].into_iter()); - /// // ^^^^^^^^^^^^ redundant. `[i32; 3]` implements `IntoIterator` - /// ``` - /// Use instead: - /// ```rust - /// fn even_sum>(iter: I) -> i32 { - /// iter.into_iter().filter(|&x| x % 2 == 0).sum() - /// } - /// - /// let _ = even_sum([1, 2, 3]); - /// ``` - #[clippy::version = "1.71.0"] - pub EXPLICIT_INTO_ITER_FN_ARG, - pedantic, - "explicit call to `.into_iter()` in function argument accepting `IntoIterator`" -} -declare_lint_pass!(ExplicitIntoIterFnArg => [EXPLICIT_INTO_ITER_FN_ARG]); - -enum MethodOrFunction { - Method, - Function, -} - -impl MethodOrFunction { - /// Maps the argument position in `pos` to the parameter position. - /// For methods, `self` is skipped. - fn param_pos(self, pos: usize) -> usize { - match self { - MethodOrFunction::Method => pos + 1, - MethodOrFunction::Function => pos, - } - } -} - -/// Returns the span of the `IntoIterator` trait bound in the function pointed to by `fn_did` -fn into_iter_bound(cx: &LateContext<'_>, fn_did: DefId, into_iter_did: DefId, param_index: u32) -> Option { - cx.tcx - .predicates_of(fn_did) - .predicates - .iter() - .find_map(|&(ref pred, span)| { - if let ty::PredicateKind::Clause(ty::Clause::Trait(tr)) = pred.kind().skip_binder() - && tr.def_id() == into_iter_did - && tr.self_ty().is_param(param_index) - { - Some(span) - } else { - None - } - }) -} - -fn into_iter_call<'hir>(cx: &LateContext<'_>, expr: &'hir Expr<'hir>) -> Option<&'hir Expr<'hir>> { - if let ExprKind::MethodCall(name, recv, _, _) = expr.kind - && is_trait_method(cx, expr, sym::IntoIterator) - && name.ident.name == sym::into_iter - { - Some(recv) - } else { - None - } -} - -impl<'tcx> LateLintPass<'tcx> for ExplicitIntoIterFnArg { - fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) { - if expr.span.from_expansion() { - return; - } - - if let Some(recv) = into_iter_call(cx, expr) - && let Some(parent) = get_parent_expr(cx, expr) - // Make sure that this is not a chained into_iter call (i.e. `x.into_iter().into_iter()`) - // That case is already covered by `useless_conversion` and we don't want to lint twice - // with two contradicting suggestions. - && into_iter_call(cx, parent).is_none() - && into_iter_call(cx, recv).is_none() - && let Some(into_iter_did) = cx.tcx.get_diagnostic_item(sym::IntoIterator) - { - - let parent = match parent.kind { - ExprKind::Call(recv, args) if let ExprKind::Path(ref qpath) = recv.kind => { - cx.qpath_res(qpath, recv.hir_id).opt_def_id() - .map(|did| (did, args, MethodOrFunction::Function)) - } - ExprKind::MethodCall(.., args, _) => { - cx.typeck_results().type_dependent_def_id(parent.hir_id) - .map(|did| (did, args, MethodOrFunction::Method)) - } - _ => None, - }; - - if let Some((parent_fn_did, args, kind)) = parent - && let sig = cx.tcx.fn_sig(parent_fn_did).skip_binder().skip_binder() - && let Some(arg_pos) = args.iter().position(|x| x.hir_id == expr.hir_id) - && let Some(&into_iter_param) = sig.inputs().get(kind.param_pos(arg_pos)) - && let ty::Param(param) = into_iter_param.kind() - && let Some(span) = into_iter_bound(cx, parent_fn_did, into_iter_did, param.index) - { - let mut applicability = Applicability::MachineApplicable; - let sugg = snippet_with_applicability(cx, recv.span.source_callsite(), "", &mut applicability).into_owned(); - - span_lint_and_then(cx, EXPLICIT_INTO_ITER_FN_ARG, expr.span, "explicit call to `.into_iter()` in function argument accepting `IntoIterator`", |diag| { - diag.span_suggestion( - expr.span, - "consider removing `.into_iter()`", - sugg, - applicability, - ); - diag.span_note(span, "this parameter accepts any `IntoIterator`, so you don't need to call `.into_iter()`"); - }); - } - } - } -} diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index bfe52e182b2..10404d51ba5 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -123,7 +123,6 @@ mod eta_reduction; mod excessive_bools; mod exhaustive_items; mod exit; -mod explicit_into_iter_fn_arg; mod explicit_write; mod extra_unused_type_parameters; mod fallible_impl_from; @@ -995,7 +994,6 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: store.register_early_pass(|| Box::new(ref_patterns::RefPatterns)); store.register_late_pass(|_| Box::new(default_constructed_unit_structs::DefaultConstructedUnitStructs)); store.register_early_pass(|| Box::new(needless_else::NeedlessElse)); - store.register_late_pass(|_| Box::new(explicit_into_iter_fn_arg::ExplicitIntoIterFnArg)); // add lints here, do not remove this comment, it's used in `new_lint` } diff --git a/clippy_lints/src/useless_conversion.rs b/clippy_lints/src/useless_conversion.rs index 28c3fc859e3..6f1e9d5f9de 100644 --- a/clippy_lints/src/useless_conversion.rs +++ b/clippy_lints/src/useless_conversion.rs @@ -1,16 +1,17 @@ -use clippy_utils::diagnostics::{span_lint_and_help, span_lint_and_sugg}; +use clippy_utils::diagnostics::{span_lint_and_help, span_lint_and_sugg, span_lint_and_then}; use clippy_utils::is_ty_alias; -use clippy_utils::source::{snippet, snippet_with_context}; +use clippy_utils::source::{snippet, snippet_with_applicability, snippet_with_context}; use clippy_utils::sugg::Sugg; use clippy_utils::ty::{is_copy, is_type_diagnostic_item, same_type_and_consts}; use clippy_utils::{get_parent_expr, is_trait_method, match_def_path, path_to_local, paths}; use if_chain::if_chain; use rustc_errors::Applicability; +use rustc_hir::def_id::DefId; use rustc_hir::{BindingAnnotation, Expr, ExprKind, HirId, MatchSource, Node, PatKind}; use rustc_lint::{LateContext, LateLintPass}; use rustc_middle::ty; use rustc_session::{declare_tool_lint, impl_lint_pass}; -use rustc_span::sym; +use rustc_span::{sym, Span}; declare_clippy_lint! { /// ### What it does @@ -43,6 +44,65 @@ pub struct UselessConversion { impl_lint_pass!(UselessConversion => [USELESS_CONVERSION]); +enum MethodOrFunction { + Method, + Function, +} + +impl MethodOrFunction { + /// Maps the argument position in `pos` to the parameter position. + /// For methods, `self` is skipped. + fn param_pos(self, pos: usize) -> usize { + match self { + MethodOrFunction::Method => pos + 1, + MethodOrFunction::Function => pos, + } + } +} + +/// Returns the span of the `IntoIterator` trait bound in the function pointed to by `fn_did` +fn into_iter_bound(cx: &LateContext<'_>, fn_did: DefId, into_iter_did: DefId, param_index: u32) -> Option { + cx.tcx + .predicates_of(fn_did) + .predicates + .iter() + .find_map(|&(ref pred, span)| { + if let ty::PredicateKind::Clause(ty::Clause::Trait(tr)) = pred.kind().skip_binder() + && tr.def_id() == into_iter_did + && tr.self_ty().is_param(param_index) + { + Some(span) + } else { + None + } + }) +} + +/// Extracts the receiver of a `.into_iter()` method call. +fn into_iter_call<'hir>(cx: &LateContext<'_>, expr: &'hir Expr<'hir>) -> Option<&'hir Expr<'hir>> { + if let ExprKind::MethodCall(name, recv, _, _) = expr.kind + && is_trait_method(cx, expr, sym::IntoIterator) + && name.ident.name == sym::into_iter + { + Some(recv) + } else { + None + } +} + +/// Same as [`into_iter_call`], but tries to look for the innermost `.into_iter()` call, e.g.: +/// `foo.into_iter().into_iter()` +/// ^^^ we want this expression +fn into_iter_deep_call<'hir>(cx: &LateContext<'_>, mut expr: &'hir Expr<'hir>) -> Option<&'hir Expr<'hir>> { + loop { + if let Some(recv) = into_iter_call(cx, expr) { + expr = recv; + } else { + return Some(expr); + } + } +} + #[expect(clippy::too_many_lines)] impl<'tcx> LateLintPass<'tcx> for UselessConversion { fn check_expr(&mut self, cx: &LateContext<'tcx>, e: &'tcx Expr<'_>) { @@ -82,9 +142,58 @@ impl<'tcx> LateLintPass<'tcx> for UselessConversion { ); } } - if is_trait_method(cx, e, sym::IntoIterator) && name.ident.name == sym::into_iter { - if get_parent_expr(cx, e).is_some() && - let Some(id) = path_to_local(recv) && + if let Some(into_iter_recv) = into_iter_call(cx, e) + // Make sure that there is no parent expression, or if there is, make sure it's not a `.into_iter()` call. + // The reason for that is that we only want to lint once (the outermost call) + // in cases like `foo.into_iter().into_iter()` + && get_parent_expr(cx, e) + .and_then(|parent| into_iter_call(cx, parent)) + .is_none() + { + if let Some(parent) = get_parent_expr(cx, e) { + let parent_fn = match parent.kind { + ExprKind::Call(recv, args) if let ExprKind::Path(ref qpath) = recv.kind => { + cx.qpath_res(qpath, recv.hir_id).opt_def_id() + .map(|did| (did, args, MethodOrFunction::Function)) + } + ExprKind::MethodCall(.., args, _) => { + cx.typeck_results().type_dependent_def_id(parent.hir_id) + .map(|did| (did, args, MethodOrFunction::Method)) + } + _ => None, + }; + + if let Some((parent_fn_did, args, kind)) = parent_fn + && let Some(into_iter_did) = cx.tcx.get_diagnostic_item(sym::IntoIterator) + && let sig = cx.tcx.fn_sig(parent_fn_did).skip_binder().skip_binder() + && let Some(arg_pos) = args.iter().position(|x| x.hir_id == e.hir_id) + && let Some(&into_iter_param) = sig.inputs().get(kind.param_pos(arg_pos)) + && let ty::Param(param) = into_iter_param.kind() + && let Some(span) = into_iter_bound(cx, parent_fn_did, into_iter_did, param.index) + // Get the "innermost" `.into_iter()` call, e.g. given this expression: + // `foo.into_iter().into_iter()` + // ^^^ + // We want this span + && let Some(into_iter_recv) = into_iter_deep_call(cx, into_iter_recv) + { + let mut applicability = Applicability::MachineApplicable; + let sugg = snippet_with_applicability(cx, into_iter_recv.span.source_callsite(), "", &mut applicability).into_owned(); + span_lint_and_then(cx, USELESS_CONVERSION, e.span, "explicit call to `.into_iter()` in function argument accepting `IntoIterator`", |diag| { + diag.span_suggestion( + e.span, + "consider removing `.into_iter()`", + sugg, + applicability, + ); + diag.span_note(span, "this parameter accepts any `IntoIterator`, so you don't need to call `.into_iter()`"); + }); + + // Early return to avoid linting again with contradicting suggestions + return; + } + } + + if let Some(id) = path_to_local(recv) && let Node::Pat(pat) = cx.tcx.hir().get(id) && let PatKind::Binding(ann, ..) = pat.kind && ann != BindingAnnotation::MUT diff --git a/tests/ui/explicit_into_iter_fn_arg.fixed b/tests/ui/explicit_into_iter_fn_arg.fixed deleted file mode 100644 index 9d778faf8e0..00000000000 --- a/tests/ui/explicit_into_iter_fn_arg.fixed +++ /dev/null @@ -1,33 +0,0 @@ -//@run-rustfix - -#![allow(unused, clippy::useless_conversion)] -#![warn(clippy::explicit_into_iter_fn_arg)] - -fn a(_: T) {} -fn b>(_: T) {} -fn c(_: impl IntoIterator) {} -fn d(_: T) -where - T: IntoIterator, -{ -} -fn f(_: std::vec::IntoIter) {} - -fn main() { - a(vec![1, 2].into_iter()); - b(vec![1, 2]); - c(vec![1, 2]); - d(vec![1, 2]); - b([&1, &2, &3].into_iter().cloned()); - - // Don't lint chained `.into_iter().into_iter()` calls. Covered by useless_conversion. - b(vec![1, 2].into_iter().into_iter()); - b(vec![1, 2].into_iter().into_iter().into_iter()); - - macro_rules! macro_generated { - () => { - vec![1, 2].into_iter() - }; - } - b(macro_generated!()); -} diff --git a/tests/ui/explicit_into_iter_fn_arg.rs b/tests/ui/explicit_into_iter_fn_arg.rs deleted file mode 100644 index 1e051fd06ec..00000000000 --- a/tests/ui/explicit_into_iter_fn_arg.rs +++ /dev/null @@ -1,33 +0,0 @@ -//@run-rustfix - -#![allow(unused, clippy::useless_conversion)] -#![warn(clippy::explicit_into_iter_fn_arg)] - -fn a(_: T) {} -fn b>(_: T) {} -fn c(_: impl IntoIterator) {} -fn d(_: T) -where - T: IntoIterator, -{ -} -fn f(_: std::vec::IntoIter) {} - -fn main() { - a(vec![1, 2].into_iter()); - b(vec![1, 2].into_iter()); - c(vec![1, 2].into_iter()); - d(vec![1, 2].into_iter()); - b([&1, &2, &3].into_iter().cloned()); - - // Don't lint chained `.into_iter().into_iter()` calls. Covered by useless_conversion. - b(vec![1, 2].into_iter().into_iter()); - b(vec![1, 2].into_iter().into_iter().into_iter()); - - macro_rules! macro_generated { - () => { - vec![1, 2].into_iter() - }; - } - b(macro_generated!()); -} diff --git a/tests/ui/explicit_into_iter_fn_arg.stderr b/tests/ui/explicit_into_iter_fn_arg.stderr deleted file mode 100644 index 14b95fb097a..00000000000 --- a/tests/ui/explicit_into_iter_fn_arg.stderr +++ /dev/null @@ -1,39 +0,0 @@ -error: explicit call to `.into_iter()` in function argument accepting `IntoIterator` - --> $DIR/explicit_into_iter_fn_arg.rs:18:7 - | -LL | b(vec![1, 2].into_iter()); - | ^^^^^^^^^^^^^^^^^^^^^^ help: consider removing `.into_iter()`: `vec![1, 2]` - | -note: this parameter accepts any `IntoIterator`, so you don't need to call `.into_iter()` - --> $DIR/explicit_into_iter_fn_arg.rs:7:9 - | -LL | fn b>(_: T) {} - | ^^^^^^^^^^^^^^^^^^^^^^^^ - = note: `-D clippy::explicit-into-iter-fn-arg` implied by `-D warnings` - -error: explicit call to `.into_iter()` in function argument accepting `IntoIterator` - --> $DIR/explicit_into_iter_fn_arg.rs:19:7 - | -LL | c(vec![1, 2].into_iter()); - | ^^^^^^^^^^^^^^^^^^^^^^ help: consider removing `.into_iter()`: `vec![1, 2]` - | -note: this parameter accepts any `IntoIterator`, so you don't need to call `.into_iter()` - --> $DIR/explicit_into_iter_fn_arg.rs:8:14 - | -LL | fn c(_: impl IntoIterator) {} - | ^^^^^^^^^^^^^^^^^^^^^^^^ - -error: explicit call to `.into_iter()` in function argument accepting `IntoIterator` - --> $DIR/explicit_into_iter_fn_arg.rs:20:7 - | -LL | d(vec![1, 2].into_iter()); - | ^^^^^^^^^^^^^^^^^^^^^^ help: consider removing `.into_iter()`: `vec![1, 2]` - | -note: this parameter accepts any `IntoIterator`, so you don't need to call `.into_iter()` - --> $DIR/explicit_into_iter_fn_arg.rs:11:8 - | -LL | T: IntoIterator, - | ^^^^^^^^^^^^^^^^^^^^^^^^ - -error: aborting due to 3 previous errors - diff --git a/tests/ui/useless_conversion.fixed b/tests/ui/useless_conversion.fixed index c16caa38fe9..e9563b8a60a 100644 --- a/tests/ui/useless_conversion.fixed +++ b/tests/ui/useless_conversion.fixed @@ -155,6 +155,35 @@ fn main() { let _ = vec![s4, s4, s4].into_iter(); } +#[allow(dead_code)] +fn explicit_into_iter_fn_arg() { + fn a(_: T) {} + fn b>(_: T) {} + fn c(_: impl IntoIterator) {} + fn d(_: T) + where + T: IntoIterator, + { + } + fn f(_: std::vec::IntoIter) {} + + a(vec![1, 2].into_iter()); + b(vec![1, 2]); + c(vec![1, 2]); + d(vec![1, 2]); + b([&1, &2, &3].into_iter().cloned()); + + b(vec![1, 2]); + b(vec![1, 2]); + + macro_rules! macro_generated { + () => { + vec![1, 2].into_iter() + }; + } + b(macro_generated!()); +} + #[derive(Copy, Clone)] struct Foo; diff --git a/tests/ui/useless_conversion.rs b/tests/ui/useless_conversion.rs index c75a2bce4ca..c2f4e3117d2 100644 --- a/tests/ui/useless_conversion.rs +++ b/tests/ui/useless_conversion.rs @@ -155,6 +155,35 @@ fn main() { let _ = vec![s4, s4, s4].into_iter().into_iter(); } +#[allow(dead_code)] +fn explicit_into_iter_fn_arg() { + fn a(_: T) {} + fn b>(_: T) {} + fn c(_: impl IntoIterator) {} + fn d(_: T) + where + T: IntoIterator, + { + } + fn f(_: std::vec::IntoIter) {} + + a(vec![1, 2].into_iter()); + b(vec![1, 2].into_iter()); + c(vec![1, 2].into_iter()); + d(vec![1, 2].into_iter()); + b([&1, &2, &3].into_iter().cloned()); + + b(vec![1, 2].into_iter().into_iter()); + b(vec![1, 2].into_iter().into_iter().into_iter()); + + macro_rules! macro_generated { + () => { + vec![1, 2].into_iter() + }; + } + b(macro_generated!()); +} + #[derive(Copy, Clone)] struct Foo; diff --git a/tests/ui/useless_conversion.stderr b/tests/ui/useless_conversion.stderr index 4dca3aac533..68f38faab59 100644 --- a/tests/ui/useless_conversion.stderr +++ b/tests/ui/useless_conversion.stderr @@ -118,5 +118,65 @@ error: useless conversion to the same type: `std::vec::IntoIter>` LL | let _ = vec![s4, s4, s4].into_iter().into_iter(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider removing `.into_iter()`: `vec![s4, s4, s4].into_iter()` -error: aborting due to 19 previous errors +error: explicit call to `.into_iter()` in function argument accepting `IntoIterator` + --> $DIR/useless_conversion.rs:171:7 + | +LL | b(vec![1, 2].into_iter()); + | ^^^^^^^^^^^^^^^^^^^^^^ help: consider removing `.into_iter()`: `vec![1, 2]` + | +note: this parameter accepts any `IntoIterator`, so you don't need to call `.into_iter()` + --> $DIR/useless_conversion.rs:161:13 + | +LL | fn b>(_: T) {} + | ^^^^^^^^^^^^^^^^^^^^^^^^ + +error: explicit call to `.into_iter()` in function argument accepting `IntoIterator` + --> $DIR/useless_conversion.rs:172:7 + | +LL | c(vec![1, 2].into_iter()); + | ^^^^^^^^^^^^^^^^^^^^^^ help: consider removing `.into_iter()`: `vec![1, 2]` + | +note: this parameter accepts any `IntoIterator`, so you don't need to call `.into_iter()` + --> $DIR/useless_conversion.rs:162:18 + | +LL | fn c(_: impl IntoIterator) {} + | ^^^^^^^^^^^^^^^^^^^^^^^^ + +error: explicit call to `.into_iter()` in function argument accepting `IntoIterator` + --> $DIR/useless_conversion.rs:173:7 + | +LL | d(vec![1, 2].into_iter()); + | ^^^^^^^^^^^^^^^^^^^^^^ help: consider removing `.into_iter()`: `vec![1, 2]` + | +note: this parameter accepts any `IntoIterator`, so you don't need to call `.into_iter()` + --> $DIR/useless_conversion.rs:165:12 + | +LL | T: IntoIterator, + | ^^^^^^^^^^^^^^^^^^^^^^^^ + +error: explicit call to `.into_iter()` in function argument accepting `IntoIterator` + --> $DIR/useless_conversion.rs:176:7 + | +LL | b(vec![1, 2].into_iter().into_iter()); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider removing `.into_iter()`: `vec![1, 2]` + | +note: this parameter accepts any `IntoIterator`, so you don't need to call `.into_iter()` + --> $DIR/useless_conversion.rs:161:13 + | +LL | fn b>(_: T) {} + | ^^^^^^^^^^^^^^^^^^^^^^^^ + +error: explicit call to `.into_iter()` in function argument accepting `IntoIterator` + --> $DIR/useless_conversion.rs:177:7 + | +LL | b(vec![1, 2].into_iter().into_iter().into_iter()); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider removing `.into_iter()`: `vec![1, 2]` + | +note: this parameter accepts any `IntoIterator`, so you don't need to call `.into_iter()` + --> $DIR/useless_conversion.rs:161:13 + | +LL | fn b>(_: T) {} + | ^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 24 previous errors From d816eba09d4ca01ae6a3576de6db3ee415214d03 Mon Sep 17 00:00:00 2001 From: y21 <30553356+y21@users.noreply.github.com> Date: Tue, 30 May 2023 22:32:47 +0200 Subject: [PATCH 021/310] fix new failing proc macro tests --- tests/ui/auxiliary/proc_macro_derive.rs | 110 +++++++++++------------- 1 file changed, 49 insertions(+), 61 deletions(-) diff --git a/tests/ui/auxiliary/proc_macro_derive.rs b/tests/ui/auxiliary/proc_macro_derive.rs index 5a924ca1830..5ea86a9ff37 100644 --- a/tests/ui/auxiliary/proc_macro_derive.rs +++ b/tests/ui/auxiliary/proc_macro_derive.rs @@ -90,70 +90,58 @@ 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(), - ) + >::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(), + ]) } #[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(), - ) + >::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(), + ]) } From d4b388eb43719543aaa9680f5aa03b69d024ea38 Mon Sep 17 00:00:00 2001 From: MarcusGrass Date: Wed, 31 May 2023 17:46:05 +0200 Subject: [PATCH 022/310] Add from_over_into replace for type in `Self` reference --- clippy_lints/src/from_over_into.rs | 75 +++++++++++++++++++++++++++++- tests/ui/from_over_into.fixed | 10 ++++ tests/ui/from_over_into.rs | 10 ++++ tests/ui/from_over_into.stderr | 15 +++++- 4 files changed, 108 insertions(+), 2 deletions(-) diff --git a/clippy_lints/src/from_over_into.rs b/clippy_lints/src/from_over_into.rs index 10ce2a0f0c7..e725fb26c22 100644 --- a/clippy_lints/src/from_over_into.rs +++ b/clippy_lints/src/from_over_into.rs @@ -163,7 +163,8 @@ fn convert_to_from( let PatKind::Binding(.., self_ident, None) = input.pat.kind else { return None }; let from = snippet_opt(cx, self_ty.span)?; - let into = snippet_opt(cx, target_ty.span)?; + // If Self is used, it refers to `self_ty`, which is now out `from` snippet + let into = replace_self(&snippet_opt(cx, target_ty.span)?, &from); let mut suggestions = vec![ // impl Into for U -> impl From for U @@ -212,3 +213,75 @@ fn convert_to_from( Some(suggestions) } + +fn replace_self(input: &str, replace_with: &str) -> String { + const SELF: &str = "Self"; + let mut chunks = input.split(SELF).peekable(); + if let Some(first) = chunks.next() { + let mut last_ended_with_break = false; + // Heuristic, we're making a guess that the expansion probably doesn't exceed `input.len() * 2` + let mut output = String::with_capacity(input.len() * 2); + if first.is_empty() || first.ends_with(word_break) { + last_ended_with_break = true; + } + output.push_str(first); + while let Some(val) = chunks.next() { + let is_last = chunks.peek().is_none(); + if last_ended_with_break && is_last && val.is_empty() { + output.push_str(replace_with); + break; + } + let this_starts_with_break = val.starts_with(word_break); + let this_ends_with_break = val.ends_with(word_break); + if this_starts_with_break && last_ended_with_break { + output.push_str(replace_with); + } else { + output.push_str(SELF); + } + output.push_str(val); + last_ended_with_break = this_ends_with_break; + } + output + } else { + input.to_string() + } +} + +#[inline] +fn word_break(ch: char) -> bool { + !ch.is_alphanumeric() +} + +#[cfg(test)] +mod tests { + use crate::from_over_into::replace_self; + + #[test] + fn replace_doesnt_touch_coincidental_self() { + let input = "impl Into for String {"; + assert_eq!(input, &replace_self(input, "T")); + } + + #[test] + fn replace_replaces_self() { + let input = "impl Into for String {"; + assert_eq!("impl Into for String {", &replace_self(input, "String")); + } + #[test] + fn replace_replaces_self_many() { + let input = "impl Into>> for Self {"; + assert_eq!( + "impl Into>> for String {", + &replace_self(input, "String") + ); + } + + #[test] + fn replace_replaces_self_many_starts_ends_self() { + let input = "Self impl Into>> for Self"; + assert_eq!( + "String impl Into>> for String", + &replace_self(input, "String") + ); + } +} diff --git a/tests/ui/from_over_into.fixed b/tests/ui/from_over_into.fixed index d18f9387565..f1333bb39a8 100644 --- a/tests/ui/from_over_into.fixed +++ b/tests/ui/from_over_into.fixed @@ -88,4 +88,14 @@ impl Into for IntoOpaque { fn into(self) -> Opaque {} } +pub struct Lval(T); + +pub struct Rval(T); + +impl From> for Rval> { + fn from(val: Lval) -> Self { + Rval(val) + } +} + fn main() {} diff --git a/tests/ui/from_over_into.rs b/tests/ui/from_over_into.rs index de8ff0b06bd..4fb91971db9 100644 --- a/tests/ui/from_over_into.rs +++ b/tests/ui/from_over_into.rs @@ -88,4 +88,14 @@ impl Into for IntoOpaque { fn into(self) -> Opaque {} } +pub struct Lval(T); + +pub struct Rval(T); + +impl Into> for Lval { + fn into(self) -> Rval { + Rval(self) + } +} + fn main() {} diff --git a/tests/ui/from_over_into.stderr b/tests/ui/from_over_into.stderr index 6039f86fe67..c514bb6146c 100644 --- a/tests/ui/from_over_into.stderr +++ b/tests/ui/from_over_into.stderr @@ -71,5 +71,18 @@ LL ~ fn from(val: Vec) -> Self { LL ~ FromOverInto(val) | -error: aborting due to 5 previous errors +error: an implementation of `From` is preferred since it gives you `Into<_>` for free where the reverse isn't true + --> $DIR/from_over_into.rs:95:1 + | +LL | impl Into> for Lval { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: replace the `Into` implementation with `From>` + | +LL ~ impl From> for Rval> { +LL ~ fn from(val: Lval) -> Self { +LL ~ Rval(val) + | + +error: aborting due to 6 previous errors From 3ab6aeefb15dd82d21c41265cd441e0cea21c6b0 Mon Sep 17 00:00:00 2001 From: Centri3 <114838443+Centri3@users.noreply.github.com> Date: Thu, 25 May 2023 08:02:57 -0500 Subject: [PATCH 023/310] `to_xx_bytes` implemented, `from_xx_bytes` todo Mentioned in #10765 --- CHANGELOG.md | 3 + clippy_lints/src/declared_lints.rs | 3 + clippy_lints/src/endian_bytes.rs | 138 ++++ clippy_lints/src/lib.rs | 2 + tests/ui/endian_bytes.rs | 163 ++++ tests/ui/endian_bytes.stderr | 1152 ++++++++++++++++++++++++++++ 6 files changed, 1461 insertions(+) create mode 100644 clippy_lints/src/endian_bytes.rs create mode 100644 tests/ui/endian_bytes.rs create mode 100644 tests/ui/endian_bytes.stderr diff --git a/CHANGELOG.md b/CHANGELOG.md index 8b609b47d81..bfb52854634 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4641,6 +4641,7 @@ Released 2018-09-13 [`await_holding_lock`]: https://rust-lang.github.io/rust-clippy/master/index.html#await_holding_lock [`await_holding_refcell_ref`]: https://rust-lang.github.io/rust-clippy/master/index.html#await_holding_refcell_ref [`bad_bit_mask`]: https://rust-lang.github.io/rust-clippy/master/index.html#bad_bit_mask +[`big_endian_bytes`]: https://rust-lang.github.io/rust-clippy/master/index.html#big_endian_bytes [`bind_instead_of_map`]: https://rust-lang.github.io/rust-clippy/master/index.html#bind_instead_of_map [`blacklisted_name`]: https://rust-lang.github.io/rust-clippy/master/index.html#blacklisted_name [`blanket_clippy_restriction_lints`]: https://rust-lang.github.io/rust-clippy/master/index.html#blanket_clippy_restriction_lints @@ -4811,6 +4812,7 @@ Released 2018-09-13 [`get_first`]: https://rust-lang.github.io/rust-clippy/master/index.html#get_first [`get_last_with_len`]: https://rust-lang.github.io/rust-clippy/master/index.html#get_last_with_len [`get_unwrap`]: https://rust-lang.github.io/rust-clippy/master/index.html#get_unwrap +[`host_endian_bytes`]: https://rust-lang.github.io/rust-clippy/master/index.html#host_endian_bytes [`identity_conversion`]: https://rust-lang.github.io/rust-clippy/master/index.html#identity_conversion [`identity_op`]: https://rust-lang.github.io/rust-clippy/master/index.html#identity_op [`if_let_mutex`]: https://rust-lang.github.io/rust-clippy/master/index.html#if_let_mutex @@ -4892,6 +4894,7 @@ Released 2018-09-13 [`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 +[`little_endian_bytes`]: https://rust-lang.github.io/rust-clippy/master/index.html#little_endian_bytes [`logic_bug`]: https://rust-lang.github.io/rust-clippy/master/index.html#logic_bug [`lossy_float_literal`]: https://rust-lang.github.io/rust-clippy/master/index.html#lossy_float_literal [`macro_use_imports`]: https://rust-lang.github.io/rust-clippy/master/index.html#macro_use_imports diff --git a/clippy_lints/src/declared_lints.rs b/clippy_lints/src/declared_lints.rs index a7067d8b86a..aaaa38d4da5 100644 --- a/clippy_lints/src/declared_lints.rs +++ b/clippy_lints/src/declared_lints.rs @@ -143,6 +143,9 @@ pub(crate) static LINTS: &[&crate::LintInfo] = &[ crate::empty_drop::EMPTY_DROP_INFO, crate::empty_enum::EMPTY_ENUM_INFO, crate::empty_structs_with_brackets::EMPTY_STRUCTS_WITH_BRACKETS_INFO, + crate::endian_bytes::BIG_ENDIAN_BYTES_INFO, + crate::endian_bytes::HOST_ENDIAN_BYTES_INFO, + crate::endian_bytes::LITTLE_ENDIAN_BYTES_INFO, crate::entry::MAP_ENTRY_INFO, crate::enum_clike::ENUM_CLIKE_UNPORTABLE_VARIANT_INFO, crate::enum_variants::ENUM_VARIANT_NAMES_INFO, diff --git a/clippy_lints/src/endian_bytes.rs b/clippy_lints/src/endian_bytes.rs new file mode 100644 index 00000000000..bf6b92644e2 --- /dev/null +++ b/clippy_lints/src/endian_bytes.rs @@ -0,0 +1,138 @@ +use clippy_utils::{ + diagnostics::{span_lint_and_help, span_lint_and_then}, + is_lint_allowed, match_def_path, path_def_id, +}; +use rustc_hir::{Expr, ExprKind}; +use rustc_lint::{LateContext, LateLintPass}; +use rustc_session::{declare_lint_pass, declare_tool_lint}; + +declare_clippy_lint! { + /// ### What it does + /// + /// ### Why is this bad? + /// + /// ### Example + /// ```rust + /// // example code where clippy issues a warning + /// ``` + /// Use instead: + /// ```rust + /// // example code which does not raise clippy warning + /// ``` + #[clippy::version = "1.71.0"] + pub HOST_ENDIAN_BYTES, + restriction, + "disallows usage of the `to_ne_bytes` method" +} + +declare_clippy_lint! { + /// ### What it does + /// Checks for the usage of the `to_ne_bytes` method. + /// + /// ### Why is this bad? + /// It's not, but some may prefer to specify the target endianness explicitly. + /// + /// ### Example + /// ```rust,ignore + /// let _x = 2i32.to_ne_bytes(); + /// let _y = 2i64.to_ne_bytes(); + /// ``` + #[clippy::version = "1.71.0"] + pub LITTLE_ENDIAN_BYTES, + restriction, + "disallows usage of the `to_le_bytes` method" +} + +declare_clippy_lint! { + /// ### What it does + /// Checks for the usage of the `to_le_bytes` method. + /// + /// ### Why is this bad? + /// + /// ### Example + /// ```rust,ignore + /// // example code where clippy issues a warning + /// ``` + #[clippy::version = "1.71.0"] + pub BIG_ENDIAN_BYTES, + restriction, + "disallows usage of the `to_be_bytes` method" +} + +declare_lint_pass!(EndianBytes => [HOST_ENDIAN_BYTES, LITTLE_ENDIAN_BYTES, BIG_ENDIAN_BYTES]); + +impl LateLintPass<'_> for EndianBytes { + fn check_expr(&mut self, cx: &LateContext<'_>, expr: &Expr<'_>) { + if_chain! { + if let ExprKind::MethodCall(method_name, receiver, args, ..) = expr.kind; + if let ExprKind::Lit(..) = receiver.kind; + if args.is_empty(); + then { + if method_name.ident.name == sym!(to_ne_bytes) { + span_lint_and_help( + cx, + HOST_ENDIAN_BYTES, + expr.span, + "use of the method `to_ne_bytes`", + None, + "consider specifying the desired endianness", + ); + } else if method_name.ident.name == sym!(to_le_bytes) { + span_lint_and_then(cx, LITTLE_ENDIAN_BYTES, expr.span, "use of the method `to_le_bytes`", |diag| { + if is_lint_allowed(cx, BIG_ENDIAN_BYTES, expr.hir_id) { + diag.help("use `to_be_bytes` instead"); + } + }); + } else if method_name.ident.name == sym!(to_be_bytes) { + span_lint_and_then(cx, BIG_ENDIAN_BYTES, expr.span, "use of the method `to_be_bytes`", |diag| { + if is_lint_allowed(cx, LITTLE_ENDIAN_BYTES, expr.hir_id) { + diag.help("use `to_le_bytes` instead"); + } + }); + } + + // don't waste time also checking from_**_bytes + return; + } + } + + span_lint_and_help( + cx, + HOST_ENDIAN_BYTES, + expr.span, + "use of the method `from_ne_bytes`", + None, + &format!("consider specifying the desired endianness: {expr:?}"), + ); + + if_chain! { + if let ExprKind::Call(function, args) = expr.kind; + if let Some(function_def_id) = path_def_id(cx, function); + if args.len() == 1; + then { + if match_def_path(cx, function_def_id, &["from_ne_bytes"]) { + span_lint_and_help( + cx, + HOST_ENDIAN_BYTES, + expr.span, + "use of the method `from_ne_bytes`", + None, + "consider specifying the desired endianness", + ); + } else if match_def_path(cx, function_def_id, &["from_le_bytes"]) { + span_lint_and_then(cx, LITTLE_ENDIAN_BYTES, expr.span, "use of the method `from_le_bytes`", |diag| { + if is_lint_allowed(cx, BIG_ENDIAN_BYTES, expr.hir_id) { + diag.help("use `from_be_bytes` instead"); + } + }); + } else if match_def_path(cx, function_def_id, &["from_be_bytes"]) { + span_lint_and_then(cx, BIG_ENDIAN_BYTES, expr.span, "use of the method `from_be_bytes`", |diag| { + if is_lint_allowed(cx, LITTLE_ENDIAN_BYTES, expr.hir_id) { + diag.help("use `from_le_bytes` instead"); + } + }); + } + } + } + } +} diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index a0a89e4967b..122fc3feeee 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -114,6 +114,7 @@ mod else_if_without_else; mod empty_drop; mod empty_enum; mod empty_structs_with_brackets; +mod endian_bytes; mod entry; mod enum_clike; mod enum_variants; @@ -996,6 +997,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: store.register_late_pass(|_| Box::new(default_constructed_unit_structs::DefaultConstructedUnitStructs)); store.register_early_pass(|| Box::new(needless_else::NeedlessElse)); store.register_late_pass(|_| Box::new(missing_fields_in_debug::MissingFieldsInDebug)); + store.register_late_pass(|_| Box::new(endian_bytes::EndianBytes)); // add lints here, do not remove this comment, it's used in `new_lint` } diff --git a/tests/ui/endian_bytes.rs b/tests/ui/endian_bytes.rs new file mode 100644 index 00000000000..1dfda9d53bf --- /dev/null +++ b/tests/ui/endian_bytes.rs @@ -0,0 +1,163 @@ +#![allow(unused)] +#![allow(clippy::diverging_sub_expression)] +#![no_main] + +#[warn(clippy::host_endian_bytes)] +fn host() { + 2u8.to_ne_bytes(); + 2i8.to_ne_bytes(); + 2u16.to_ne_bytes(); + 2i16.to_ne_bytes(); + 2u32.to_ne_bytes(); + 2i32.to_ne_bytes(); + 2u64.to_ne_bytes(); + 2i64.to_ne_bytes(); + 2u128.to_ne_bytes(); + 2i128.to_ne_bytes(); + 2usize.to_ne_bytes(); + 2isize.to_ne_bytes(); + 2.0f32.to_ne_bytes(); + 2.0f64.to_ne_bytes(); + u8::from_ne_bytes(todo!()); + i8::from_ne_bytes(todo!()); + u16::from_ne_bytes(todo!()); + i16::from_ne_bytes(todo!()); + u32::from_ne_bytes(todo!()); + i32::from_ne_bytes(todo!()); + u64::from_ne_bytes(todo!()); + i64::from_ne_bytes(todo!()); + u128::from_ne_bytes(todo!()); + i128::from_ne_bytes(todo!()); + f32::from_ne_bytes(todo!()); + f64::from_ne_bytes(todo!()); +} + +#[warn(clippy::little_endian_bytes)] +fn little() { + 2u8.to_le_bytes(); + 2i8.to_le_bytes(); + 2u16.to_le_bytes(); + 2i16.to_le_bytes(); + 2u32.to_le_bytes(); + 2i32.to_le_bytes(); + 2u64.to_le_bytes(); + 2i64.to_le_bytes(); + 2u128.to_le_bytes(); + 2i128.to_le_bytes(); + 2usize.to_le_bytes(); + 2isize.to_le_bytes(); + 2.0f32.to_le_bytes(); + 2.0f64.to_le_bytes(); + u8::from_le_bytes(todo!()); + i8::from_le_bytes(todo!()); + u16::from_le_bytes(todo!()); + i16::from_le_bytes(todo!()); + u32::from_le_bytes(todo!()); + i32::from_le_bytes(todo!()); + u64::from_le_bytes(todo!()); + i64::from_le_bytes(todo!()); + u128::from_le_bytes(todo!()); + i128::from_le_bytes(todo!()); + usize::from_le_bytes(todo!()); + isize::from_le_bytes(todo!()); + f32::from_le_bytes(todo!()); + f64::from_le_bytes(todo!()); +} + +#[warn(clippy::big_endian_bytes)] +fn big() { + 2u8.to_be_bytes(); + 2i8.to_be_bytes(); + 2u16.to_be_bytes(); + 2i16.to_be_bytes(); + 2u32.to_be_bytes(); + 2i32.to_be_bytes(); + 2u64.to_be_bytes(); + 2i64.to_be_bytes(); + 2u128.to_be_bytes(); + 2i128.to_be_bytes(); + 2.0f32.to_be_bytes(); + 2.0f64.to_be_bytes(); + 2usize.to_be_bytes(); + 2isize.to_be_bytes(); + u8::from_be_bytes(todo!()); + i8::from_be_bytes(todo!()); + u16::from_be_bytes(todo!()); + i16::from_be_bytes(todo!()); + u32::from_be_bytes(todo!()); + i32::from_be_bytes(todo!()); + u64::from_be_bytes(todo!()); + i64::from_be_bytes(todo!()); + u128::from_be_bytes(todo!()); + i128::from_be_bytes(todo!()); + usize::from_be_bytes(todo!()); + isize::from_be_bytes(todo!()); + f32::from_be_bytes(todo!()); + f64::from_be_bytes(todo!()); +} + +#[warn(clippy::little_endian_bytes)] +#[warn(clippy::big_endian_bytes)] +fn little_no_help() { + 2u8.to_le_bytes(); + 2i8.to_le_bytes(); + 2u16.to_le_bytes(); + 2i16.to_le_bytes(); + 2u32.to_le_bytes(); + 2i32.to_le_bytes(); + 2u64.to_le_bytes(); + 2i64.to_le_bytes(); + 2u128.to_le_bytes(); + 2i128.to_le_bytes(); + 2usize.to_le_bytes(); + 2isize.to_le_bytes(); + 2.0f32.to_le_bytes(); + 2.0f64.to_le_bytes(); + u8::from_le_bytes(todo!()); + i8::from_le_bytes(todo!()); + u16::from_le_bytes(todo!()); + i16::from_le_bytes(todo!()); + u32::from_le_bytes(todo!()); + i32::from_le_bytes(todo!()); + u64::from_le_bytes(todo!()); + i64::from_le_bytes(todo!()); + u128::from_le_bytes(todo!()); + i128::from_le_bytes(todo!()); + usize::from_le_bytes(todo!()); + isize::from_le_bytes(todo!()); + f32::from_le_bytes(todo!()); + f64::from_le_bytes(todo!()); +} + +#[warn(clippy::big_endian_bytes)] +#[warn(clippy::little_endian_bytes)] +fn big_no_help() { + 2u8.to_be_bytes(); + 2i8.to_be_bytes(); + 2u16.to_be_bytes(); + 2i16.to_be_bytes(); + 2u32.to_be_bytes(); + 2i32.to_be_bytes(); + 2u64.to_be_bytes(); + 2i64.to_be_bytes(); + 2u128.to_be_bytes(); + 2i128.to_be_bytes(); + 2usize.to_be_bytes(); + 2isize.to_be_bytes(); + 2.0f32.to_be_bytes(); + 2.0f64.to_be_bytes(); + u8::from_be_bytes(todo!()); + i8::from_be_bytes(todo!()); + u16::from_be_bytes(todo!()); + i16::from_be_bytes(todo!()); + u32::from_be_bytes(todo!()); + i32::from_be_bytes(todo!()); + u64::from_be_bytes(todo!()); + i64::from_be_bytes(todo!()); + u128::from_be_bytes(todo!()); + i128::from_be_bytes(todo!()); + usize::from_be_bytes(todo!()); + isize::from_be_bytes(todo!()); + f32::from_be_bytes(todo!()); + f64::from_be_bytes(todo!()); +} diff --git a/tests/ui/endian_bytes.stderr b/tests/ui/endian_bytes.stderr new file mode 100644 index 00000000000..afbb8e3b16c --- /dev/null +++ b/tests/ui/endian_bytes.stderr @@ -0,0 +1,1152 @@ +error: use of the method `from_ne_bytes` + --> $DIR/endian_bytes.rs:6:11 + | +LL | fn host() { + | ___________^ +LL | | 2u8.to_ne_bytes(); +LL | | 2i8.to_ne_bytes(); +LL | | 2u16.to_ne_bytes(); +... | +LL | | f64::from_ne_bytes(todo!()); +LL | | } + | |_^ + | + = help: consider specifying the desired endianness: Expr { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).202), kind: Block(Block { stmts: [Stmt { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).4), kind: Semi(Expr { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).1), kind: MethodCall(PathSegment { ident: to_ne_bytes#0, hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).2), res: Err, args: None, infer_args: true }, Expr { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).3), kind: Lit(Spanned { node: Int(2, Unsigned(U8)), span: $DIR/endian_bytes.rs:7:5: 7:8 (#0) }), span: $DIR/endian_bytes.rs:7:5: 7:8 (#0) }, [], $DIR/endian_bytes.rs:7:9: 7:22 (#0)), span: $DIR/endian_bytes.rs:7:5: 7:22 (#0) }), span: $DIR/endian_bytes.rs:7:5: 7:23 (#0) }, Stmt { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).8), kind: Semi(Expr { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).5), kind: MethodCall(PathSegment { ident: to_ne_bytes#0, hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).6), res: Err, args: None, infer_args: true }, Expr { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).7), kind: Lit(Spanned { node: Int(2, Signed(I8)), span: $DIR/endian_bytes.rs:8:5: 8:8 (#0) }), span: $DIR/endian_bytes.rs:8:5: 8:8 (#0) }, [], $DIR/endian_bytes.rs:8:9: 8:22 (#0)), span: $DIR/endian_bytes.rs:8:5: 8:22 (#0) }), span: $DIR/endian_bytes.rs:8:5: 8:23 (#0) }, Stmt { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).12), kind: Semi(Expr { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).9), kind: MethodCall(PathSegment { ident: to_ne_bytes#0, hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).10), res: Err, args: None, infer_args: true }, Expr { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).11), kind: Lit(Spanned { node: Int(2, Unsigned(U16)), span: $DIR/endian_bytes.rs:9:5: 9:9 (#0) }), span: $DIR/endian_bytes.rs:9:5: 9:9 (#0) }, [], $DIR/endian_bytes.rs:9:10: 9:23 (#0)), span: $DIR/endian_bytes.rs:9:5: 9:23 (#0) }), span: $DIR/endian_bytes.rs:9:5: 9:24 (#0) }, Stmt { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).16), kind: Semi(Expr { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).13), kind: MethodCall(PathSegment { ident: to_ne_bytes#0, hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).14), res: Err, args: None, infer_args: true }, Expr { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).15), kind: Lit(Spanned { node: Int(2, Signed(I16)), span: $DIR/endian_bytes.rs:10:5: 10:9 (#0) }), span: $DIR/endian_bytes.rs:10:5: 10:9 (#0) }, [], $DIR/endian_bytes.rs:10:10: 10:23 (#0)), span: $DIR/endian_bytes.rs:10:5: 10:23 (#0) }), span: $DIR/endian_bytes.rs:10:5: 10:24 (#0) }, Stmt { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).20), kind: Semi(Expr { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).17), kind: MethodCall(PathSegment { ident: to_ne_bytes#0, hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).18), res: Err, args: None, infer_args: true }, Expr { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).19), kind: Lit(Spanned { node: Int(2, Unsigned(U32)), span: $DIR/endian_bytes.rs:11:5: 11:9 (#0) }), span: $DIR/endian_bytes.rs:11:5: 11:9 (#0) }, [], $DIR/endian_bytes.rs:11:10: 11:23 (#0)), span: $DIR/endian_bytes.rs:11:5: 11:23 (#0) }), span: $DIR/endian_bytes.rs:11:5: 11:24 (#0) }, Stmt { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).24), kind: Semi(Expr { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).21), kind: MethodCall(PathSegment { ident: to_ne_bytes#0, hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).22), res: Err, args: None, infer_args: true }, Expr { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).23), kind: Lit(Spanned { node: Int(2, Signed(I32)), span: $DIR/endian_bytes.rs:12:5: 12:9 (#0) }), span: $DIR/endian_bytes.rs:12:5: 12:9 (#0) }, [], $DIR/endian_bytes.rs:12:10: 12:23 (#0)), span: $DIR/endian_bytes.rs:12:5: 12:23 (#0) }), span: $DIR/endian_bytes.rs:12:5: 12:24 (#0) }, Stmt { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).28), kind: Semi(Expr { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).25), kind: MethodCall(PathSegment { ident: to_ne_bytes#0, hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).26), res: Err, args: None, infer_args: true }, Expr { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).27), kind: Lit(Spanned { node: Int(2, Unsigned(U64)), span: $DIR/endian_bytes.rs:13:5: 13:9 (#0) }), span: $DIR/endian_bytes.rs:13:5: 13:9 (#0) }, [], $DIR/endian_bytes.rs:13:10: 13:23 (#0)), span: $DIR/endian_bytes.rs:13:5: 13:23 (#0) }), span: $DIR/endian_bytes.rs:13:5: 13:24 (#0) }, Stmt { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).32), kind: Semi(Expr { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).29), kind: MethodCall(PathSegment { ident: to_ne_bytes#0, hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).30), res: Err, args: None, infer_args: true }, Expr { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).31), kind: Lit(Spanned { node: Int(2, Signed(I64)), span: $DIR/endian_bytes.rs:14:5: 14:9 (#0) }), span: $DIR/endian_bytes.rs:14:5: 14:9 (#0) }, [], $DIR/endian_bytes.rs:14:10: 14:23 (#0)), span: $DIR/endian_bytes.rs:14:5: 14:23 (#0) }), span: $DIR/endian_bytes.rs:14:5: 14:24 (#0) }, Stmt { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).36), kind: Semi(Expr { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).33), kind: MethodCall(PathSegment { ident: to_ne_bytes#0, hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).34), res: Err, args: None, infer_args: true }, Expr { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).35), kind: Lit(Spanned { node: Int(2, Unsigned(U128)), span: $DIR/endian_bytes.rs:15:5: 15:10 (#0) }), span: $DIR/endian_bytes.rs:15:5: 15:10 (#0) }, [], $DIR/endian_bytes.rs:15:11: 15:24 (#0)), span: $DIR/endian_bytes.rs:15:5: 15:24 (#0) }), span: $DIR/endian_bytes.rs:15:5: 15:25 (#0) }, Stmt { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).40), kind: Semi(Expr { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).37), kind: MethodCall(PathSegment { ident: to_ne_bytes#0, hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).38), res: Err, args: None, infer_args: true }, Expr { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).39), kind: Lit(Spanned { node: Int(2, Signed(I128)), span: $DIR/endian_bytes.rs:16:5: 16:10 (#0) }), span: $DIR/endian_bytes.rs:16:5: 16:10 (#0) }, [], $DIR/endian_bytes.rs:16:11: 16:24 (#0)), span: $DIR/endian_bytes.rs:16:5: 16:24 (#0) }), span: $DIR/endian_bytes.rs:16:5: 16:25 (#0) }, Stmt { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).44), kind: Semi(Expr { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).41), kind: MethodCall(PathSegment { ident: to_ne_bytes#0, hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).42), res: Err, args: None, infer_args: true }, Expr { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).43), kind: Lit(Spanned { node: Int(2, Unsigned(Usize)), span: $DIR/endian_bytes.rs:17:5: 17:11 (#0) }), span: $DIR/endian_bytes.rs:17:5: 17:11 (#0) }, [], $DIR/endian_bytes.rs:17:12: 17:25 (#0)), span: $DIR/endian_bytes.rs:17:5: 17:25 (#0) }), span: $DIR/endian_bytes.rs:17:5: 17:26 (#0) }, Stmt { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).48), kind: Semi(Expr { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).45), kind: MethodCall(PathSegment { ident: to_ne_bytes#0, hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).46), res: Err, args: None, infer_args: true }, Expr { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).47), kind: Lit(Spanned { node: Int(2, Signed(Isize)), span: $DIR/endian_bytes.rs:18:5: 18:11 (#0) }), span: $DIR/endian_bytes.rs:18:5: 18:11 (#0) }, [], $DIR/endian_bytes.rs:18:12: 18:25 (#0)), span: $DIR/endian_bytes.rs:18:5: 18:25 (#0) }), span: $DIR/endian_bytes.rs:18:5: 18:26 (#0) }, Stmt { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).52), kind: Semi(Expr { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).49), kind: MethodCall(PathSegment { ident: to_ne_bytes#0, hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).50), res: Err, args: None, infer_args: true }, Expr { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).51), kind: Lit(Spanned { node: Float("2.0", Suffixed(F32)), span: $DIR/endian_bytes.rs:19:5: 19:11 (#0) }), span: $DIR/endian_bytes.rs:19:5: 19:11 (#0) }, [], $DIR/endian_bytes.rs:19:12: 19:25 (#0)), span: $DIR/endian_bytes.rs:19:5: 19:25 (#0) }), span: $DIR/endian_bytes.rs:19:5: 19:26 (#0) }, Stmt { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).56), kind: Semi(Expr { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).53), kind: MethodCall(PathSegment { ident: to_ne_bytes#0, hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).54), res: Err, args: None, infer_args: true }, Expr { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).55), kind: Lit(Spanned { node: Float("2.0", Suffixed(F64)), span: $DIR/endian_bytes.rs:20:5: 20:11 (#0) }), span: $DIR/endian_bytes.rs:20:5: 20:11 (#0) }, [], $DIR/endian_bytes.rs:20:12: 20:25 (#0)), span: $DIR/endian_bytes.rs:20:5: 20:25 (#0) }), span: $DIR/endian_bytes.rs:20:5: 20:26 (#0) }, Stmt { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).68), kind: Semi(Expr { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).57), kind: Call(Expr { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).58), kind: Path(TypeRelative(Ty { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).60), kind: Path(Resolved(None, Path { span: $DIR/endian_bytes.rs:21:5: 21:7 (#0), res: PrimTy(Uint(U8)), segments: [PathSegment { ident: u8#0, hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).59), res: PrimTy(Uint(U8)), args: None, infer_args: true }] })), span: $DIR/endian_bytes.rs:21:5: 21:7 (#0) }, PathSegment { ident: from_ne_bytes#0, hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).61), res: Err, args: None, infer_args: true })), span: $DIR/endian_bytes.rs:21:5: 21:22 (#0) }, [Expr { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).62), kind: Call(Expr { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).63), kind: Path(Resolved(None, Path { span: /home/centri/.rustup/toolchains/nightly-2023-05-05-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/macros/mod.rs:773:9: 773:33 (#4), res: Def(Fn, DefId(2:8292 ~ core[690e]::panicking::panic)), segments: [PathSegment { ident: $crate#4, hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).64), res: Err, args: None, infer_args: true }, PathSegment { ident: panicking#4, hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).65), res: Def(Mod, DefId(2:8281 ~ core[690e]::panicking)), args: None, infer_args: true }, PathSegment { ident: panic#4, hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).66), res: Def(Fn, DefId(2:8292 ~ core[690e]::panicking::panic)), args: None, infer_args: true }] })), span: /home/centri/.rustup/toolchains/nightly-2023-05-05-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/macros/mod.rs:773:9: 773:33 (#4) }, [Expr { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).67), kind: Lit(Spanned { node: Str("not yet implemented", Cooked), span: /home/centri/.rustup/toolchains/nightly-2023-05-05-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/macros/mod.rs:773:34: 773:55 (#4) }), span: /home/centri/.rustup/toolchains/nightly-2023-05-05-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/macros/mod.rs:773:34: 773:55 (#4) }]), span: /home/centri/.rustup/toolchains/nightly-2023-05-05-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/macros/mod.rs:773:9: 773:56 (#4) }]), span: $DIR/endian_bytes.rs:21:5: 21:31 (#0) }), span: $DIR/endian_bytes.rs:21:5: 21:32 (#0) }, Stmt { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).80), kind: Semi(Expr { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).69), kind: Call(Expr { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).70), kind: Path(TypeRelative(Ty { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).72), kind: Path(Resolved(None, Path { span: $DIR/endian_bytes.rs:22:5: 22:7 (#0), res: PrimTy(Int(I8)), segments: [PathSegment { ident: i8#0, hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).71), res: PrimTy(Int(I8)), args: None, infer_args: true }] })), span: $DIR/endian_bytes.rs:22:5: 22:7 (#0) }, PathSegment { ident: from_ne_bytes#0, hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).73), res: Err, args: None, infer_args: true })), span: $DIR/endian_bytes.rs:22:5: 22:22 (#0) }, [Expr { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).74), kind: Call(Expr { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).75), kind: Path(Resolved(None, Path { span: /home/centri/.rustup/toolchains/nightly-2023-05-05-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/macros/mod.rs:773:9: 773:33 (#5), res: Def(Fn, DefId(2:8292 ~ core[690e]::panicking::panic)), segments: [PathSegment { ident: $crate#5, hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).76), res: Err, args: None, infer_args: true }, PathSegment { ident: panicking#5, hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).77), res: Def(Mod, DefId(2:8281 ~ core[690e]::panicking)), args: None, infer_args: true }, PathSegment { ident: panic#5, hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).78), res: Def(Fn, DefId(2:8292 ~ core[690e]::panicking::panic)), args: None, infer_args: true }] })), span: /home/centri/.rustup/toolchains/nightly-2023-05-05-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/macros/mod.rs:773:9: 773:33 (#5) }, [Expr { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).79), kind: Lit(Spanned { node: Str("not yet implemented", Cooked), span: /home/centri/.rustup/toolchains/nightly-2023-05-05-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/macros/mod.rs:773:34: 773:55 (#5) }), span: /home/centri/.rustup/toolchains/nightly-2023-05-05-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/macros/mod.rs:773:34: 773:55 (#5) }]), span: /home/centri/.rustup/toolchains/nightly-2023-05-05-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/macros/mod.rs:773:9: 773:56 (#5) }]), span: $DIR/endian_bytes.rs:22:5: 22:31 (#0) }), span: $DIR/endian_bytes.rs:22:5: 22:32 (#0) }, Stmt { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).92), kind: Semi(Expr { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).81), kind: Call(Expr { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).82), kind: Path(TypeRelative(Ty { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).84), kind: Path(Resolved(None, Path { span: $DIR/endian_bytes.rs:23:5: 23:8 (#0), res: PrimTy(Uint(U16)), segments: [PathSegment { ident: u16#0, hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).83), res: PrimTy(Uint(U16)), args: None, infer_args: true }] })), span: $DIR/endian_bytes.rs:23:5: 23:8 (#0) }, PathSegment { ident: from_ne_bytes#0, hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).85), res: Err, args: None, infer_args: true })), span: $DIR/endian_bytes.rs:23:5: 23:23 (#0) }, [Expr { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).86), kind: Call(Expr { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).87), kind: Path(Resolved(None, Path { span: /home/centri/.rustup/toolchains/nightly-2023-05-05-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/macros/mod.rs:773:9: 773:33 (#6), res: Def(Fn, DefId(2:8292 ~ core[690e]::panicking::panic)), segments: [PathSegment { ident: $crate#6, hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).88), res: Err, args: None, infer_args: true }, PathSegment { ident: panicking#6, hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).89), res: Def(Mod, DefId(2:8281 ~ core[690e]::panicking)), args: None, infer_args: true }, PathSegment { ident: panic#6, hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).90), res: Def(Fn, DefId(2:8292 ~ core[690e]::panicking::panic)), args: None, infer_args: true }] })), span: /home/centri/.rustup/toolchains/nightly-2023-05-05-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/macros/mod.rs:773:9: 773:33 (#6) }, [Expr { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).91), kind: Lit(Spanned { node: Str("not yet implemented", Cooked), span: /home/centri/.rustup/toolchains/nightly-2023-05-05-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/macros/mod.rs:773:34: 773:55 (#6) }), span: /home/centri/.rustup/toolchains/nightly-2023-05-05-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/macros/mod.rs:773:34: 773:55 (#6) }]), span: /home/centri/.rustup/toolchains/nightly-2023-05-05-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/macros/mod.rs:773:9: 773:56 (#6) }]), span: $DIR/endian_bytes.rs:23:5: 23:32 (#0) }), span: $DIR/endian_bytes.rs:23:5: 23:33 (#0) }, Stmt { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).104), kind: Semi(Expr { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).93), kind: Call(Expr { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).94), kind: Path(TypeRelative(Ty { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).96), kind: Path(Resolved(None, Path { span: $DIR/endian_bytes.rs:24:5: 24:8 (#0), res: PrimTy(Int(I16)), segments: [PathSegment { ident: i16#0, hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).95), res: PrimTy(Int(I16)), args: None, infer_args: true }] })), span: $DIR/endian_bytes.rs:24:5: 24:8 (#0) }, PathSegment { ident: from_ne_bytes#0, hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).97), res: Err, args: None, infer_args: true })), span: $DIR/endian_bytes.rs:24:5: 24:23 (#0) }, [Expr { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).98), kind: Call(Expr { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).99), kind: Path(Resolved(None, Path { span: /home/centri/.rustup/toolchains/nightly-2023-05-05-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/macros/mod.rs:773:9: 773:33 (#7), res: Def(Fn, DefId(2:8292 ~ core[690e]::panicking::panic)), segments: [PathSegment { ident: $crate#7, hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).100), res: Err, args: None, infer_args: true }, PathSegment { ident: panicking#7, hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).101), res: Def(Mod, DefId(2:8281 ~ core[690e]::panicking)), args: None, infer_args: true }, PathSegment { ident: panic#7, hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).102), res: Def(Fn, DefId(2:8292 ~ core[690e]::panicking::panic)), args: None, infer_args: true }] })), span: /home/centri/.rustup/toolchains/nightly-2023-05-05-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/macros/mod.rs:773:9: 773:33 (#7) }, [Expr { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).103), kind: Lit(Spanned { node: Str("not yet implemented", Cooked), span: /home/centri/.rustup/toolchains/nightly-2023-05-05-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/macros/mod.rs:773:34: 773:55 (#7) }), span: /home/centri/.rustup/toolchains/nightly-2023-05-05-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/macros/mod.rs:773:34: 773:55 (#7) }]), span: /home/centri/.rustup/toolchains/nightly-2023-05-05-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/macros/mod.rs:773:9: 773:56 (#7) }]), span: $DIR/endian_bytes.rs:24:5: 24:32 (#0) }), span: $DIR/endian_bytes.rs:24:5: 24:33 (#0) }, Stmt { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).116), kind: Semi(Expr { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).105), kind: Call(Expr { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).106), kind: Path(TypeRelative(Ty { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).108), kind: Path(Resolved(None, Path { span: $DIR/endian_bytes.rs:25:5: 25:8 (#0), res: PrimTy(Uint(U32)), segments: [PathSegment { ident: u32#0, hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).107), res: PrimTy(Uint(U32)), args: None, infer_args: true }] })), span: $DIR/endian_bytes.rs:25:5: 25:8 (#0) }, PathSegment { ident: from_ne_bytes#0, hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).109), res: Err, args: None, infer_args: true })), span: $DIR/endian_bytes.rs:25:5: 25:23 (#0) }, [Expr { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).110), kind: Call(Expr { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).111), kind: Path(Resolved(None, Path { span: /home/centri/.rustup/toolchains/nightly-2023-05-05-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/macros/mod.rs:773:9: 773:33 (#8), res: Def(Fn, DefId(2:8292 ~ core[690e]::panicking::panic)), segments: [PathSegment { ident: $crate#8, hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).112), res: Err, args: None, infer_args: true }, PathSegment { ident: panicking#8, hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).113), res: Def(Mod, DefId(2:8281 ~ core[690e]::panicking)), args: None, infer_args: true }, PathSegment { ident: panic#8, hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).114), res: Def(Fn, DefId(2:8292 ~ core[690e]::panicking::panic)), args: None, infer_args: true }] })), span: /home/centri/.rustup/toolchains/nightly-2023-05-05-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/macros/mod.rs:773:9: 773:33 (#8) }, [Expr { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).115), kind: Lit(Spanned { node: Str("not yet implemented", Cooked), span: /home/centri/.rustup/toolchains/nightly-2023-05-05-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/macros/mod.rs:773:34: 773:55 (#8) }), span: /home/centri/.rustup/toolchains/nightly-2023-05-05-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/macros/mod.rs:773:34: 773:55 (#8) }]), span: /home/centri/.rustup/toolchains/nightly-2023-05-05-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/macros/mod.rs:773:9: 773:56 (#8) }]), span: $DIR/endian_bytes.rs:25:5: 25:32 (#0) }), span: $DIR/endian_bytes.rs:25:5: 25:33 (#0) }, Stmt { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).128), kind: Semi(Expr { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).117), kind: Call(Expr { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).118), kind: Path(TypeRelative(Ty { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).120), kind: Path(Resolved(None, Path { span: $DIR/endian_bytes.rs:26:5: 26:8 (#0), res: PrimTy(Int(I32)), segments: [PathSegment { ident: i32#0, hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).119), res: PrimTy(Int(I32)), args: None, infer_args: true }] })), span: $DIR/endian_bytes.rs:26:5: 26:8 (#0) }, PathSegment { ident: from_ne_bytes#0, hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).121), res: Err, args: None, infer_args: true })), span: $DIR/endian_bytes.rs:26:5: 26:23 (#0) }, [Expr { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).122), kind: Call(Expr { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).123), kind: Path(Resolved(None, Path { span: /home/centri/.rustup/toolchains/nightly-2023-05-05-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/macros/mod.rs:773:9: 773:33 (#9), res: Def(Fn, DefId(2:8292 ~ core[690e]::panicking::panic)), segments: [PathSegment { ident: $crate#9, hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).124), res: Err, args: None, infer_args: true }, PathSegment { ident: panicking#9, hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).125), res: Def(Mod, DefId(2:8281 ~ core[690e]::panicking)), args: None, infer_args: true }, PathSegment { ident: panic#9, hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).126), res: Def(Fn, DefId(2:8292 ~ core[690e]::panicking::panic)), args: None, infer_args: true }] })), span: /home/centri/.rustup/toolchains/nightly-2023-05-05-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/macros/mod.rs:773:9: 773:33 (#9) }, [Expr { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).127), kind: Lit(Spanned { node: Str("not yet implemented", Cooked), span: /home/centri/.rustup/toolchains/nightly-2023-05-05-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/macros/mod.rs:773:34: 773:55 (#9) }), span: /home/centri/.rustup/toolchains/nightly-2023-05-05-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/macros/mod.rs:773:34: 773:55 (#9) }]), span: /home/centri/.rustup/toolchains/nightly-2023-05-05-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/macros/mod.rs:773:9: 773:56 (#9) }]), span: $DIR/endian_bytes.rs:26:5: 26:32 (#0) }), span: $DIR/endian_bytes.rs:26:5: 26:33 (#0) }, Stmt { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).140), kind: Semi(Expr { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).129), kind: Call(Expr { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).130), kind: Path(TypeRelative(Ty { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).132), kind: Path(Resolved(None, Path { span: $DIR/endian_bytes.rs:27:5: 27:8 (#0), res: PrimTy(Uint(U64)), segments: [PathSegment { ident: u64#0, hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).131), res: PrimTy(Uint(U64)), args: None, infer_args: true }] })), span: $DIR/endian_bytes.rs:27:5: 27:8 (#0) }, PathSegment { ident: from_ne_bytes#0, hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).133), res: Err, args: None, infer_args: true })), span: $DIR/endian_bytes.rs:27:5: 27:23 (#0) }, [Expr { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).134), kind: Call(Expr { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).135), kind: Path(Resolved(None, Path { span: /home/centri/.rustup/toolchains/nightly-2023-05-05-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/macros/mod.rs:773:9: 773:33 (#10), res: Def(Fn, DefId(2:8292 ~ core[690e]::panicking::panic)), segments: [PathSegment { ident: $crate#10, hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).136), res: Err, args: None, infer_args: true }, PathSegment { ident: panicking#10, hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).137), res: Def(Mod, DefId(2:8281 ~ core[690e]::panicking)), args: None, infer_args: true }, PathSegment { ident: panic#10, hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).138), res: Def(Fn, DefId(2:8292 ~ core[690e]::panicking::panic)), args: None, infer_args: true }] })), span: /home/centri/.rustup/toolchains/nightly-2023-05-05-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/macros/mod.rs:773:9: 773:33 (#10) }, [Expr { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).139), kind: Lit(Spanned { node: Str("not yet implemented", Cooked), span: /home/centri/.rustup/toolchains/nightly-2023-05-05-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/macros/mod.rs:773:34: 773:55 (#10) }), span: /home/centri/.rustup/toolchains/nightly-2023-05-05-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/macros/mod.rs:773:34: 773:55 (#10) }]), span: /home/centri/.rustup/toolchains/nightly-2023-05-05-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/macros/mod.rs:773:9: 773:56 (#10) }]), span: $DIR/endian_bytes.rs:27:5: 27:32 (#0) }), span: $DIR/endian_bytes.rs:27:5: 27:33 (#0) }, Stmt { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).152), kind: Semi(Expr { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).141), kind: Call(Expr { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).142), kind: Path(TypeRelative(Ty { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).144), kind: Path(Resolved(None, Path { span: $DIR/endian_bytes.rs:28:5: 28:8 (#0), res: PrimTy(Int(I64)), segments: [PathSegment { ident: i64#0, hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).143), res: PrimTy(Int(I64)), args: None, infer_args: true }] })), span: $DIR/endian_bytes.rs:28:5: 28:8 (#0) }, PathSegment { ident: from_ne_bytes#0, hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).145), res: Err, args: None, infer_args: true })), span: $DIR/endian_bytes.rs:28:5: 28:23 (#0) }, [Expr { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).146), kind: Call(Expr { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).147), kind: Path(Resolved(None, Path { span: /home/centri/.rustup/toolchains/nightly-2023-05-05-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/macros/mod.rs:773:9: 773:33 (#11), res: Def(Fn, DefId(2:8292 ~ core[690e]::panicking::panic)), segments: [PathSegment { ident: $crate#11, hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).148), res: Err, args: None, infer_args: true }, PathSegment { ident: panicking#11, hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).149), res: Def(Mod, DefId(2:8281 ~ core[690e]::panicking)), args: None, infer_args: true }, PathSegment { ident: panic#11, hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).150), res: Def(Fn, DefId(2:8292 ~ core[690e]::panicking::panic)), args: None, infer_args: true }] })), span: /home/centri/.rustup/toolchains/nightly-2023-05-05-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/macros/mod.rs:773:9: 773:33 (#11) }, [Expr { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).151), kind: Lit(Spanned { node: Str("not yet implemented", Cooked), span: /home/centri/.rustup/toolchains/nightly-2023-05-05-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/macros/mod.rs:773:34: 773:55 (#11) }), span: /home/centri/.rustup/toolchains/nightly-2023-05-05-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/macros/mod.rs:773:34: 773:55 (#11) }]), span: /home/centri/.rustup/toolchains/nightly-2023-05-05-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/macros/mod.rs:773:9: 773:56 (#11) }]), span: $DIR/endian_bytes.rs:28:5: 28:32 (#0) }), span: $DIR/endian_bytes.rs:28:5: 28:33 (#0) }, Stmt { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).164), kind: Semi(Expr { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).153), kind: Call(Expr { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).154), kind: Path(TypeRelative(Ty { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).156), kind: Path(Resolved(None, Path { span: $DIR/endian_bytes.rs:29:5: 29:9 (#0), res: PrimTy(Uint(U128)), segments: [PathSegment { ident: u128#0, hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).155), res: PrimTy(Uint(U128)), args: None, infer_args: true }] })), span: $DIR/endian_bytes.rs:29:5: 29:9 (#0) }, PathSegment { ident: from_ne_bytes#0, hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).157), res: Err, args: None, infer_args: true })), span: $DIR/endian_bytes.rs:29:5: 29:24 (#0) }, [Expr { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).158), kind: Call(Expr { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).159), kind: Path(Resolved(None, Path { span: /home/centri/.rustup/toolchains/nightly-2023-05-05-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/macros/mod.rs:773:9: 773:33 (#12), res: Def(Fn, DefId(2:8292 ~ core[690e]::panicking::panic)), segments: [PathSegment { ident: $crate#12, hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).160), res: Err, args: None, infer_args: true }, PathSegment { ident: panicking#12, hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).161), res: Def(Mod, DefId(2:8281 ~ core[690e]::panicking)), args: None, infer_args: true }, PathSegment { ident: panic#12, hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).162), res: Def(Fn, DefId(2:8292 ~ core[690e]::panicking::panic)), args: None, infer_args: true }] })), span: /home/centri/.rustup/toolchains/nightly-2023-05-05-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/macros/mod.rs:773:9: 773:33 (#12) }, [Expr { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).163), kind: Lit(Spanned { node: Str("not yet implemented", Cooked), span: /home/centri/.rustup/toolchains/nightly-2023-05-05-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/macros/mod.rs:773:34: 773:55 (#12) }), span: /home/centri/.rustup/toolchains/nightly-2023-05-05-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/macros/mod.rs:773:34: 773:55 (#12) }]), span: /home/centri/.rustup/toolchains/nightly-2023-05-05-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/macros/mod.rs:773:9: 773:56 (#12) }]), span: $DIR/endian_bytes.rs:29:5: 29:33 (#0) }), span: $DIR/endian_bytes.rs:29:5: 29:34 (#0) }, Stmt { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).176), kind: Semi(Expr { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).165), kind: Call(Expr { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).166), kind: Path(TypeRelative(Ty { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).168), kind: Path(Resolved(None, Path { span: $DIR/endian_bytes.rs:30:5: 30:9 (#0), res: PrimTy(Int(I128)), segments: [PathSegment { ident: i128#0, hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).167), res: PrimTy(Int(I128)), args: None, infer_args: true }] })), span: $DIR/endian_bytes.rs:30:5: 30:9 (#0) }, PathSegment { ident: from_ne_bytes#0, hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).169), res: Err, args: None, infer_args: true })), span: $DIR/endian_bytes.rs:30:5: 30:24 (#0) }, [Expr { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).170), kind: Call(Expr { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).171), kind: Path(Resolved(None, Path { span: /home/centri/.rustup/toolchains/nightly-2023-05-05-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/macros/mod.rs:773:9: 773:33 (#13), res: Def(Fn, DefId(2:8292 ~ core[690e]::panicking::panic)), segments: [PathSegment { ident: $crate#13, hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).172), res: Err, args: None, infer_args: true }, PathSegment { ident: panicking#13, hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).173), res: Def(Mod, DefId(2:8281 ~ core[690e]::panicking)), args: None, infer_args: true }, PathSegment { ident: panic#13, hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).174), res: Def(Fn, DefId(2:8292 ~ core[690e]::panicking::panic)), args: None, infer_args: true }] })), span: /home/centri/.rustup/toolchains/nightly-2023-05-05-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/macros/mod.rs:773:9: 773:33 (#13) }, [Expr { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).175), kind: Lit(Spanned { node: Str("not yet implemented", Cooked), span: /home/centri/.rustup/toolchains/nightly-2023-05-05-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/macros/mod.rs:773:34: 773:55 (#13) }), span: /home/centri/.rustup/toolchains/nightly-2023-05-05-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/macros/mod.rs:773:34: 773:55 (#13) }]), span: /home/centri/.rustup/toolchains/nightly-2023-05-05-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/macros/mod.rs:773:9: 773:56 (#13) }]), span: $DIR/endian_bytes.rs:30:5: 30:33 (#0) }), span: $DIR/endian_bytes.rs:30:5: 30:34 (#0) }, Stmt { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).188), kind: Semi(Expr { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).177), kind: Call(Expr { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).178), kind: Path(TypeRelative(Ty { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).180), kind: Path(Resolved(None, Path { span: $DIR/endian_bytes.rs:31:5: 31:8 (#0), res: PrimTy(Float(F32)), segments: [PathSegment { ident: f32#0, hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).179), res: PrimTy(Float(F32)), args: None, infer_args: true }] })), span: $DIR/endian_bytes.rs:31:5: 31:8 (#0) }, PathSegment { ident: from_ne_bytes#0, hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).181), res: Err, args: None, infer_args: true })), span: $DIR/endian_bytes.rs:31:5: 31:23 (#0) }, [Expr { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).182), kind: Call(Expr { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).183), kind: Path(Resolved(None, Path { span: /home/centri/.rustup/toolchains/nightly-2023-05-05-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/macros/mod.rs:773:9: 773:33 (#14), res: Def(Fn, DefId(2:8292 ~ core[690e]::panicking::panic)), segments: [PathSegment { ident: $crate#14, hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).184), res: Err, args: None, infer_args: true }, PathSegment { ident: panicking#14, hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).185), res: Def(Mod, DefId(2:8281 ~ core[690e]::panicking)), args: None, infer_args: true }, PathSegment { ident: panic#14, hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).186), res: Def(Fn, DefId(2:8292 ~ core[690e]::panicking::panic)), args: None, infer_args: true }] })), span: /home/centri/.rustup/toolchains/nightly-2023-05-05-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/macros/mod.rs:773:9: 773:33 (#14) }, [Expr { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).187), kind: Lit(Spanned { node: Str("not yet implemented", Cooked), span: /home/centri/.rustup/toolchains/nightly-2023-05-05-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/macros/mod.rs:773:34: 773:55 (#14) }), span: /home/centri/.rustup/toolchains/nightly-2023-05-05-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/macros/mod.rs:773:34: 773:55 (#14) }]), span: /home/centri/.rustup/toolchains/nightly-2023-05-05-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/macros/mod.rs:773:9: 773:56 (#14) }]), span: $DIR/endian_bytes.rs:31:5: 31:32 (#0) }), span: $DIR/endian_bytes.rs:31:5: 31:33 (#0) }, Stmt { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).200), kind: Semi(Expr { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).189), kind: Call(Expr { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).190), kind: Path(TypeRelative(Ty { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).192), kind: Path(Resolved(None, Path { span: $DIR/endian_bytes.rs:32:5: 32:8 (#0), res: PrimTy(Float(F64)), segments: [PathSegment { ident: f64#0, hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).191), res: PrimTy(Float(F64)), args: None, infer_args: true }] })), span: $DIR/endian_bytes.rs:32:5: 32:8 (#0) }, PathSegment { ident: from_ne_bytes#0, hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).193), res: Err, args: None, infer_args: true })), span: $DIR/endian_bytes.rs:32:5: 32:23 (#0) }, [Expr { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).194), kind: Call(Expr { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).195), kind: Path(Resolved(None, Path { span: /home/centri/.rustup/toolchains/nightly-2023-05-05-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/macros/mod.rs:773:9: 773:33 (#15), res: Def(Fn, DefId(2:8292 ~ core[690e]::panicking::panic)), segments: [PathSegment { ident: $crate#15, hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).196), res: Err, args: None, infer_args: true }, PathSegment { ident: panicking#15, hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).197), res: Def(Mod, DefId(2:8281 ~ core[690e]::panicking)), args: None, infer_args: true }, PathSegment { ident: panic#15, hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).198), res: Def(Fn, DefId(2:8292 ~ core[690e]::panicking::panic)), args: None, infer_args: true }] })), span: /home/centri/.rustup/toolchains/nightly-2023-05-05-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/macros/mod.rs:773:9: 773:33 (#15) }, [Expr { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).199), kind: Lit(Spanned { node: Str("not yet implemented", Cooked), span: /home/centri/.rustup/toolchains/nightly-2023-05-05-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/macros/mod.rs:773:34: 773:55 (#15) }), span: /home/centri/.rustup/toolchains/nightly-2023-05-05-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/macros/mod.rs:773:34: 773:55 (#15) }]), span: /home/centri/.rustup/toolchains/nightly-2023-05-05-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/macros/mod.rs:773:9: 773:56 (#15) }]), span: $DIR/endian_bytes.rs:32:5: 32:32 (#0) }), span: $DIR/endian_bytes.rs:32:5: 32:33 (#0) }], expr: None, hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).201), rules: DefaultBlock, span: $DIR/endian_bytes.rs:6:11: 33:2 (#0), targeted_by_break: false }, None), span: $DIR/endian_bytes.rs:6:11: 33:2 (#0) } + = note: `-D clippy::host-endian-bytes` implied by `-D warnings` + +error: use of the method `to_ne_bytes` + --> $DIR/endian_bytes.rs:7:5 + | +LL | 2u8.to_ne_bytes(); + | ^^^^^^^^^^^^^^^^^ + | + = help: consider specifying the desired endianness + +error: use of the method `from_ne_bytes` + --> $DIR/endian_bytes.rs:7:5 + | +LL | 2u8.to_ne_bytes(); + | ^^^ + | + = help: consider specifying the desired endianness: Expr { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).3), kind: Lit(Spanned { node: Int(2, Unsigned(U8)), span: $DIR/endian_bytes.rs:7:5: 7:8 (#0) }), span: $DIR/endian_bytes.rs:7:5: 7:8 (#0) } + +error: use of the method `to_ne_bytes` + --> $DIR/endian_bytes.rs:8:5 + | +LL | 2i8.to_ne_bytes(); + | ^^^^^^^^^^^^^^^^^ + | + = help: consider specifying the desired endianness + +error: use of the method `from_ne_bytes` + --> $DIR/endian_bytes.rs:8:5 + | +LL | 2i8.to_ne_bytes(); + | ^^^ + | + = help: consider specifying the desired endianness: Expr { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).7), kind: Lit(Spanned { node: Int(2, Signed(I8)), span: $DIR/endian_bytes.rs:8:5: 8:8 (#0) }), span: $DIR/endian_bytes.rs:8:5: 8:8 (#0) } + +error: use of the method `to_ne_bytes` + --> $DIR/endian_bytes.rs:9:5 + | +LL | 2u16.to_ne_bytes(); + | ^^^^^^^^^^^^^^^^^^ + | + = help: consider specifying the desired endianness + +error: use of the method `from_ne_bytes` + --> $DIR/endian_bytes.rs:9:5 + | +LL | 2u16.to_ne_bytes(); + | ^^^^ + | + = help: consider specifying the desired endianness: Expr { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).11), kind: Lit(Spanned { node: Int(2, Unsigned(U16)), span: $DIR/endian_bytes.rs:9:5: 9:9 (#0) }), span: $DIR/endian_bytes.rs:9:5: 9:9 (#0) } + +error: use of the method `to_ne_bytes` + --> $DIR/endian_bytes.rs:10:5 + | +LL | 2i16.to_ne_bytes(); + | ^^^^^^^^^^^^^^^^^^ + | + = help: consider specifying the desired endianness + +error: use of the method `from_ne_bytes` + --> $DIR/endian_bytes.rs:10:5 + | +LL | 2i16.to_ne_bytes(); + | ^^^^ + | + = help: consider specifying the desired endianness: Expr { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).15), kind: Lit(Spanned { node: Int(2, Signed(I16)), span: $DIR/endian_bytes.rs:10:5: 10:9 (#0) }), span: $DIR/endian_bytes.rs:10:5: 10:9 (#0) } + +error: use of the method `to_ne_bytes` + --> $DIR/endian_bytes.rs:11:5 + | +LL | 2u32.to_ne_bytes(); + | ^^^^^^^^^^^^^^^^^^ + | + = help: consider specifying the desired endianness + +error: use of the method `from_ne_bytes` + --> $DIR/endian_bytes.rs:11:5 + | +LL | 2u32.to_ne_bytes(); + | ^^^^ + | + = help: consider specifying the desired endianness: Expr { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).19), kind: Lit(Spanned { node: Int(2, Unsigned(U32)), span: $DIR/endian_bytes.rs:11:5: 11:9 (#0) }), span: $DIR/endian_bytes.rs:11:5: 11:9 (#0) } + +error: use of the method `to_ne_bytes` + --> $DIR/endian_bytes.rs:12:5 + | +LL | 2i32.to_ne_bytes(); + | ^^^^^^^^^^^^^^^^^^ + | + = help: consider specifying the desired endianness + +error: use of the method `from_ne_bytes` + --> $DIR/endian_bytes.rs:12:5 + | +LL | 2i32.to_ne_bytes(); + | ^^^^ + | + = help: consider specifying the desired endianness: Expr { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).23), kind: Lit(Spanned { node: Int(2, Signed(I32)), span: $DIR/endian_bytes.rs:12:5: 12:9 (#0) }), span: $DIR/endian_bytes.rs:12:5: 12:9 (#0) } + +error: use of the method `to_ne_bytes` + --> $DIR/endian_bytes.rs:13:5 + | +LL | 2u64.to_ne_bytes(); + | ^^^^^^^^^^^^^^^^^^ + | + = help: consider specifying the desired endianness + +error: use of the method `from_ne_bytes` + --> $DIR/endian_bytes.rs:13:5 + | +LL | 2u64.to_ne_bytes(); + | ^^^^ + | + = help: consider specifying the desired endianness: Expr { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).27), kind: Lit(Spanned { node: Int(2, Unsigned(U64)), span: $DIR/endian_bytes.rs:13:5: 13:9 (#0) }), span: $DIR/endian_bytes.rs:13:5: 13:9 (#0) } + +error: use of the method `to_ne_bytes` + --> $DIR/endian_bytes.rs:14:5 + | +LL | 2i64.to_ne_bytes(); + | ^^^^^^^^^^^^^^^^^^ + | + = help: consider specifying the desired endianness + +error: use of the method `from_ne_bytes` + --> $DIR/endian_bytes.rs:14:5 + | +LL | 2i64.to_ne_bytes(); + | ^^^^ + | + = help: consider specifying the desired endianness: Expr { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).31), kind: Lit(Spanned { node: Int(2, Signed(I64)), span: $DIR/endian_bytes.rs:14:5: 14:9 (#0) }), span: $DIR/endian_bytes.rs:14:5: 14:9 (#0) } + +error: use of the method `to_ne_bytes` + --> $DIR/endian_bytes.rs:15:5 + | +LL | 2u128.to_ne_bytes(); + | ^^^^^^^^^^^^^^^^^^^ + | + = help: consider specifying the desired endianness + +error: use of the method `from_ne_bytes` + --> $DIR/endian_bytes.rs:15:5 + | +LL | 2u128.to_ne_bytes(); + | ^^^^^ + | + = help: consider specifying the desired endianness: Expr { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).35), kind: Lit(Spanned { node: Int(2, Unsigned(U128)), span: $DIR/endian_bytes.rs:15:5: 15:10 (#0) }), span: $DIR/endian_bytes.rs:15:5: 15:10 (#0) } + +error: use of the method `to_ne_bytes` + --> $DIR/endian_bytes.rs:16:5 + | +LL | 2i128.to_ne_bytes(); + | ^^^^^^^^^^^^^^^^^^^ + | + = help: consider specifying the desired endianness + +error: use of the method `from_ne_bytes` + --> $DIR/endian_bytes.rs:16:5 + | +LL | 2i128.to_ne_bytes(); + | ^^^^^ + | + = help: consider specifying the desired endianness: Expr { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).39), kind: Lit(Spanned { node: Int(2, Signed(I128)), span: $DIR/endian_bytes.rs:16:5: 16:10 (#0) }), span: $DIR/endian_bytes.rs:16:5: 16:10 (#0) } + +error: use of the method `to_ne_bytes` + --> $DIR/endian_bytes.rs:17:5 + | +LL | 2usize.to_ne_bytes(); + | ^^^^^^^^^^^^^^^^^^^^ + | + = help: consider specifying the desired endianness + +error: use of the method `from_ne_bytes` + --> $DIR/endian_bytes.rs:17:5 + | +LL | 2usize.to_ne_bytes(); + | ^^^^^^ + | + = help: consider specifying the desired endianness: Expr { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).43), kind: Lit(Spanned { node: Int(2, Unsigned(Usize)), span: $DIR/endian_bytes.rs:17:5: 17:11 (#0) }), span: $DIR/endian_bytes.rs:17:5: 17:11 (#0) } + +error: use of the method `to_ne_bytes` + --> $DIR/endian_bytes.rs:18:5 + | +LL | 2isize.to_ne_bytes(); + | ^^^^^^^^^^^^^^^^^^^^ + | + = help: consider specifying the desired endianness + +error: use of the method `from_ne_bytes` + --> $DIR/endian_bytes.rs:18:5 + | +LL | 2isize.to_ne_bytes(); + | ^^^^^^ + | + = help: consider specifying the desired endianness: Expr { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).47), kind: Lit(Spanned { node: Int(2, Signed(Isize)), span: $DIR/endian_bytes.rs:18:5: 18:11 (#0) }), span: $DIR/endian_bytes.rs:18:5: 18:11 (#0) } + +error: use of the method `to_ne_bytes` + --> $DIR/endian_bytes.rs:19:5 + | +LL | 2.0f32.to_ne_bytes(); + | ^^^^^^^^^^^^^^^^^^^^ + | + = help: consider specifying the desired endianness + +error: use of the method `from_ne_bytes` + --> $DIR/endian_bytes.rs:19:5 + | +LL | 2.0f32.to_ne_bytes(); + | ^^^^^^ + | + = help: consider specifying the desired endianness: Expr { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).51), kind: Lit(Spanned { node: Float("2.0", Suffixed(F32)), span: $DIR/endian_bytes.rs:19:5: 19:11 (#0) }), span: $DIR/endian_bytes.rs:19:5: 19:11 (#0) } + +error: use of the method `to_ne_bytes` + --> $DIR/endian_bytes.rs:20:5 + | +LL | 2.0f64.to_ne_bytes(); + | ^^^^^^^^^^^^^^^^^^^^ + | + = help: consider specifying the desired endianness + +error: use of the method `from_ne_bytes` + --> $DIR/endian_bytes.rs:20:5 + | +LL | 2.0f64.to_ne_bytes(); + | ^^^^^^ + | + = help: consider specifying the desired endianness: Expr { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).55), kind: Lit(Spanned { node: Float("2.0", Suffixed(F64)), span: $DIR/endian_bytes.rs:20:5: 20:11 (#0) }), span: $DIR/endian_bytes.rs:20:5: 20:11 (#0) } + +error: use of the method `from_ne_bytes` + --> $DIR/endian_bytes.rs:21:5 + | +LL | u8::from_ne_bytes(todo!()); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: consider specifying the desired endianness: Expr { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).57), kind: Call(Expr { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).58), kind: Path(TypeRelative(Ty { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).60), kind: Path(Resolved(None, Path { span: $DIR/endian_bytes.rs:21:5: 21:7 (#0), res: PrimTy(Uint(U8)), segments: [PathSegment { ident: u8#0, hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).59), res: PrimTy(Uint(U8)), args: None, infer_args: true }] })), span: $DIR/endian_bytes.rs:21:5: 21:7 (#0) }, PathSegment { ident: from_ne_bytes#0, hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).61), res: Err, args: None, infer_args: true })), span: $DIR/endian_bytes.rs:21:5: 21:22 (#0) }, [Expr { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).62), kind: Call(Expr { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).63), kind: Path(Resolved(None, Path { span: /home/centri/.rustup/toolchains/nightly-2023-05-05-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/macros/mod.rs:773:9: 773:33 (#4), res: Def(Fn, DefId(2:8292 ~ core[690e]::panicking::panic)), segments: [PathSegment { ident: $crate#4, hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).64), res: Err, args: None, infer_args: true }, PathSegment { ident: panicking#4, hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).65), res: Def(Mod, DefId(2:8281 ~ core[690e]::panicking)), args: None, infer_args: true }, PathSegment { ident: panic#4, hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).66), res: Def(Fn, DefId(2:8292 ~ core[690e]::panicking::panic)), args: None, infer_args: true }] })), span: /home/centri/.rustup/toolchains/nightly-2023-05-05-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/macros/mod.rs:773:9: 773:33 (#4) }, [Expr { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).67), kind: Lit(Spanned { node: Str("not yet implemented", Cooked), span: /home/centri/.rustup/toolchains/nightly-2023-05-05-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/macros/mod.rs:773:34: 773:55 (#4) }), span: /home/centri/.rustup/toolchains/nightly-2023-05-05-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/macros/mod.rs:773:34: 773:55 (#4) }]), span: /home/centri/.rustup/toolchains/nightly-2023-05-05-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/macros/mod.rs:773:9: 773:56 (#4) }]), span: $DIR/endian_bytes.rs:21:5: 21:31 (#0) } + +error: use of the method `from_ne_bytes` + --> $DIR/endian_bytes.rs:21:5 + | +LL | u8::from_ne_bytes(todo!()); + | ^^^^^^^^^^^^^^^^^ + | + = help: consider specifying the desired endianness: Expr { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).58), kind: Path(TypeRelative(Ty { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).60), kind: Path(Resolved(None, Path { span: $DIR/endian_bytes.rs:21:5: 21:7 (#0), res: PrimTy(Uint(U8)), segments: [PathSegment { ident: u8#0, hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).59), res: PrimTy(Uint(U8)), args: None, infer_args: true }] })), span: $DIR/endian_bytes.rs:21:5: 21:7 (#0) }, PathSegment { ident: from_ne_bytes#0, hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).61), res: Err, args: None, infer_args: true })), span: $DIR/endian_bytes.rs:21:5: 21:22 (#0) } + +error: use of the method `from_ne_bytes` + --> $DIR/endian_bytes.rs:21:23 + | +LL | u8::from_ne_bytes(todo!()); + | ^^^^^^^ + | + = help: consider specifying the desired endianness: Expr { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).62), kind: Call(Expr { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).63), kind: Path(Resolved(None, Path { span: /home/centri/.rustup/toolchains/nightly-2023-05-05-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/macros/mod.rs:773:9: 773:33 (#4), res: Def(Fn, DefId(2:8292 ~ core[690e]::panicking::panic)), segments: [PathSegment { ident: $crate#4, hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).64), res: Err, args: None, infer_args: true }, PathSegment { ident: panicking#4, hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).65), res: Def(Mod, DefId(2:8281 ~ core[690e]::panicking)), args: None, infer_args: true }, PathSegment { ident: panic#4, hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).66), res: Def(Fn, DefId(2:8292 ~ core[690e]::panicking::panic)), args: None, infer_args: true }] })), span: /home/centri/.rustup/toolchains/nightly-2023-05-05-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/macros/mod.rs:773:9: 773:33 (#4) }, [Expr { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).67), kind: Lit(Spanned { node: Str("not yet implemented", Cooked), span: /home/centri/.rustup/toolchains/nightly-2023-05-05-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/macros/mod.rs:773:34: 773:55 (#4) }), span: /home/centri/.rustup/toolchains/nightly-2023-05-05-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/macros/mod.rs:773:34: 773:55 (#4) }]), span: /home/centri/.rustup/toolchains/nightly-2023-05-05-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/macros/mod.rs:773:9: 773:56 (#4) } + = note: this error originates in the macro `todo` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: use of the method `from_ne_bytes` + --> $DIR/endian_bytes.rs:21:23 + | +LL | u8::from_ne_bytes(todo!()); + | ^^^^^^^ + | + = help: consider specifying the desired endianness: Expr { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).63), kind: Path(Resolved(None, Path { span: /home/centri/.rustup/toolchains/nightly-2023-05-05-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/macros/mod.rs:773:9: 773:33 (#4), res: Def(Fn, DefId(2:8292 ~ core[690e]::panicking::panic)), segments: [PathSegment { ident: $crate#4, hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).64), res: Err, args: None, infer_args: true }, PathSegment { ident: panicking#4, hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).65), res: Def(Mod, DefId(2:8281 ~ core[690e]::panicking)), args: None, infer_args: true }, PathSegment { ident: panic#4, hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).66), res: Def(Fn, DefId(2:8292 ~ core[690e]::panicking::panic)), args: None, infer_args: true }] })), span: /home/centri/.rustup/toolchains/nightly-2023-05-05-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/macros/mod.rs:773:9: 773:33 (#4) } + = note: this error originates in the macro `todo` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: use of the method `from_ne_bytes` + --> $DIR/endian_bytes.rs:21:23 + | +LL | u8::from_ne_bytes(todo!()); + | ^^^^^^^ + | + = help: consider specifying the desired endianness: Expr { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).67), kind: Lit(Spanned { node: Str("not yet implemented", Cooked), span: /home/centri/.rustup/toolchains/nightly-2023-05-05-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/macros/mod.rs:773:34: 773:55 (#4) }), span: /home/centri/.rustup/toolchains/nightly-2023-05-05-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/macros/mod.rs:773:34: 773:55 (#4) } + = note: this error originates in the macro `todo` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: use of the method `from_ne_bytes` + --> $DIR/endian_bytes.rs:22:5 + | +LL | i8::from_ne_bytes(todo!()); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: consider specifying the desired endianness: Expr { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).69), kind: Call(Expr { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).70), kind: Path(TypeRelative(Ty { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).72), kind: Path(Resolved(None, Path { span: $DIR/endian_bytes.rs:22:5: 22:7 (#0), res: PrimTy(Int(I8)), segments: [PathSegment { ident: i8#0, hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).71), res: PrimTy(Int(I8)), args: None, infer_args: true }] })), span: $DIR/endian_bytes.rs:22:5: 22:7 (#0) }, PathSegment { ident: from_ne_bytes#0, hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).73), res: Err, args: None, infer_args: true })), span: $DIR/endian_bytes.rs:22:5: 22:22 (#0) }, [Expr { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).74), kind: Call(Expr { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).75), kind: Path(Resolved(None, Path { span: /home/centri/.rustup/toolchains/nightly-2023-05-05-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/macros/mod.rs:773:9: 773:33 (#5), res: Def(Fn, DefId(2:8292 ~ core[690e]::panicking::panic)), segments: [PathSegment { ident: $crate#5, hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).76), res: Err, args: None, infer_args: true }, PathSegment { ident: panicking#5, hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).77), res: Def(Mod, DefId(2:8281 ~ core[690e]::panicking)), args: None, infer_args: true }, PathSegment { ident: panic#5, hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).78), res: Def(Fn, DefId(2:8292 ~ core[690e]::panicking::panic)), args: None, infer_args: true }] })), span: /home/centri/.rustup/toolchains/nightly-2023-05-05-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/macros/mod.rs:773:9: 773:33 (#5) }, [Expr { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).79), kind: Lit(Spanned { node: Str("not yet implemented", Cooked), span: /home/centri/.rustup/toolchains/nightly-2023-05-05-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/macros/mod.rs:773:34: 773:55 (#5) }), span: /home/centri/.rustup/toolchains/nightly-2023-05-05-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/macros/mod.rs:773:34: 773:55 (#5) }]), span: /home/centri/.rustup/toolchains/nightly-2023-05-05-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/macros/mod.rs:773:9: 773:56 (#5) }]), span: $DIR/endian_bytes.rs:22:5: 22:31 (#0) } + +error: use of the method `from_ne_bytes` + --> $DIR/endian_bytes.rs:22:5 + | +LL | i8::from_ne_bytes(todo!()); + | ^^^^^^^^^^^^^^^^^ + | + = help: consider specifying the desired endianness: Expr { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).70), kind: Path(TypeRelative(Ty { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).72), kind: Path(Resolved(None, Path { span: $DIR/endian_bytes.rs:22:5: 22:7 (#0), res: PrimTy(Int(I8)), segments: [PathSegment { ident: i8#0, hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).71), res: PrimTy(Int(I8)), args: None, infer_args: true }] })), span: $DIR/endian_bytes.rs:22:5: 22:7 (#0) }, PathSegment { ident: from_ne_bytes#0, hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).73), res: Err, args: None, infer_args: true })), span: $DIR/endian_bytes.rs:22:5: 22:22 (#0) } + +error: use of the method `from_ne_bytes` + --> $DIR/endian_bytes.rs:22:23 + | +LL | i8::from_ne_bytes(todo!()); + | ^^^^^^^ + | + = help: consider specifying the desired endianness: Expr { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).74), kind: Call(Expr { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).75), kind: Path(Resolved(None, Path { span: /home/centri/.rustup/toolchains/nightly-2023-05-05-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/macros/mod.rs:773:9: 773:33 (#5), res: Def(Fn, DefId(2:8292 ~ core[690e]::panicking::panic)), segments: [PathSegment { ident: $crate#5, hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).76), res: Err, args: None, infer_args: true }, PathSegment { ident: panicking#5, hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).77), res: Def(Mod, DefId(2:8281 ~ core[690e]::panicking)), args: None, infer_args: true }, PathSegment { ident: panic#5, hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).78), res: Def(Fn, DefId(2:8292 ~ core[690e]::panicking::panic)), args: None, infer_args: true }] })), span: /home/centri/.rustup/toolchains/nightly-2023-05-05-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/macros/mod.rs:773:9: 773:33 (#5) }, [Expr { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).79), kind: Lit(Spanned { node: Str("not yet implemented", Cooked), span: /home/centri/.rustup/toolchains/nightly-2023-05-05-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/macros/mod.rs:773:34: 773:55 (#5) }), span: /home/centri/.rustup/toolchains/nightly-2023-05-05-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/macros/mod.rs:773:34: 773:55 (#5) }]), span: /home/centri/.rustup/toolchains/nightly-2023-05-05-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/macros/mod.rs:773:9: 773:56 (#5) } + = note: this error originates in the macro `todo` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: use of the method `from_ne_bytes` + --> $DIR/endian_bytes.rs:22:23 + | +LL | i8::from_ne_bytes(todo!()); + | ^^^^^^^ + | + = help: consider specifying the desired endianness: Expr { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).75), kind: Path(Resolved(None, Path { span: /home/centri/.rustup/toolchains/nightly-2023-05-05-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/macros/mod.rs:773:9: 773:33 (#5), res: Def(Fn, DefId(2:8292 ~ core[690e]::panicking::panic)), segments: [PathSegment { ident: $crate#5, hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).76), res: Err, args: None, infer_args: true }, PathSegment { ident: panicking#5, hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).77), res: Def(Mod, DefId(2:8281 ~ core[690e]::panicking)), args: None, infer_args: true }, PathSegment { ident: panic#5, hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).78), res: Def(Fn, DefId(2:8292 ~ core[690e]::panicking::panic)), args: None, infer_args: true }] })), span: /home/centri/.rustup/toolchains/nightly-2023-05-05-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/macros/mod.rs:773:9: 773:33 (#5) } + = note: this error originates in the macro `todo` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: use of the method `from_ne_bytes` + --> $DIR/endian_bytes.rs:22:23 + | +LL | i8::from_ne_bytes(todo!()); + | ^^^^^^^ + | + = help: consider specifying the desired endianness: Expr { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).79), kind: Lit(Spanned { node: Str("not yet implemented", Cooked), span: /home/centri/.rustup/toolchains/nightly-2023-05-05-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/macros/mod.rs:773:34: 773:55 (#5) }), span: /home/centri/.rustup/toolchains/nightly-2023-05-05-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/macros/mod.rs:773:34: 773:55 (#5) } + = note: this error originates in the macro `todo` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: use of the method `from_ne_bytes` + --> $DIR/endian_bytes.rs:23:5 + | +LL | u16::from_ne_bytes(todo!()); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: consider specifying the desired endianness: Expr { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).81), kind: Call(Expr { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).82), kind: Path(TypeRelative(Ty { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).84), kind: Path(Resolved(None, Path { span: $DIR/endian_bytes.rs:23:5: 23:8 (#0), res: PrimTy(Uint(U16)), segments: [PathSegment { ident: u16#0, hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).83), res: PrimTy(Uint(U16)), args: None, infer_args: true }] })), span: $DIR/endian_bytes.rs:23:5: 23:8 (#0) }, PathSegment { ident: from_ne_bytes#0, hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).85), res: Err, args: None, infer_args: true })), span: $DIR/endian_bytes.rs:23:5: 23:23 (#0) }, [Expr { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).86), kind: Call(Expr { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).87), kind: Path(Resolved(None, Path { span: /home/centri/.rustup/toolchains/nightly-2023-05-05-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/macros/mod.rs:773:9: 773:33 (#6), res: Def(Fn, DefId(2:8292 ~ core[690e]::panicking::panic)), segments: [PathSegment { ident: $crate#6, hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).88), res: Err, args: None, infer_args: true }, PathSegment { ident: panicking#6, hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).89), res: Def(Mod, DefId(2:8281 ~ core[690e]::panicking)), args: None, infer_args: true }, PathSegment { ident: panic#6, hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).90), res: Def(Fn, DefId(2:8292 ~ core[690e]::panicking::panic)), args: None, infer_args: true }] })), span: /home/centri/.rustup/toolchains/nightly-2023-05-05-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/macros/mod.rs:773:9: 773:33 (#6) }, [Expr { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).91), kind: Lit(Spanned { node: Str("not yet implemented", Cooked), span: /home/centri/.rustup/toolchains/nightly-2023-05-05-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/macros/mod.rs:773:34: 773:55 (#6) }), span: /home/centri/.rustup/toolchains/nightly-2023-05-05-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/macros/mod.rs:773:34: 773:55 (#6) }]), span: /home/centri/.rustup/toolchains/nightly-2023-05-05-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/macros/mod.rs:773:9: 773:56 (#6) }]), span: $DIR/endian_bytes.rs:23:5: 23:32 (#0) } + +error: use of the method `from_ne_bytes` + --> $DIR/endian_bytes.rs:23:5 + | +LL | u16::from_ne_bytes(todo!()); + | ^^^^^^^^^^^^^^^^^^ + | + = help: consider specifying the desired endianness: Expr { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).82), kind: Path(TypeRelative(Ty { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).84), kind: Path(Resolved(None, Path { span: $DIR/endian_bytes.rs:23:5: 23:8 (#0), res: PrimTy(Uint(U16)), segments: [PathSegment { ident: u16#0, hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).83), res: PrimTy(Uint(U16)), args: None, infer_args: true }] })), span: $DIR/endian_bytes.rs:23:5: 23:8 (#0) }, PathSegment { ident: from_ne_bytes#0, hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).85), res: Err, args: None, infer_args: true })), span: $DIR/endian_bytes.rs:23:5: 23:23 (#0) } + +error: use of the method `from_ne_bytes` + --> $DIR/endian_bytes.rs:23:24 + | +LL | u16::from_ne_bytes(todo!()); + | ^^^^^^^ + | + = help: consider specifying the desired endianness: Expr { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).86), kind: Call(Expr { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).87), kind: Path(Resolved(None, Path { span: /home/centri/.rustup/toolchains/nightly-2023-05-05-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/macros/mod.rs:773:9: 773:33 (#6), res: Def(Fn, DefId(2:8292 ~ core[690e]::panicking::panic)), segments: [PathSegment { ident: $crate#6, hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).88), res: Err, args: None, infer_args: true }, PathSegment { ident: panicking#6, hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).89), res: Def(Mod, DefId(2:8281 ~ core[690e]::panicking)), args: None, infer_args: true }, PathSegment { ident: panic#6, hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).90), res: Def(Fn, DefId(2:8292 ~ core[690e]::panicking::panic)), args: None, infer_args: true }] })), span: /home/centri/.rustup/toolchains/nightly-2023-05-05-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/macros/mod.rs:773:9: 773:33 (#6) }, [Expr { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).91), kind: Lit(Spanned { node: Str("not yet implemented", Cooked), span: /home/centri/.rustup/toolchains/nightly-2023-05-05-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/macros/mod.rs:773:34: 773:55 (#6) }), span: /home/centri/.rustup/toolchains/nightly-2023-05-05-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/macros/mod.rs:773:34: 773:55 (#6) }]), span: /home/centri/.rustup/toolchains/nightly-2023-05-05-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/macros/mod.rs:773:9: 773:56 (#6) } + = note: this error originates in the macro `todo` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: use of the method `from_ne_bytes` + --> $DIR/endian_bytes.rs:23:24 + | +LL | u16::from_ne_bytes(todo!()); + | ^^^^^^^ + | + = help: consider specifying the desired endianness: Expr { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).87), kind: Path(Resolved(None, Path { span: /home/centri/.rustup/toolchains/nightly-2023-05-05-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/macros/mod.rs:773:9: 773:33 (#6), res: Def(Fn, DefId(2:8292 ~ core[690e]::panicking::panic)), segments: [PathSegment { ident: $crate#6, hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).88), res: Err, args: None, infer_args: true }, PathSegment { ident: panicking#6, hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).89), res: Def(Mod, DefId(2:8281 ~ core[690e]::panicking)), args: None, infer_args: true }, PathSegment { ident: panic#6, hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).90), res: Def(Fn, DefId(2:8292 ~ core[690e]::panicking::panic)), args: None, infer_args: true }] })), span: /home/centri/.rustup/toolchains/nightly-2023-05-05-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/macros/mod.rs:773:9: 773:33 (#6) } + = note: this error originates in the macro `todo` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: use of the method `from_ne_bytes` + --> $DIR/endian_bytes.rs:23:24 + | +LL | u16::from_ne_bytes(todo!()); + | ^^^^^^^ + | + = help: consider specifying the desired endianness: Expr { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).91), kind: Lit(Spanned { node: Str("not yet implemented", Cooked), span: /home/centri/.rustup/toolchains/nightly-2023-05-05-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/macros/mod.rs:773:34: 773:55 (#6) }), span: /home/centri/.rustup/toolchains/nightly-2023-05-05-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/macros/mod.rs:773:34: 773:55 (#6) } + = note: this error originates in the macro `todo` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: use of the method `from_ne_bytes` + --> $DIR/endian_bytes.rs:24:5 + | +LL | i16::from_ne_bytes(todo!()); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: consider specifying the desired endianness: Expr { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).93), kind: Call(Expr { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).94), kind: Path(TypeRelative(Ty { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).96), kind: Path(Resolved(None, Path { span: $DIR/endian_bytes.rs:24:5: 24:8 (#0), res: PrimTy(Int(I16)), segments: [PathSegment { ident: i16#0, hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).95), res: PrimTy(Int(I16)), args: None, infer_args: true }] })), span: $DIR/endian_bytes.rs:24:5: 24:8 (#0) }, PathSegment { ident: from_ne_bytes#0, hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).97), res: Err, args: None, infer_args: true })), span: $DIR/endian_bytes.rs:24:5: 24:23 (#0) }, [Expr { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).98), kind: Call(Expr { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).99), kind: Path(Resolved(None, Path { span: /home/centri/.rustup/toolchains/nightly-2023-05-05-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/macros/mod.rs:773:9: 773:33 (#7), res: Def(Fn, DefId(2:8292 ~ core[690e]::panicking::panic)), segments: [PathSegment { ident: $crate#7, hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).100), res: Err, args: None, infer_args: true }, PathSegment { ident: panicking#7, hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).101), res: Def(Mod, DefId(2:8281 ~ core[690e]::panicking)), args: None, infer_args: true }, PathSegment { ident: panic#7, hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).102), res: Def(Fn, DefId(2:8292 ~ core[690e]::panicking::panic)), args: None, infer_args: true }] })), span: /home/centri/.rustup/toolchains/nightly-2023-05-05-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/macros/mod.rs:773:9: 773:33 (#7) }, [Expr { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).103), kind: Lit(Spanned { node: Str("not yet implemented", Cooked), span: /home/centri/.rustup/toolchains/nightly-2023-05-05-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/macros/mod.rs:773:34: 773:55 (#7) }), span: /home/centri/.rustup/toolchains/nightly-2023-05-05-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/macros/mod.rs:773:34: 773:55 (#7) }]), span: /home/centri/.rustup/toolchains/nightly-2023-05-05-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/macros/mod.rs:773:9: 773:56 (#7) }]), span: $DIR/endian_bytes.rs:24:5: 24:32 (#0) } + +error: use of the method `from_ne_bytes` + --> $DIR/endian_bytes.rs:24:5 + | +LL | i16::from_ne_bytes(todo!()); + | ^^^^^^^^^^^^^^^^^^ + | + = help: consider specifying the desired endianness: Expr { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).94), kind: Path(TypeRelative(Ty { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).96), kind: Path(Resolved(None, Path { span: $DIR/endian_bytes.rs:24:5: 24:8 (#0), res: PrimTy(Int(I16)), segments: [PathSegment { ident: i16#0, hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).95), res: PrimTy(Int(I16)), args: None, infer_args: true }] })), span: $DIR/endian_bytes.rs:24:5: 24:8 (#0) }, PathSegment { ident: from_ne_bytes#0, hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).97), res: Err, args: None, infer_args: true })), span: $DIR/endian_bytes.rs:24:5: 24:23 (#0) } + +error: use of the method `from_ne_bytes` + --> $DIR/endian_bytes.rs:24:24 + | +LL | i16::from_ne_bytes(todo!()); + | ^^^^^^^ + | + = help: consider specifying the desired endianness: Expr { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).98), kind: Call(Expr { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).99), kind: Path(Resolved(None, Path { span: /home/centri/.rustup/toolchains/nightly-2023-05-05-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/macros/mod.rs:773:9: 773:33 (#7), res: Def(Fn, DefId(2:8292 ~ core[690e]::panicking::panic)), segments: [PathSegment { ident: $crate#7, hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).100), res: Err, args: None, infer_args: true }, PathSegment { ident: panicking#7, hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).101), res: Def(Mod, DefId(2:8281 ~ core[690e]::panicking)), args: None, infer_args: true }, PathSegment { ident: panic#7, hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).102), res: Def(Fn, DefId(2:8292 ~ core[690e]::panicking::panic)), args: None, infer_args: true }] })), span: /home/centri/.rustup/toolchains/nightly-2023-05-05-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/macros/mod.rs:773:9: 773:33 (#7) }, [Expr { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).103), kind: Lit(Spanned { node: Str("not yet implemented", Cooked), span: /home/centri/.rustup/toolchains/nightly-2023-05-05-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/macros/mod.rs:773:34: 773:55 (#7) }), span: /home/centri/.rustup/toolchains/nightly-2023-05-05-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/macros/mod.rs:773:34: 773:55 (#7) }]), span: /home/centri/.rustup/toolchains/nightly-2023-05-05-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/macros/mod.rs:773:9: 773:56 (#7) } + = note: this error originates in the macro `todo` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: use of the method `from_ne_bytes` + --> $DIR/endian_bytes.rs:24:24 + | +LL | i16::from_ne_bytes(todo!()); + | ^^^^^^^ + | + = help: consider specifying the desired endianness: Expr { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).99), kind: Path(Resolved(None, Path { span: /home/centri/.rustup/toolchains/nightly-2023-05-05-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/macros/mod.rs:773:9: 773:33 (#7), res: Def(Fn, DefId(2:8292 ~ core[690e]::panicking::panic)), segments: [PathSegment { ident: $crate#7, hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).100), res: Err, args: None, infer_args: true }, PathSegment { ident: panicking#7, hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).101), res: Def(Mod, DefId(2:8281 ~ core[690e]::panicking)), args: None, infer_args: true }, PathSegment { ident: panic#7, hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).102), res: Def(Fn, DefId(2:8292 ~ core[690e]::panicking::panic)), args: None, infer_args: true }] })), span: /home/centri/.rustup/toolchains/nightly-2023-05-05-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/macros/mod.rs:773:9: 773:33 (#7) } + = note: this error originates in the macro `todo` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: use of the method `from_ne_bytes` + --> $DIR/endian_bytes.rs:24:24 + | +LL | i16::from_ne_bytes(todo!()); + | ^^^^^^^ + | + = help: consider specifying the desired endianness: Expr { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).103), kind: Lit(Spanned { node: Str("not yet implemented", Cooked), span: /home/centri/.rustup/toolchains/nightly-2023-05-05-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/macros/mod.rs:773:34: 773:55 (#7) }), span: /home/centri/.rustup/toolchains/nightly-2023-05-05-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/macros/mod.rs:773:34: 773:55 (#7) } + = note: this error originates in the macro `todo` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: use of the method `from_ne_bytes` + --> $DIR/endian_bytes.rs:25:5 + | +LL | u32::from_ne_bytes(todo!()); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: consider specifying the desired endianness: Expr { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).105), kind: Call(Expr { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).106), kind: Path(TypeRelative(Ty { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).108), kind: Path(Resolved(None, Path { span: $DIR/endian_bytes.rs:25:5: 25:8 (#0), res: PrimTy(Uint(U32)), segments: [PathSegment { ident: u32#0, hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).107), res: PrimTy(Uint(U32)), args: None, infer_args: true }] })), span: $DIR/endian_bytes.rs:25:5: 25:8 (#0) }, PathSegment { ident: from_ne_bytes#0, hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).109), res: Err, args: None, infer_args: true })), span: $DIR/endian_bytes.rs:25:5: 25:23 (#0) }, [Expr { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).110), kind: Call(Expr { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).111), kind: Path(Resolved(None, Path { span: /home/centri/.rustup/toolchains/nightly-2023-05-05-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/macros/mod.rs:773:9: 773:33 (#8), res: Def(Fn, DefId(2:8292 ~ core[690e]::panicking::panic)), segments: [PathSegment { ident: $crate#8, hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).112), res: Err, args: None, infer_args: true }, PathSegment { ident: panicking#8, hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).113), res: Def(Mod, DefId(2:8281 ~ core[690e]::panicking)), args: None, infer_args: true }, PathSegment { ident: panic#8, hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).114), res: Def(Fn, DefId(2:8292 ~ core[690e]::panicking::panic)), args: None, infer_args: true }] })), span: /home/centri/.rustup/toolchains/nightly-2023-05-05-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/macros/mod.rs:773:9: 773:33 (#8) }, [Expr { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).115), kind: Lit(Spanned { node: Str("not yet implemented", Cooked), span: /home/centri/.rustup/toolchains/nightly-2023-05-05-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/macros/mod.rs:773:34: 773:55 (#8) }), span: /home/centri/.rustup/toolchains/nightly-2023-05-05-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/macros/mod.rs:773:34: 773:55 (#8) }]), span: /home/centri/.rustup/toolchains/nightly-2023-05-05-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/macros/mod.rs:773:9: 773:56 (#8) }]), span: $DIR/endian_bytes.rs:25:5: 25:32 (#0) } + +error: use of the method `from_ne_bytes` + --> $DIR/endian_bytes.rs:25:5 + | +LL | u32::from_ne_bytes(todo!()); + | ^^^^^^^^^^^^^^^^^^ + | + = help: consider specifying the desired endianness: Expr { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).106), kind: Path(TypeRelative(Ty { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).108), kind: Path(Resolved(None, Path { span: $DIR/endian_bytes.rs:25:5: 25:8 (#0), res: PrimTy(Uint(U32)), segments: [PathSegment { ident: u32#0, hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).107), res: PrimTy(Uint(U32)), args: None, infer_args: true }] })), span: $DIR/endian_bytes.rs:25:5: 25:8 (#0) }, PathSegment { ident: from_ne_bytes#0, hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).109), res: Err, args: None, infer_args: true })), span: $DIR/endian_bytes.rs:25:5: 25:23 (#0) } + +error: use of the method `from_ne_bytes` + --> $DIR/endian_bytes.rs:25:24 + | +LL | u32::from_ne_bytes(todo!()); + | ^^^^^^^ + | + = help: consider specifying the desired endianness: Expr { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).110), kind: Call(Expr { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).111), kind: Path(Resolved(None, Path { span: /home/centri/.rustup/toolchains/nightly-2023-05-05-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/macros/mod.rs:773:9: 773:33 (#8), res: Def(Fn, DefId(2:8292 ~ core[690e]::panicking::panic)), segments: [PathSegment { ident: $crate#8, hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).112), res: Err, args: None, infer_args: true }, PathSegment { ident: panicking#8, hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).113), res: Def(Mod, DefId(2:8281 ~ core[690e]::panicking)), args: None, infer_args: true }, PathSegment { ident: panic#8, hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).114), res: Def(Fn, DefId(2:8292 ~ core[690e]::panicking::panic)), args: None, infer_args: true }] })), span: /home/centri/.rustup/toolchains/nightly-2023-05-05-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/macros/mod.rs:773:9: 773:33 (#8) }, [Expr { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).115), kind: Lit(Spanned { node: Str("not yet implemented", Cooked), span: /home/centri/.rustup/toolchains/nightly-2023-05-05-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/macros/mod.rs:773:34: 773:55 (#8) }), span: /home/centri/.rustup/toolchains/nightly-2023-05-05-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/macros/mod.rs:773:34: 773:55 (#8) }]), span: /home/centri/.rustup/toolchains/nightly-2023-05-05-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/macros/mod.rs:773:9: 773:56 (#8) } + = note: this error originates in the macro `todo` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: use of the method `from_ne_bytes` + --> $DIR/endian_bytes.rs:25:24 + | +LL | u32::from_ne_bytes(todo!()); + | ^^^^^^^ + | + = help: consider specifying the desired endianness: Expr { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).111), kind: Path(Resolved(None, Path { span: /home/centri/.rustup/toolchains/nightly-2023-05-05-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/macros/mod.rs:773:9: 773:33 (#8), res: Def(Fn, DefId(2:8292 ~ core[690e]::panicking::panic)), segments: [PathSegment { ident: $crate#8, hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).112), res: Err, args: None, infer_args: true }, PathSegment { ident: panicking#8, hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).113), res: Def(Mod, DefId(2:8281 ~ core[690e]::panicking)), args: None, infer_args: true }, PathSegment { ident: panic#8, hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).114), res: Def(Fn, DefId(2:8292 ~ core[690e]::panicking::panic)), args: None, infer_args: true }] })), span: /home/centri/.rustup/toolchains/nightly-2023-05-05-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/macros/mod.rs:773:9: 773:33 (#8) } + = note: this error originates in the macro `todo` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: use of the method `from_ne_bytes` + --> $DIR/endian_bytes.rs:25:24 + | +LL | u32::from_ne_bytes(todo!()); + | ^^^^^^^ + | + = help: consider specifying the desired endianness: Expr { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).115), kind: Lit(Spanned { node: Str("not yet implemented", Cooked), span: /home/centri/.rustup/toolchains/nightly-2023-05-05-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/macros/mod.rs:773:34: 773:55 (#8) }), span: /home/centri/.rustup/toolchains/nightly-2023-05-05-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/macros/mod.rs:773:34: 773:55 (#8) } + = note: this error originates in the macro `todo` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: use of the method `from_ne_bytes` + --> $DIR/endian_bytes.rs:26:5 + | +LL | i32::from_ne_bytes(todo!()); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: consider specifying the desired endianness: Expr { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).117), kind: Call(Expr { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).118), kind: Path(TypeRelative(Ty { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).120), kind: Path(Resolved(None, Path { span: $DIR/endian_bytes.rs:26:5: 26:8 (#0), res: PrimTy(Int(I32)), segments: [PathSegment { ident: i32#0, hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).119), res: PrimTy(Int(I32)), args: None, infer_args: true }] })), span: $DIR/endian_bytes.rs:26:5: 26:8 (#0) }, PathSegment { ident: from_ne_bytes#0, hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).121), res: Err, args: None, infer_args: true })), span: $DIR/endian_bytes.rs:26:5: 26:23 (#0) }, [Expr { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).122), kind: Call(Expr { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).123), kind: Path(Resolved(None, Path { span: /home/centri/.rustup/toolchains/nightly-2023-05-05-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/macros/mod.rs:773:9: 773:33 (#9), res: Def(Fn, DefId(2:8292 ~ core[690e]::panicking::panic)), segments: [PathSegment { ident: $crate#9, hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).124), res: Err, args: None, infer_args: true }, PathSegment { ident: panicking#9, hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).125), res: Def(Mod, DefId(2:8281 ~ core[690e]::panicking)), args: None, infer_args: true }, PathSegment { ident: panic#9, hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).126), res: Def(Fn, DefId(2:8292 ~ core[690e]::panicking::panic)), args: None, infer_args: true }] })), span: /home/centri/.rustup/toolchains/nightly-2023-05-05-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/macros/mod.rs:773:9: 773:33 (#9) }, [Expr { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).127), kind: Lit(Spanned { node: Str("not yet implemented", Cooked), span: /home/centri/.rustup/toolchains/nightly-2023-05-05-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/macros/mod.rs:773:34: 773:55 (#9) }), span: /home/centri/.rustup/toolchains/nightly-2023-05-05-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/macros/mod.rs:773:34: 773:55 (#9) }]), span: /home/centri/.rustup/toolchains/nightly-2023-05-05-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/macros/mod.rs:773:9: 773:56 (#9) }]), span: $DIR/endian_bytes.rs:26:5: 26:32 (#0) } + +error: use of the method `from_ne_bytes` + --> $DIR/endian_bytes.rs:26:5 + | +LL | i32::from_ne_bytes(todo!()); + | ^^^^^^^^^^^^^^^^^^ + | + = help: consider specifying the desired endianness: Expr { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).118), kind: Path(TypeRelative(Ty { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).120), kind: Path(Resolved(None, Path { span: $DIR/endian_bytes.rs:26:5: 26:8 (#0), res: PrimTy(Int(I32)), segments: [PathSegment { ident: i32#0, hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).119), res: PrimTy(Int(I32)), args: None, infer_args: true }] })), span: $DIR/endian_bytes.rs:26:5: 26:8 (#0) }, PathSegment { ident: from_ne_bytes#0, hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).121), res: Err, args: None, infer_args: true })), span: $DIR/endian_bytes.rs:26:5: 26:23 (#0) } + +error: use of the method `from_ne_bytes` + --> $DIR/endian_bytes.rs:26:24 + | +LL | i32::from_ne_bytes(todo!()); + | ^^^^^^^ + | + = help: consider specifying the desired endianness: Expr { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).122), kind: Call(Expr { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).123), kind: Path(Resolved(None, Path { span: /home/centri/.rustup/toolchains/nightly-2023-05-05-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/macros/mod.rs:773:9: 773:33 (#9), res: Def(Fn, DefId(2:8292 ~ core[690e]::panicking::panic)), segments: [PathSegment { ident: $crate#9, hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).124), res: Err, args: None, infer_args: true }, PathSegment { ident: panicking#9, hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).125), res: Def(Mod, DefId(2:8281 ~ core[690e]::panicking)), args: None, infer_args: true }, PathSegment { ident: panic#9, hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).126), res: Def(Fn, DefId(2:8292 ~ core[690e]::panicking::panic)), args: None, infer_args: true }] })), span: /home/centri/.rustup/toolchains/nightly-2023-05-05-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/macros/mod.rs:773:9: 773:33 (#9) }, [Expr { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).127), kind: Lit(Spanned { node: Str("not yet implemented", Cooked), span: /home/centri/.rustup/toolchains/nightly-2023-05-05-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/macros/mod.rs:773:34: 773:55 (#9) }), span: /home/centri/.rustup/toolchains/nightly-2023-05-05-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/macros/mod.rs:773:34: 773:55 (#9) }]), span: /home/centri/.rustup/toolchains/nightly-2023-05-05-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/macros/mod.rs:773:9: 773:56 (#9) } + = note: this error originates in the macro `todo` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: use of the method `from_ne_bytes` + --> $DIR/endian_bytes.rs:26:24 + | +LL | i32::from_ne_bytes(todo!()); + | ^^^^^^^ + | + = help: consider specifying the desired endianness: Expr { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).123), kind: Path(Resolved(None, Path { span: /home/centri/.rustup/toolchains/nightly-2023-05-05-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/macros/mod.rs:773:9: 773:33 (#9), res: Def(Fn, DefId(2:8292 ~ core[690e]::panicking::panic)), segments: [PathSegment { ident: $crate#9, hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).124), res: Err, args: None, infer_args: true }, PathSegment { ident: panicking#9, hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).125), res: Def(Mod, DefId(2:8281 ~ core[690e]::panicking)), args: None, infer_args: true }, PathSegment { ident: panic#9, hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).126), res: Def(Fn, DefId(2:8292 ~ core[690e]::panicking::panic)), args: None, infer_args: true }] })), span: /home/centri/.rustup/toolchains/nightly-2023-05-05-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/macros/mod.rs:773:9: 773:33 (#9) } + = note: this error originates in the macro `todo` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: use of the method `from_ne_bytes` + --> $DIR/endian_bytes.rs:26:24 + | +LL | i32::from_ne_bytes(todo!()); + | ^^^^^^^ + | + = help: consider specifying the desired endianness: Expr { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).127), kind: Lit(Spanned { node: Str("not yet implemented", Cooked), span: /home/centri/.rustup/toolchains/nightly-2023-05-05-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/macros/mod.rs:773:34: 773:55 (#9) }), span: /home/centri/.rustup/toolchains/nightly-2023-05-05-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/macros/mod.rs:773:34: 773:55 (#9) } + = note: this error originates in the macro `todo` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: use of the method `from_ne_bytes` + --> $DIR/endian_bytes.rs:27:5 + | +LL | u64::from_ne_bytes(todo!()); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: consider specifying the desired endianness: Expr { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).129), kind: Call(Expr { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).130), kind: Path(TypeRelative(Ty { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).132), kind: Path(Resolved(None, Path { span: $DIR/endian_bytes.rs:27:5: 27:8 (#0), res: PrimTy(Uint(U64)), segments: [PathSegment { ident: u64#0, hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).131), res: PrimTy(Uint(U64)), args: None, infer_args: true }] })), span: $DIR/endian_bytes.rs:27:5: 27:8 (#0) }, PathSegment { ident: from_ne_bytes#0, hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).133), res: Err, args: None, infer_args: true })), span: $DIR/endian_bytes.rs:27:5: 27:23 (#0) }, [Expr { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).134), kind: Call(Expr { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).135), kind: Path(Resolved(None, Path { span: /home/centri/.rustup/toolchains/nightly-2023-05-05-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/macros/mod.rs:773:9: 773:33 (#10), res: Def(Fn, DefId(2:8292 ~ core[690e]::panicking::panic)), segments: [PathSegment { ident: $crate#10, hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).136), res: Err, args: None, infer_args: true }, PathSegment { ident: panicking#10, hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).137), res: Def(Mod, DefId(2:8281 ~ core[690e]::panicking)), args: None, infer_args: true }, PathSegment { ident: panic#10, hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).138), res: Def(Fn, DefId(2:8292 ~ core[690e]::panicking::panic)), args: None, infer_args: true }] })), span: /home/centri/.rustup/toolchains/nightly-2023-05-05-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/macros/mod.rs:773:9: 773:33 (#10) }, [Expr { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).139), kind: Lit(Spanned { node: Str("not yet implemented", Cooked), span: /home/centri/.rustup/toolchains/nightly-2023-05-05-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/macros/mod.rs:773:34: 773:55 (#10) }), span: /home/centri/.rustup/toolchains/nightly-2023-05-05-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/macros/mod.rs:773:34: 773:55 (#10) }]), span: /home/centri/.rustup/toolchains/nightly-2023-05-05-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/macros/mod.rs:773:9: 773:56 (#10) }]), span: $DIR/endian_bytes.rs:27:5: 27:32 (#0) } + +error: use of the method `from_ne_bytes` + --> $DIR/endian_bytes.rs:27:5 + | +LL | u64::from_ne_bytes(todo!()); + | ^^^^^^^^^^^^^^^^^^ + | + = help: consider specifying the desired endianness: Expr { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).130), kind: Path(TypeRelative(Ty { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).132), kind: Path(Resolved(None, Path { span: $DIR/endian_bytes.rs:27:5: 27:8 (#0), res: PrimTy(Uint(U64)), segments: [PathSegment { ident: u64#0, hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).131), res: PrimTy(Uint(U64)), args: None, infer_args: true }] })), span: $DIR/endian_bytes.rs:27:5: 27:8 (#0) }, PathSegment { ident: from_ne_bytes#0, hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).133), res: Err, args: None, infer_args: true })), span: $DIR/endian_bytes.rs:27:5: 27:23 (#0) } + +error: use of the method `from_ne_bytes` + --> $DIR/endian_bytes.rs:27:24 + | +LL | u64::from_ne_bytes(todo!()); + | ^^^^^^^ + | + = help: consider specifying the desired endianness: Expr { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).134), kind: Call(Expr { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).135), kind: Path(Resolved(None, Path { span: /home/centri/.rustup/toolchains/nightly-2023-05-05-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/macros/mod.rs:773:9: 773:33 (#10), res: Def(Fn, DefId(2:8292 ~ core[690e]::panicking::panic)), segments: [PathSegment { ident: $crate#10, hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).136), res: Err, args: None, infer_args: true }, PathSegment { ident: panicking#10, hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).137), res: Def(Mod, DefId(2:8281 ~ core[690e]::panicking)), args: None, infer_args: true }, PathSegment { ident: panic#10, hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).138), res: Def(Fn, DefId(2:8292 ~ core[690e]::panicking::panic)), args: None, infer_args: true }] })), span: /home/centri/.rustup/toolchains/nightly-2023-05-05-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/macros/mod.rs:773:9: 773:33 (#10) }, [Expr { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).139), kind: Lit(Spanned { node: Str("not yet implemented", Cooked), span: /home/centri/.rustup/toolchains/nightly-2023-05-05-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/macros/mod.rs:773:34: 773:55 (#10) }), span: /home/centri/.rustup/toolchains/nightly-2023-05-05-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/macros/mod.rs:773:34: 773:55 (#10) }]), span: /home/centri/.rustup/toolchains/nightly-2023-05-05-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/macros/mod.rs:773:9: 773:56 (#10) } + = note: this error originates in the macro `todo` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: use of the method `from_ne_bytes` + --> $DIR/endian_bytes.rs:27:24 + | +LL | u64::from_ne_bytes(todo!()); + | ^^^^^^^ + | + = help: consider specifying the desired endianness: Expr { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).135), kind: Path(Resolved(None, Path { span: /home/centri/.rustup/toolchains/nightly-2023-05-05-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/macros/mod.rs:773:9: 773:33 (#10), res: Def(Fn, DefId(2:8292 ~ core[690e]::panicking::panic)), segments: [PathSegment { ident: $crate#10, hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).136), res: Err, args: None, infer_args: true }, PathSegment { ident: panicking#10, hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).137), res: Def(Mod, DefId(2:8281 ~ core[690e]::panicking)), args: None, infer_args: true }, PathSegment { ident: panic#10, hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).138), res: Def(Fn, DefId(2:8292 ~ core[690e]::panicking::panic)), args: None, infer_args: true }] })), span: /home/centri/.rustup/toolchains/nightly-2023-05-05-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/macros/mod.rs:773:9: 773:33 (#10) } + = note: this error originates in the macro `todo` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: use of the method `from_ne_bytes` + --> $DIR/endian_bytes.rs:27:24 + | +LL | u64::from_ne_bytes(todo!()); + | ^^^^^^^ + | + = help: consider specifying the desired endianness: Expr { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).139), kind: Lit(Spanned { node: Str("not yet implemented", Cooked), span: /home/centri/.rustup/toolchains/nightly-2023-05-05-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/macros/mod.rs:773:34: 773:55 (#10) }), span: /home/centri/.rustup/toolchains/nightly-2023-05-05-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/macros/mod.rs:773:34: 773:55 (#10) } + = note: this error originates in the macro `todo` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: use of the method `from_ne_bytes` + --> $DIR/endian_bytes.rs:28:5 + | +LL | i64::from_ne_bytes(todo!()); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: consider specifying the desired endianness: Expr { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).141), kind: Call(Expr { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).142), kind: Path(TypeRelative(Ty { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).144), kind: Path(Resolved(None, Path { span: $DIR/endian_bytes.rs:28:5: 28:8 (#0), res: PrimTy(Int(I64)), segments: [PathSegment { ident: i64#0, hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).143), res: PrimTy(Int(I64)), args: None, infer_args: true }] })), span: $DIR/endian_bytes.rs:28:5: 28:8 (#0) }, PathSegment { ident: from_ne_bytes#0, hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).145), res: Err, args: None, infer_args: true })), span: $DIR/endian_bytes.rs:28:5: 28:23 (#0) }, [Expr { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).146), kind: Call(Expr { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).147), kind: Path(Resolved(None, Path { span: /home/centri/.rustup/toolchains/nightly-2023-05-05-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/macros/mod.rs:773:9: 773:33 (#11), res: Def(Fn, DefId(2:8292 ~ core[690e]::panicking::panic)), segments: [PathSegment { ident: $crate#11, hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).148), res: Err, args: None, infer_args: true }, PathSegment { ident: panicking#11, hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).149), res: Def(Mod, DefId(2:8281 ~ core[690e]::panicking)), args: None, infer_args: true }, PathSegment { ident: panic#11, hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).150), res: Def(Fn, DefId(2:8292 ~ core[690e]::panicking::panic)), args: None, infer_args: true }] })), span: /home/centri/.rustup/toolchains/nightly-2023-05-05-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/macros/mod.rs:773:9: 773:33 (#11) }, [Expr { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).151), kind: Lit(Spanned { node: Str("not yet implemented", Cooked), span: /home/centri/.rustup/toolchains/nightly-2023-05-05-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/macros/mod.rs:773:34: 773:55 (#11) }), span: /home/centri/.rustup/toolchains/nightly-2023-05-05-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/macros/mod.rs:773:34: 773:55 (#11) }]), span: /home/centri/.rustup/toolchains/nightly-2023-05-05-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/macros/mod.rs:773:9: 773:56 (#11) }]), span: $DIR/endian_bytes.rs:28:5: 28:32 (#0) } + +error: use of the method `from_ne_bytes` + --> $DIR/endian_bytes.rs:28:5 + | +LL | i64::from_ne_bytes(todo!()); + | ^^^^^^^^^^^^^^^^^^ + | + = help: consider specifying the desired endianness: Expr { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).142), kind: Path(TypeRelative(Ty { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).144), kind: Path(Resolved(None, Path { span: $DIR/endian_bytes.rs:28:5: 28:8 (#0), res: PrimTy(Int(I64)), segments: [PathSegment { ident: i64#0, hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).143), res: PrimTy(Int(I64)), args: None, infer_args: true }] })), span: $DIR/endian_bytes.rs:28:5: 28:8 (#0) }, PathSegment { ident: from_ne_bytes#0, hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).145), res: Err, args: None, infer_args: true })), span: $DIR/endian_bytes.rs:28:5: 28:23 (#0) } + +error: use of the method `from_ne_bytes` + --> $DIR/endian_bytes.rs:28:24 + | +LL | i64::from_ne_bytes(todo!()); + | ^^^^^^^ + | + = help: consider specifying the desired endianness: Expr { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).146), kind: Call(Expr { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).147), kind: Path(Resolved(None, Path { span: /home/centri/.rustup/toolchains/nightly-2023-05-05-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/macros/mod.rs:773:9: 773:33 (#11), res: Def(Fn, DefId(2:8292 ~ core[690e]::panicking::panic)), segments: [PathSegment { ident: $crate#11, hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).148), res: Err, args: None, infer_args: true }, PathSegment { ident: panicking#11, hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).149), res: Def(Mod, DefId(2:8281 ~ core[690e]::panicking)), args: None, infer_args: true }, PathSegment { ident: panic#11, hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).150), res: Def(Fn, DefId(2:8292 ~ core[690e]::panicking::panic)), args: None, infer_args: true }] })), span: /home/centri/.rustup/toolchains/nightly-2023-05-05-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/macros/mod.rs:773:9: 773:33 (#11) }, [Expr { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).151), kind: Lit(Spanned { node: Str("not yet implemented", Cooked), span: /home/centri/.rustup/toolchains/nightly-2023-05-05-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/macros/mod.rs:773:34: 773:55 (#11) }), span: /home/centri/.rustup/toolchains/nightly-2023-05-05-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/macros/mod.rs:773:34: 773:55 (#11) }]), span: /home/centri/.rustup/toolchains/nightly-2023-05-05-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/macros/mod.rs:773:9: 773:56 (#11) } + = note: this error originates in the macro `todo` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: use of the method `from_ne_bytes` + --> $DIR/endian_bytes.rs:28:24 + | +LL | i64::from_ne_bytes(todo!()); + | ^^^^^^^ + | + = help: consider specifying the desired endianness: Expr { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).147), kind: Path(Resolved(None, Path { span: /home/centri/.rustup/toolchains/nightly-2023-05-05-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/macros/mod.rs:773:9: 773:33 (#11), res: Def(Fn, DefId(2:8292 ~ core[690e]::panicking::panic)), segments: [PathSegment { ident: $crate#11, hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).148), res: Err, args: None, infer_args: true }, PathSegment { ident: panicking#11, hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).149), res: Def(Mod, DefId(2:8281 ~ core[690e]::panicking)), args: None, infer_args: true }, PathSegment { ident: panic#11, hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).150), res: Def(Fn, DefId(2:8292 ~ core[690e]::panicking::panic)), args: None, infer_args: true }] })), span: /home/centri/.rustup/toolchains/nightly-2023-05-05-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/macros/mod.rs:773:9: 773:33 (#11) } + = note: this error originates in the macro `todo` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: use of the method `from_ne_bytes` + --> $DIR/endian_bytes.rs:28:24 + | +LL | i64::from_ne_bytes(todo!()); + | ^^^^^^^ + | + = help: consider specifying the desired endianness: Expr { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).151), kind: Lit(Spanned { node: Str("not yet implemented", Cooked), span: /home/centri/.rustup/toolchains/nightly-2023-05-05-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/macros/mod.rs:773:34: 773:55 (#11) }), span: /home/centri/.rustup/toolchains/nightly-2023-05-05-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/macros/mod.rs:773:34: 773:55 (#11) } + = note: this error originates in the macro `todo` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: use of the method `from_ne_bytes` + --> $DIR/endian_bytes.rs:29:5 + | +LL | u128::from_ne_bytes(todo!()); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: consider specifying the desired endianness: Expr { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).153), kind: Call(Expr { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).154), kind: Path(TypeRelative(Ty { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).156), kind: Path(Resolved(None, Path { span: $DIR/endian_bytes.rs:29:5: 29:9 (#0), res: PrimTy(Uint(U128)), segments: [PathSegment { ident: u128#0, hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).155), res: PrimTy(Uint(U128)), args: None, infer_args: true }] })), span: $DIR/endian_bytes.rs:29:5: 29:9 (#0) }, PathSegment { ident: from_ne_bytes#0, hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).157), res: Err, args: None, infer_args: true })), span: $DIR/endian_bytes.rs:29:5: 29:24 (#0) }, [Expr { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).158), kind: Call(Expr { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).159), kind: Path(Resolved(None, Path { span: /home/centri/.rustup/toolchains/nightly-2023-05-05-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/macros/mod.rs:773:9: 773:33 (#12), res: Def(Fn, DefId(2:8292 ~ core[690e]::panicking::panic)), segments: [PathSegment { ident: $crate#12, hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).160), res: Err, args: None, infer_args: true }, PathSegment { ident: panicking#12, hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).161), res: Def(Mod, DefId(2:8281 ~ core[690e]::panicking)), args: None, infer_args: true }, PathSegment { ident: panic#12, hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).162), res: Def(Fn, DefId(2:8292 ~ core[690e]::panicking::panic)), args: None, infer_args: true }] })), span: /home/centri/.rustup/toolchains/nightly-2023-05-05-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/macros/mod.rs:773:9: 773:33 (#12) }, [Expr { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).163), kind: Lit(Spanned { node: Str("not yet implemented", Cooked), span: /home/centri/.rustup/toolchains/nightly-2023-05-05-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/macros/mod.rs:773:34: 773:55 (#12) }), span: /home/centri/.rustup/toolchains/nightly-2023-05-05-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/macros/mod.rs:773:34: 773:55 (#12) }]), span: /home/centri/.rustup/toolchains/nightly-2023-05-05-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/macros/mod.rs:773:9: 773:56 (#12) }]), span: $DIR/endian_bytes.rs:29:5: 29:33 (#0) } + +error: use of the method `from_ne_bytes` + --> $DIR/endian_bytes.rs:29:5 + | +LL | u128::from_ne_bytes(todo!()); + | ^^^^^^^^^^^^^^^^^^^ + | + = help: consider specifying the desired endianness: Expr { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).154), kind: Path(TypeRelative(Ty { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).156), kind: Path(Resolved(None, Path { span: $DIR/endian_bytes.rs:29:5: 29:9 (#0), res: PrimTy(Uint(U128)), segments: [PathSegment { ident: u128#0, hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).155), res: PrimTy(Uint(U128)), args: None, infer_args: true }] })), span: $DIR/endian_bytes.rs:29:5: 29:9 (#0) }, PathSegment { ident: from_ne_bytes#0, hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).157), res: Err, args: None, infer_args: true })), span: $DIR/endian_bytes.rs:29:5: 29:24 (#0) } + +error: use of the method `from_ne_bytes` + --> $DIR/endian_bytes.rs:29:25 + | +LL | u128::from_ne_bytes(todo!()); + | ^^^^^^^ + | + = help: consider specifying the desired endianness: Expr { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).158), kind: Call(Expr { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).159), kind: Path(Resolved(None, Path { span: /home/centri/.rustup/toolchains/nightly-2023-05-05-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/macros/mod.rs:773:9: 773:33 (#12), res: Def(Fn, DefId(2:8292 ~ core[690e]::panicking::panic)), segments: [PathSegment { ident: $crate#12, hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).160), res: Err, args: None, infer_args: true }, PathSegment { ident: panicking#12, hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).161), res: Def(Mod, DefId(2:8281 ~ core[690e]::panicking)), args: None, infer_args: true }, PathSegment { ident: panic#12, hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).162), res: Def(Fn, DefId(2:8292 ~ core[690e]::panicking::panic)), args: None, infer_args: true }] })), span: /home/centri/.rustup/toolchains/nightly-2023-05-05-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/macros/mod.rs:773:9: 773:33 (#12) }, [Expr { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).163), kind: Lit(Spanned { node: Str("not yet implemented", Cooked), span: /home/centri/.rustup/toolchains/nightly-2023-05-05-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/macros/mod.rs:773:34: 773:55 (#12) }), span: /home/centri/.rustup/toolchains/nightly-2023-05-05-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/macros/mod.rs:773:34: 773:55 (#12) }]), span: /home/centri/.rustup/toolchains/nightly-2023-05-05-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/macros/mod.rs:773:9: 773:56 (#12) } + = note: this error originates in the macro `todo` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: use of the method `from_ne_bytes` + --> $DIR/endian_bytes.rs:29:25 + | +LL | u128::from_ne_bytes(todo!()); + | ^^^^^^^ + | + = help: consider specifying the desired endianness: Expr { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).159), kind: Path(Resolved(None, Path { span: /home/centri/.rustup/toolchains/nightly-2023-05-05-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/macros/mod.rs:773:9: 773:33 (#12), res: Def(Fn, DefId(2:8292 ~ core[690e]::panicking::panic)), segments: [PathSegment { ident: $crate#12, hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).160), res: Err, args: None, infer_args: true }, PathSegment { ident: panicking#12, hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).161), res: Def(Mod, DefId(2:8281 ~ core[690e]::panicking)), args: None, infer_args: true }, PathSegment { ident: panic#12, hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).162), res: Def(Fn, DefId(2:8292 ~ core[690e]::panicking::panic)), args: None, infer_args: true }] })), span: /home/centri/.rustup/toolchains/nightly-2023-05-05-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/macros/mod.rs:773:9: 773:33 (#12) } + = note: this error originates in the macro `todo` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: use of the method `from_ne_bytes` + --> $DIR/endian_bytes.rs:29:25 + | +LL | u128::from_ne_bytes(todo!()); + | ^^^^^^^ + | + = help: consider specifying the desired endianness: Expr { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).163), kind: Lit(Spanned { node: Str("not yet implemented", Cooked), span: /home/centri/.rustup/toolchains/nightly-2023-05-05-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/macros/mod.rs:773:34: 773:55 (#12) }), span: /home/centri/.rustup/toolchains/nightly-2023-05-05-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/macros/mod.rs:773:34: 773:55 (#12) } + = note: this error originates in the macro `todo` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: use of the method `from_ne_bytes` + --> $DIR/endian_bytes.rs:30:5 + | +LL | i128::from_ne_bytes(todo!()); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: consider specifying the desired endianness: Expr { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).165), kind: Call(Expr { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).166), kind: Path(TypeRelative(Ty { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).168), kind: Path(Resolved(None, Path { span: $DIR/endian_bytes.rs:30:5: 30:9 (#0), res: PrimTy(Int(I128)), segments: [PathSegment { ident: i128#0, hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).167), res: PrimTy(Int(I128)), args: None, infer_args: true }] })), span: $DIR/endian_bytes.rs:30:5: 30:9 (#0) }, PathSegment { ident: from_ne_bytes#0, hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).169), res: Err, args: None, infer_args: true })), span: $DIR/endian_bytes.rs:30:5: 30:24 (#0) }, [Expr { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).170), kind: Call(Expr { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).171), kind: Path(Resolved(None, Path { span: /home/centri/.rustup/toolchains/nightly-2023-05-05-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/macros/mod.rs:773:9: 773:33 (#13), res: Def(Fn, DefId(2:8292 ~ core[690e]::panicking::panic)), segments: [PathSegment { ident: $crate#13, hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).172), res: Err, args: None, infer_args: true }, PathSegment { ident: panicking#13, hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).173), res: Def(Mod, DefId(2:8281 ~ core[690e]::panicking)), args: None, infer_args: true }, PathSegment { ident: panic#13, hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).174), res: Def(Fn, DefId(2:8292 ~ core[690e]::panicking::panic)), args: None, infer_args: true }] })), span: /home/centri/.rustup/toolchains/nightly-2023-05-05-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/macros/mod.rs:773:9: 773:33 (#13) }, [Expr { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).175), kind: Lit(Spanned { node: Str("not yet implemented", Cooked), span: /home/centri/.rustup/toolchains/nightly-2023-05-05-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/macros/mod.rs:773:34: 773:55 (#13) }), span: /home/centri/.rustup/toolchains/nightly-2023-05-05-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/macros/mod.rs:773:34: 773:55 (#13) }]), span: /home/centri/.rustup/toolchains/nightly-2023-05-05-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/macros/mod.rs:773:9: 773:56 (#13) }]), span: $DIR/endian_bytes.rs:30:5: 30:33 (#0) } + +error: use of the method `from_ne_bytes` + --> $DIR/endian_bytes.rs:30:5 + | +LL | i128::from_ne_bytes(todo!()); + | ^^^^^^^^^^^^^^^^^^^ + | + = help: consider specifying the desired endianness: Expr { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).166), kind: Path(TypeRelative(Ty { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).168), kind: Path(Resolved(None, Path { span: $DIR/endian_bytes.rs:30:5: 30:9 (#0), res: PrimTy(Int(I128)), segments: [PathSegment { ident: i128#0, hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).167), res: PrimTy(Int(I128)), args: None, infer_args: true }] })), span: $DIR/endian_bytes.rs:30:5: 30:9 (#0) }, PathSegment { ident: from_ne_bytes#0, hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).169), res: Err, args: None, infer_args: true })), span: $DIR/endian_bytes.rs:30:5: 30:24 (#0) } + +error: use of the method `from_ne_bytes` + --> $DIR/endian_bytes.rs:30:25 + | +LL | i128::from_ne_bytes(todo!()); + | ^^^^^^^ + | + = help: consider specifying the desired endianness: Expr { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).170), kind: Call(Expr { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).171), kind: Path(Resolved(None, Path { span: /home/centri/.rustup/toolchains/nightly-2023-05-05-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/macros/mod.rs:773:9: 773:33 (#13), res: Def(Fn, DefId(2:8292 ~ core[690e]::panicking::panic)), segments: [PathSegment { ident: $crate#13, hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).172), res: Err, args: None, infer_args: true }, PathSegment { ident: panicking#13, hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).173), res: Def(Mod, DefId(2:8281 ~ core[690e]::panicking)), args: None, infer_args: true }, PathSegment { ident: panic#13, hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).174), res: Def(Fn, DefId(2:8292 ~ core[690e]::panicking::panic)), args: None, infer_args: true }] })), span: /home/centri/.rustup/toolchains/nightly-2023-05-05-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/macros/mod.rs:773:9: 773:33 (#13) }, [Expr { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).175), kind: Lit(Spanned { node: Str("not yet implemented", Cooked), span: /home/centri/.rustup/toolchains/nightly-2023-05-05-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/macros/mod.rs:773:34: 773:55 (#13) }), span: /home/centri/.rustup/toolchains/nightly-2023-05-05-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/macros/mod.rs:773:34: 773:55 (#13) }]), span: /home/centri/.rustup/toolchains/nightly-2023-05-05-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/macros/mod.rs:773:9: 773:56 (#13) } + = note: this error originates in the macro `todo` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: use of the method `from_ne_bytes` + --> $DIR/endian_bytes.rs:30:25 + | +LL | i128::from_ne_bytes(todo!()); + | ^^^^^^^ + | + = help: consider specifying the desired endianness: Expr { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).171), kind: Path(Resolved(None, Path { span: /home/centri/.rustup/toolchains/nightly-2023-05-05-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/macros/mod.rs:773:9: 773:33 (#13), res: Def(Fn, DefId(2:8292 ~ core[690e]::panicking::panic)), segments: [PathSegment { ident: $crate#13, hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).172), res: Err, args: None, infer_args: true }, PathSegment { ident: panicking#13, hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).173), res: Def(Mod, DefId(2:8281 ~ core[690e]::panicking)), args: None, infer_args: true }, PathSegment { ident: panic#13, hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).174), res: Def(Fn, DefId(2:8292 ~ core[690e]::panicking::panic)), args: None, infer_args: true }] })), span: /home/centri/.rustup/toolchains/nightly-2023-05-05-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/macros/mod.rs:773:9: 773:33 (#13) } + = note: this error originates in the macro `todo` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: use of the method `from_ne_bytes` + --> $DIR/endian_bytes.rs:30:25 + | +LL | i128::from_ne_bytes(todo!()); + | ^^^^^^^ + | + = help: consider specifying the desired endianness: Expr { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).175), kind: Lit(Spanned { node: Str("not yet implemented", Cooked), span: /home/centri/.rustup/toolchains/nightly-2023-05-05-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/macros/mod.rs:773:34: 773:55 (#13) }), span: /home/centri/.rustup/toolchains/nightly-2023-05-05-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/macros/mod.rs:773:34: 773:55 (#13) } + = note: this error originates in the macro `todo` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: use of the method `from_ne_bytes` + --> $DIR/endian_bytes.rs:31:5 + | +LL | f32::from_ne_bytes(todo!()); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: consider specifying the desired endianness: Expr { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).177), kind: Call(Expr { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).178), kind: Path(TypeRelative(Ty { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).180), kind: Path(Resolved(None, Path { span: $DIR/endian_bytes.rs:31:5: 31:8 (#0), res: PrimTy(Float(F32)), segments: [PathSegment { ident: f32#0, hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).179), res: PrimTy(Float(F32)), args: None, infer_args: true }] })), span: $DIR/endian_bytes.rs:31:5: 31:8 (#0) }, PathSegment { ident: from_ne_bytes#0, hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).181), res: Err, args: None, infer_args: true })), span: $DIR/endian_bytes.rs:31:5: 31:23 (#0) }, [Expr { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).182), kind: Call(Expr { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).183), kind: Path(Resolved(None, Path { span: /home/centri/.rustup/toolchains/nightly-2023-05-05-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/macros/mod.rs:773:9: 773:33 (#14), res: Def(Fn, DefId(2:8292 ~ core[690e]::panicking::panic)), segments: [PathSegment { ident: $crate#14, hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).184), res: Err, args: None, infer_args: true }, PathSegment { ident: panicking#14, hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).185), res: Def(Mod, DefId(2:8281 ~ core[690e]::panicking)), args: None, infer_args: true }, PathSegment { ident: panic#14, hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).186), res: Def(Fn, DefId(2:8292 ~ core[690e]::panicking::panic)), args: None, infer_args: true }] })), span: /home/centri/.rustup/toolchains/nightly-2023-05-05-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/macros/mod.rs:773:9: 773:33 (#14) }, [Expr { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).187), kind: Lit(Spanned { node: Str("not yet implemented", Cooked), span: /home/centri/.rustup/toolchains/nightly-2023-05-05-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/macros/mod.rs:773:34: 773:55 (#14) }), span: /home/centri/.rustup/toolchains/nightly-2023-05-05-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/macros/mod.rs:773:34: 773:55 (#14) }]), span: /home/centri/.rustup/toolchains/nightly-2023-05-05-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/macros/mod.rs:773:9: 773:56 (#14) }]), span: $DIR/endian_bytes.rs:31:5: 31:32 (#0) } + +error: use of the method `from_ne_bytes` + --> $DIR/endian_bytes.rs:31:5 + | +LL | f32::from_ne_bytes(todo!()); + | ^^^^^^^^^^^^^^^^^^ + | + = help: consider specifying the desired endianness: Expr { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).178), kind: Path(TypeRelative(Ty { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).180), kind: Path(Resolved(None, Path { span: $DIR/endian_bytes.rs:31:5: 31:8 (#0), res: PrimTy(Float(F32)), segments: [PathSegment { ident: f32#0, hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).179), res: PrimTy(Float(F32)), args: None, infer_args: true }] })), span: $DIR/endian_bytes.rs:31:5: 31:8 (#0) }, PathSegment { ident: from_ne_bytes#0, hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).181), res: Err, args: None, infer_args: true })), span: $DIR/endian_bytes.rs:31:5: 31:23 (#0) } + +error: use of the method `from_ne_bytes` + --> $DIR/endian_bytes.rs:31:24 + | +LL | f32::from_ne_bytes(todo!()); + | ^^^^^^^ + | + = help: consider specifying the desired endianness: Expr { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).182), kind: Call(Expr { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).183), kind: Path(Resolved(None, Path { span: /home/centri/.rustup/toolchains/nightly-2023-05-05-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/macros/mod.rs:773:9: 773:33 (#14), res: Def(Fn, DefId(2:8292 ~ core[690e]::panicking::panic)), segments: [PathSegment { ident: $crate#14, hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).184), res: Err, args: None, infer_args: true }, PathSegment { ident: panicking#14, hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).185), res: Def(Mod, DefId(2:8281 ~ core[690e]::panicking)), args: None, infer_args: true }, PathSegment { ident: panic#14, hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).186), res: Def(Fn, DefId(2:8292 ~ core[690e]::panicking::panic)), args: None, infer_args: true }] })), span: /home/centri/.rustup/toolchains/nightly-2023-05-05-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/macros/mod.rs:773:9: 773:33 (#14) }, [Expr { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).187), kind: Lit(Spanned { node: Str("not yet implemented", Cooked), span: /home/centri/.rustup/toolchains/nightly-2023-05-05-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/macros/mod.rs:773:34: 773:55 (#14) }), span: /home/centri/.rustup/toolchains/nightly-2023-05-05-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/macros/mod.rs:773:34: 773:55 (#14) }]), span: /home/centri/.rustup/toolchains/nightly-2023-05-05-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/macros/mod.rs:773:9: 773:56 (#14) } + = note: this error originates in the macro `todo` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: use of the method `from_ne_bytes` + --> $DIR/endian_bytes.rs:31:24 + | +LL | f32::from_ne_bytes(todo!()); + | ^^^^^^^ + | + = help: consider specifying the desired endianness: Expr { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).183), kind: Path(Resolved(None, Path { span: /home/centri/.rustup/toolchains/nightly-2023-05-05-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/macros/mod.rs:773:9: 773:33 (#14), res: Def(Fn, DefId(2:8292 ~ core[690e]::panicking::panic)), segments: [PathSegment { ident: $crate#14, hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).184), res: Err, args: None, infer_args: true }, PathSegment { ident: panicking#14, hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).185), res: Def(Mod, DefId(2:8281 ~ core[690e]::panicking)), args: None, infer_args: true }, PathSegment { ident: panic#14, hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).186), res: Def(Fn, DefId(2:8292 ~ core[690e]::panicking::panic)), args: None, infer_args: true }] })), span: /home/centri/.rustup/toolchains/nightly-2023-05-05-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/macros/mod.rs:773:9: 773:33 (#14) } + = note: this error originates in the macro `todo` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: use of the method `from_ne_bytes` + --> $DIR/endian_bytes.rs:31:24 + | +LL | f32::from_ne_bytes(todo!()); + | ^^^^^^^ + | + = help: consider specifying the desired endianness: Expr { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).187), kind: Lit(Spanned { node: Str("not yet implemented", Cooked), span: /home/centri/.rustup/toolchains/nightly-2023-05-05-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/macros/mod.rs:773:34: 773:55 (#14) }), span: /home/centri/.rustup/toolchains/nightly-2023-05-05-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/macros/mod.rs:773:34: 773:55 (#14) } + = note: this error originates in the macro `todo` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: use of the method `from_ne_bytes` + --> $DIR/endian_bytes.rs:32:5 + | +LL | f64::from_ne_bytes(todo!()); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: consider specifying the desired endianness: Expr { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).189), kind: Call(Expr { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).190), kind: Path(TypeRelative(Ty { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).192), kind: Path(Resolved(None, Path { span: $DIR/endian_bytes.rs:32:5: 32:8 (#0), res: PrimTy(Float(F64)), segments: [PathSegment { ident: f64#0, hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).191), res: PrimTy(Float(F64)), args: None, infer_args: true }] })), span: $DIR/endian_bytes.rs:32:5: 32:8 (#0) }, PathSegment { ident: from_ne_bytes#0, hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).193), res: Err, args: None, infer_args: true })), span: $DIR/endian_bytes.rs:32:5: 32:23 (#0) }, [Expr { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).194), kind: Call(Expr { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).195), kind: Path(Resolved(None, Path { span: /home/centri/.rustup/toolchains/nightly-2023-05-05-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/macros/mod.rs:773:9: 773:33 (#15), res: Def(Fn, DefId(2:8292 ~ core[690e]::panicking::panic)), segments: [PathSegment { ident: $crate#15, hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).196), res: Err, args: None, infer_args: true }, PathSegment { ident: panicking#15, hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).197), res: Def(Mod, DefId(2:8281 ~ core[690e]::panicking)), args: None, infer_args: true }, PathSegment { ident: panic#15, hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).198), res: Def(Fn, DefId(2:8292 ~ core[690e]::panicking::panic)), args: None, infer_args: true }] })), span: /home/centri/.rustup/toolchains/nightly-2023-05-05-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/macros/mod.rs:773:9: 773:33 (#15) }, [Expr { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).199), kind: Lit(Spanned { node: Str("not yet implemented", Cooked), span: /home/centri/.rustup/toolchains/nightly-2023-05-05-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/macros/mod.rs:773:34: 773:55 (#15) }), span: /home/centri/.rustup/toolchains/nightly-2023-05-05-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/macros/mod.rs:773:34: 773:55 (#15) }]), span: /home/centri/.rustup/toolchains/nightly-2023-05-05-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/macros/mod.rs:773:9: 773:56 (#15) }]), span: $DIR/endian_bytes.rs:32:5: 32:32 (#0) } + +error: use of the method `from_ne_bytes` + --> $DIR/endian_bytes.rs:32:5 + | +LL | f64::from_ne_bytes(todo!()); + | ^^^^^^^^^^^^^^^^^^ + | + = help: consider specifying the desired endianness: Expr { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).190), kind: Path(TypeRelative(Ty { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).192), kind: Path(Resolved(None, Path { span: $DIR/endian_bytes.rs:32:5: 32:8 (#0), res: PrimTy(Float(F64)), segments: [PathSegment { ident: f64#0, hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).191), res: PrimTy(Float(F64)), args: None, infer_args: true }] })), span: $DIR/endian_bytes.rs:32:5: 32:8 (#0) }, PathSegment { ident: from_ne_bytes#0, hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).193), res: Err, args: None, infer_args: true })), span: $DIR/endian_bytes.rs:32:5: 32:23 (#0) } + +error: use of the method `from_ne_bytes` + --> $DIR/endian_bytes.rs:32:24 + | +LL | f64::from_ne_bytes(todo!()); + | ^^^^^^^ + | + = help: consider specifying the desired endianness: Expr { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).194), kind: Call(Expr { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).195), kind: Path(Resolved(None, Path { span: /home/centri/.rustup/toolchains/nightly-2023-05-05-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/macros/mod.rs:773:9: 773:33 (#15), res: Def(Fn, DefId(2:8292 ~ core[690e]::panicking::panic)), segments: [PathSegment { ident: $crate#15, hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).196), res: Err, args: None, infer_args: true }, PathSegment { ident: panicking#15, hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).197), res: Def(Mod, DefId(2:8281 ~ core[690e]::panicking)), args: None, infer_args: true }, PathSegment { ident: panic#15, hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).198), res: Def(Fn, DefId(2:8292 ~ core[690e]::panicking::panic)), args: None, infer_args: true }] })), span: /home/centri/.rustup/toolchains/nightly-2023-05-05-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/macros/mod.rs:773:9: 773:33 (#15) }, [Expr { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).199), kind: Lit(Spanned { node: Str("not yet implemented", Cooked), span: /home/centri/.rustup/toolchains/nightly-2023-05-05-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/macros/mod.rs:773:34: 773:55 (#15) }), span: /home/centri/.rustup/toolchains/nightly-2023-05-05-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/macros/mod.rs:773:34: 773:55 (#15) }]), span: /home/centri/.rustup/toolchains/nightly-2023-05-05-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/macros/mod.rs:773:9: 773:56 (#15) } + = note: this error originates in the macro `todo` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: use of the method `from_ne_bytes` + --> $DIR/endian_bytes.rs:32:24 + | +LL | f64::from_ne_bytes(todo!()); + | ^^^^^^^ + | + = help: consider specifying the desired endianness: Expr { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).195), kind: Path(Resolved(None, Path { span: /home/centri/.rustup/toolchains/nightly-2023-05-05-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/macros/mod.rs:773:9: 773:33 (#15), res: Def(Fn, DefId(2:8292 ~ core[690e]::panicking::panic)), segments: [PathSegment { ident: $crate#15, hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).196), res: Err, args: None, infer_args: true }, PathSegment { ident: panicking#15, hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).197), res: Def(Mod, DefId(2:8281 ~ core[690e]::panicking)), args: None, infer_args: true }, PathSegment { ident: panic#15, hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).198), res: Def(Fn, DefId(2:8292 ~ core[690e]::panicking::panic)), args: None, infer_args: true }] })), span: /home/centri/.rustup/toolchains/nightly-2023-05-05-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/macros/mod.rs:773:9: 773:33 (#15) } + = note: this error originates in the macro `todo` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: use of the method `from_ne_bytes` + --> $DIR/endian_bytes.rs:32:24 + | +LL | f64::from_ne_bytes(todo!()); + | ^^^^^^^ + | + = help: consider specifying the desired endianness: Expr { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).199), kind: Lit(Spanned { node: Str("not yet implemented", Cooked), span: /home/centri/.rustup/toolchains/nightly-2023-05-05-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/macros/mod.rs:773:34: 773:55 (#15) }), span: /home/centri/.rustup/toolchains/nightly-2023-05-05-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/macros/mod.rs:773:34: 773:55 (#15) } + = note: this error originates in the macro `todo` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: use of the method `to_le_bytes` + --> $DIR/endian_bytes.rs:37:5 + | +LL | 2u8.to_le_bytes(); + | ^^^^^^^^^^^^^^^^^ + | + = help: use `to_be_bytes` instead + = note: `-D clippy::little-endian-bytes` implied by `-D warnings` + +error: use of the method `to_le_bytes` + --> $DIR/endian_bytes.rs:38:5 + | +LL | 2i8.to_le_bytes(); + | ^^^^^^^^^^^^^^^^^ + | + = help: use `to_be_bytes` instead + +error: use of the method `to_le_bytes` + --> $DIR/endian_bytes.rs:39:5 + | +LL | 2u16.to_le_bytes(); + | ^^^^^^^^^^^^^^^^^^ + | + = help: use `to_be_bytes` instead + +error: use of the method `to_le_bytes` + --> $DIR/endian_bytes.rs:40:5 + | +LL | 2i16.to_le_bytes(); + | ^^^^^^^^^^^^^^^^^^ + | + = help: use `to_be_bytes` instead + +error: use of the method `to_le_bytes` + --> $DIR/endian_bytes.rs:41:5 + | +LL | 2u32.to_le_bytes(); + | ^^^^^^^^^^^^^^^^^^ + | + = help: use `to_be_bytes` instead + +error: use of the method `to_le_bytes` + --> $DIR/endian_bytes.rs:42:5 + | +LL | 2i32.to_le_bytes(); + | ^^^^^^^^^^^^^^^^^^ + | + = help: use `to_be_bytes` instead + +error: use of the method `to_le_bytes` + --> $DIR/endian_bytes.rs:43:5 + | +LL | 2u64.to_le_bytes(); + | ^^^^^^^^^^^^^^^^^^ + | + = help: use `to_be_bytes` instead + +error: use of the method `to_le_bytes` + --> $DIR/endian_bytes.rs:44:5 + | +LL | 2i64.to_le_bytes(); + | ^^^^^^^^^^^^^^^^^^ + | + = help: use `to_be_bytes` instead + +error: use of the method `to_le_bytes` + --> $DIR/endian_bytes.rs:45:5 + | +LL | 2u128.to_le_bytes(); + | ^^^^^^^^^^^^^^^^^^^ + | + = help: use `to_be_bytes` instead + +error: use of the method `to_le_bytes` + --> $DIR/endian_bytes.rs:46:5 + | +LL | 2i128.to_le_bytes(); + | ^^^^^^^^^^^^^^^^^^^ + | + = help: use `to_be_bytes` instead + +error: use of the method `to_le_bytes` + --> $DIR/endian_bytes.rs:47:5 + | +LL | 2usize.to_le_bytes(); + | ^^^^^^^^^^^^^^^^^^^^ + | + = help: use `to_be_bytes` instead + +error: use of the method `to_le_bytes` + --> $DIR/endian_bytes.rs:48:5 + | +LL | 2isize.to_le_bytes(); + | ^^^^^^^^^^^^^^^^^^^^ + | + = help: use `to_be_bytes` instead + +error: use of the method `to_le_bytes` + --> $DIR/endian_bytes.rs:49:5 + | +LL | 2.0f32.to_le_bytes(); + | ^^^^^^^^^^^^^^^^^^^^ + | + = help: use `to_be_bytes` instead + +error: use of the method `to_le_bytes` + --> $DIR/endian_bytes.rs:50:5 + | +LL | 2.0f64.to_le_bytes(); + | ^^^^^^^^^^^^^^^^^^^^ + | + = help: use `to_be_bytes` instead + +error: use of the method `to_be_bytes` + --> $DIR/endian_bytes.rs:69:5 + | +LL | 2u8.to_be_bytes(); + | ^^^^^^^^^^^^^^^^^ + | + = help: use `to_le_bytes` instead + = note: `-D clippy::big-endian-bytes` implied by `-D warnings` + +error: use of the method `to_be_bytes` + --> $DIR/endian_bytes.rs:70:5 + | +LL | 2i8.to_be_bytes(); + | ^^^^^^^^^^^^^^^^^ + | + = help: use `to_le_bytes` instead + +error: use of the method `to_be_bytes` + --> $DIR/endian_bytes.rs:71:5 + | +LL | 2u16.to_be_bytes(); + | ^^^^^^^^^^^^^^^^^^ + | + = help: use `to_le_bytes` instead + +error: use of the method `to_be_bytes` + --> $DIR/endian_bytes.rs:72:5 + | +LL | 2i16.to_be_bytes(); + | ^^^^^^^^^^^^^^^^^^ + | + = help: use `to_le_bytes` instead + +error: use of the method `to_be_bytes` + --> $DIR/endian_bytes.rs:73:5 + | +LL | 2u32.to_be_bytes(); + | ^^^^^^^^^^^^^^^^^^ + | + = help: use `to_le_bytes` instead + +error: use of the method `to_be_bytes` + --> $DIR/endian_bytes.rs:74:5 + | +LL | 2i32.to_be_bytes(); + | ^^^^^^^^^^^^^^^^^^ + | + = help: use `to_le_bytes` instead + +error: use of the method `to_be_bytes` + --> $DIR/endian_bytes.rs:75:5 + | +LL | 2u64.to_be_bytes(); + | ^^^^^^^^^^^^^^^^^^ + | + = help: use `to_le_bytes` instead + +error: use of the method `to_be_bytes` + --> $DIR/endian_bytes.rs:76:5 + | +LL | 2i64.to_be_bytes(); + | ^^^^^^^^^^^^^^^^^^ + | + = help: use `to_le_bytes` instead + +error: use of the method `to_be_bytes` + --> $DIR/endian_bytes.rs:77:5 + | +LL | 2u128.to_be_bytes(); + | ^^^^^^^^^^^^^^^^^^^ + | + = help: use `to_le_bytes` instead + +error: use of the method `to_be_bytes` + --> $DIR/endian_bytes.rs:78:5 + | +LL | 2i128.to_be_bytes(); + | ^^^^^^^^^^^^^^^^^^^ + | + = help: use `to_le_bytes` instead + +error: use of the method `to_be_bytes` + --> $DIR/endian_bytes.rs:79:5 + | +LL | 2.0f32.to_be_bytes(); + | ^^^^^^^^^^^^^^^^^^^^ + | + = help: use `to_le_bytes` instead + +error: use of the method `to_be_bytes` + --> $DIR/endian_bytes.rs:80:5 + | +LL | 2.0f64.to_be_bytes(); + | ^^^^^^^^^^^^^^^^^^^^ + | + = help: use `to_le_bytes` instead + +error: use of the method `to_be_bytes` + --> $DIR/endian_bytes.rs:81:5 + | +LL | 2usize.to_be_bytes(); + | ^^^^^^^^^^^^^^^^^^^^ + | + = help: use `to_le_bytes` instead + +error: use of the method `to_be_bytes` + --> $DIR/endian_bytes.rs:82:5 + | +LL | 2isize.to_be_bytes(); + | ^^^^^^^^^^^^^^^^^^^^ + | + = help: use `to_le_bytes` instead + +error: use of the method `to_le_bytes` + --> $DIR/endian_bytes.rs:102:5 + | +LL | 2u8.to_le_bytes(); + | ^^^^^^^^^^^^^^^^^ + +error: use of the method `to_le_bytes` + --> $DIR/endian_bytes.rs:103:5 + | +LL | 2i8.to_le_bytes(); + | ^^^^^^^^^^^^^^^^^ + +error: use of the method `to_le_bytes` + --> $DIR/endian_bytes.rs:104:5 + | +LL | 2u16.to_le_bytes(); + | ^^^^^^^^^^^^^^^^^^ + +error: use of the method `to_le_bytes` + --> $DIR/endian_bytes.rs:105:5 + | +LL | 2i16.to_le_bytes(); + | ^^^^^^^^^^^^^^^^^^ + +error: use of the method `to_le_bytes` + --> $DIR/endian_bytes.rs:106:5 + | +LL | 2u32.to_le_bytes(); + | ^^^^^^^^^^^^^^^^^^ + +error: use of the method `to_le_bytes` + --> $DIR/endian_bytes.rs:107:5 + | +LL | 2i32.to_le_bytes(); + | ^^^^^^^^^^^^^^^^^^ + +error: use of the method `to_le_bytes` + --> $DIR/endian_bytes.rs:108:5 + | +LL | 2u64.to_le_bytes(); + | ^^^^^^^^^^^^^^^^^^ + +error: use of the method `to_le_bytes` + --> $DIR/endian_bytes.rs:109:5 + | +LL | 2i64.to_le_bytes(); + | ^^^^^^^^^^^^^^^^^^ + +error: use of the method `to_le_bytes` + --> $DIR/endian_bytes.rs:110:5 + | +LL | 2u128.to_le_bytes(); + | ^^^^^^^^^^^^^^^^^^^ + +error: use of the method `to_le_bytes` + --> $DIR/endian_bytes.rs:111:5 + | +LL | 2i128.to_le_bytes(); + | ^^^^^^^^^^^^^^^^^^^ + +error: use of the method `to_le_bytes` + --> $DIR/endian_bytes.rs:112:5 + | +LL | 2usize.to_le_bytes(); + | ^^^^^^^^^^^^^^^^^^^^ + +error: use of the method `to_le_bytes` + --> $DIR/endian_bytes.rs:113:5 + | +LL | 2isize.to_le_bytes(); + | ^^^^^^^^^^^^^^^^^^^^ + +error: use of the method `to_le_bytes` + --> $DIR/endian_bytes.rs:114:5 + | +LL | 2.0f32.to_le_bytes(); + | ^^^^^^^^^^^^^^^^^^^^ + +error: use of the method `to_le_bytes` + --> $DIR/endian_bytes.rs:115:5 + | +LL | 2.0f64.to_le_bytes(); + | ^^^^^^^^^^^^^^^^^^^^ + +error: use of the method `to_be_bytes` + --> $DIR/endian_bytes.rs:135:5 + | +LL | 2u8.to_be_bytes(); + | ^^^^^^^^^^^^^^^^^ + +error: use of the method `to_be_bytes` + --> $DIR/endian_bytes.rs:136:5 + | +LL | 2i8.to_be_bytes(); + | ^^^^^^^^^^^^^^^^^ + +error: use of the method `to_be_bytes` + --> $DIR/endian_bytes.rs:137:5 + | +LL | 2u16.to_be_bytes(); + | ^^^^^^^^^^^^^^^^^^ + +error: use of the method `to_be_bytes` + --> $DIR/endian_bytes.rs:138:5 + | +LL | 2i16.to_be_bytes(); + | ^^^^^^^^^^^^^^^^^^ + +error: use of the method `to_be_bytes` + --> $DIR/endian_bytes.rs:139:5 + | +LL | 2u32.to_be_bytes(); + | ^^^^^^^^^^^^^^^^^^ + +error: use of the method `to_be_bytes` + --> $DIR/endian_bytes.rs:140:5 + | +LL | 2i32.to_be_bytes(); + | ^^^^^^^^^^^^^^^^^^ + +error: use of the method `to_be_bytes` + --> $DIR/endian_bytes.rs:141:5 + | +LL | 2u64.to_be_bytes(); + | ^^^^^^^^^^^^^^^^^^ + +error: use of the method `to_be_bytes` + --> $DIR/endian_bytes.rs:142:5 + | +LL | 2i64.to_be_bytes(); + | ^^^^^^^^^^^^^^^^^^ + +error: use of the method `to_be_bytes` + --> $DIR/endian_bytes.rs:143:5 + | +LL | 2u128.to_be_bytes(); + | ^^^^^^^^^^^^^^^^^^^ + +error: use of the method `to_be_bytes` + --> $DIR/endian_bytes.rs:144:5 + | +LL | 2i128.to_be_bytes(); + | ^^^^^^^^^^^^^^^^^^^ + +error: use of the method `to_be_bytes` + --> $DIR/endian_bytes.rs:145:5 + | +LL | 2usize.to_be_bytes(); + | ^^^^^^^^^^^^^^^^^^^^ + +error: use of the method `to_be_bytes` + --> $DIR/endian_bytes.rs:146:5 + | +LL | 2isize.to_be_bytes(); + | ^^^^^^^^^^^^^^^^^^^^ + +error: use of the method `to_be_bytes` + --> $DIR/endian_bytes.rs:147:5 + | +LL | 2.0f32.to_be_bytes(); + | ^^^^^^^^^^^^^^^^^^^^ + +error: use of the method `to_be_bytes` + --> $DIR/endian_bytes.rs:148:5 + | +LL | 2.0f64.to_be_bytes(); + | ^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 145 previous errors + From 97a0ccc1d312ed763584c28b6d669cffba87c910 Mon Sep 17 00:00:00 2001 From: Centri3 <114838443+Centri3@users.noreply.github.com> Date: Thu, 25 May 2023 11:02:54 -0500 Subject: [PATCH 024/310] implement `host_endian_bytes` and the other two --- clippy_lints/src/endian_bytes.rs | 229 ++-- tests/ui/endian_bytes.rs | 260 ++-- tests/ui/endian_bytes.stderr | 1893 ++++++++++++++---------------- 3 files changed, 1142 insertions(+), 1240 deletions(-) diff --git a/clippy_lints/src/endian_bytes.rs b/clippy_lints/src/endian_bytes.rs index bf6b92644e2..6486430cf57 100644 --- a/clippy_lints/src/endian_bytes.rs +++ b/clippy_lints/src/endian_bytes.rs @@ -1,29 +1,11 @@ -use clippy_utils::{ - diagnostics::{span_lint_and_help, span_lint_and_then}, - is_lint_allowed, match_def_path, path_def_id, -}; +use crate::Lint; +use clippy_utils::{diagnostics::span_lint_and_then, is_lint_allowed}; use rustc_hir::{Expr, ExprKind}; -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! { - /// ### What it does - /// - /// ### Why is this bad? - /// - /// ### Example - /// ```rust - /// // example code where clippy issues a warning - /// ``` - /// Use instead: - /// ```rust - /// // example code which does not raise clippy warning - /// ``` - #[clippy::version = "1.71.0"] - pub HOST_ENDIAN_BYTES, - restriction, - "disallows usage of the `to_ne_bytes` method" -} +use rustc_span::Symbol; +use std::borrow::Cow; declare_clippy_lint! { /// ### What it does @@ -38,9 +20,9 @@ declare_clippy_lint! { /// let _y = 2i64.to_ne_bytes(); /// ``` #[clippy::version = "1.71.0"] - pub LITTLE_ENDIAN_BYTES, + pub HOST_ENDIAN_BYTES, restriction, - "disallows usage of the `to_le_bytes` method" + "disallows usage of the `to_ne_bytes` method" } declare_clippy_lint! { @@ -48,10 +30,32 @@ declare_clippy_lint! { /// Checks for the usage of the `to_le_bytes` method. /// /// ### Why is this bad? + /// It's not, but some may wish to lint usages of this method, either to suggest using the host + /// endianness or big endian. /// /// ### Example /// ```rust,ignore - /// // example code where clippy issues a warning + /// let _x = 2i32.to_le_bytes(); + /// let _y = 2i64.to_le_bytes(); + /// ``` + #[clippy::version = "1.71.0"] + pub LITTLE_ENDIAN_BYTES, + restriction, + "disallows usage of the `to_le_bytes` method" +} + +declare_clippy_lint! { + /// ### What it does + /// Checks for the usage of the `to_be_bytes` method. + /// + /// ### Why is this bad? + /// It's not, but some may wish to lint usages of this method, either to suggest using the host + /// endianness or little endian. + /// + /// ### Example + /// ```rust,ignore + /// let _x = 2i32.to_be_bytes(); + /// let _y = 2i64.to_be_bytes(); /// ``` #[clippy::version = "1.71.0"] pub BIG_ENDIAN_BYTES, @@ -61,78 +65,133 @@ declare_clippy_lint! { declare_lint_pass!(EndianBytes => [HOST_ENDIAN_BYTES, LITTLE_ENDIAN_BYTES, BIG_ENDIAN_BYTES]); +#[derive(Clone, Debug)] +enum LintKind { + Host, + Little, + Big, +} + +impl LintKind { + fn allowed(&self, cx: &LateContext<'_>, expr: &Expr<'_>) -> bool { + is_lint_allowed(cx, self.as_lint(), expr.hir_id) + } + + fn as_lint(&self) -> &'static Lint { + match self { + LintKind::Host => HOST_ENDIAN_BYTES, + LintKind::Little => LITTLE_ENDIAN_BYTES, + LintKind::Big => BIG_ENDIAN_BYTES, + } + } + + fn to_name(&self, prefix: &str) -> String { + match self { + LintKind::Host => format!("{prefix}_ne_bytes"), + LintKind::Little => format!("{prefix}_le_bytes"), + LintKind::Big => format!("{prefix}_be_bytes"), + } + } +} + impl LateLintPass<'_> for EndianBytes { fn check_expr(&mut self, cx: &LateContext<'_>, expr: &Expr<'_>) { + if in_external_macro(cx.sess(), expr.span) { + return; + } + if_chain! { if let ExprKind::MethodCall(method_name, receiver, args, ..) = expr.kind; if let ExprKind::Lit(..) = receiver.kind; if args.is_empty(); + if try_lint_endian_bytes(cx, expr, "to", method_name.ident.name); then { - if method_name.ident.name == sym!(to_ne_bytes) { - span_lint_and_help( - cx, - HOST_ENDIAN_BYTES, - expr.span, - "use of the method `to_ne_bytes`", - None, - "consider specifying the desired endianness", - ); - } else if method_name.ident.name == sym!(to_le_bytes) { - span_lint_and_then(cx, LITTLE_ENDIAN_BYTES, expr.span, "use of the method `to_le_bytes`", |diag| { - if is_lint_allowed(cx, BIG_ENDIAN_BYTES, expr.hir_id) { - diag.help("use `to_be_bytes` instead"); - } - }); - } else if method_name.ident.name == sym!(to_be_bytes) { - span_lint_and_then(cx, BIG_ENDIAN_BYTES, expr.span, "use of the method `to_be_bytes`", |diag| { - if is_lint_allowed(cx, LITTLE_ENDIAN_BYTES, expr.hir_id) { - diag.help("use `to_le_bytes` instead"); - } - }); - } - - // don't waste time also checking from_**_bytes return; } } - span_lint_and_help( - cx, - HOST_ENDIAN_BYTES, - expr.span, - "use of the method `from_ne_bytes`", - None, - &format!("consider specifying the desired endianness: {expr:?}"), - ); - if_chain! { - if let ExprKind::Call(function, args) = expr.kind; - if let Some(function_def_id) = path_def_id(cx, function); - if args.len() == 1; + if let ExprKind::Call(function, ..) = expr.kind; + if let ExprKind::Path(qpath) = function.kind; + if let Some(def_id) = cx.qpath_res(&qpath, function.hir_id).opt_def_id(); + if let Some(function_name) = cx.get_def_path(def_id).last(); + if cx.typeck_results().expr_ty(expr).is_primitive_ty(); then { - if match_def_path(cx, function_def_id, &["from_ne_bytes"]) { - span_lint_and_help( - cx, - HOST_ENDIAN_BYTES, - expr.span, - "use of the method `from_ne_bytes`", - None, - "consider specifying the desired endianness", - ); - } else if match_def_path(cx, function_def_id, &["from_le_bytes"]) { - span_lint_and_then(cx, LITTLE_ENDIAN_BYTES, expr.span, "use of the method `from_le_bytes`", |diag| { - if is_lint_allowed(cx, BIG_ENDIAN_BYTES, expr.hir_id) { - diag.help("use `from_be_bytes` instead"); - } - }); - } else if match_def_path(cx, function_def_id, &["from_be_bytes"]) { - span_lint_and_then(cx, BIG_ENDIAN_BYTES, expr.span, "use of the method `from_be_bytes`", |diag| { - if is_lint_allowed(cx, LITTLE_ENDIAN_BYTES, expr.hir_id) { - diag.help("use `from_le_bytes` instead"); - } - }); - } + try_lint_endian_bytes(cx, expr, "from", *function_name); } } } } + +fn try_lint_endian_bytes(cx: &LateContext<'_>, expr: &Expr<'_>, prefix: &str, name: Symbol) -> bool { + let ne = format!("{prefix}_ne_bytes"); + let le = format!("{prefix}_le_bytes"); + let be = format!("{prefix}_be_bytes"); + + let (lint, other_lints) = match name.as_str() { + name if name == ne => ((&LintKind::Host), [(&LintKind::Little), (&LintKind::Big)]), + name if name == le => ((&LintKind::Little), [(&LintKind::Host), (&LintKind::Big)]), + name if name == be => ((&LintKind::Big), [(&LintKind::Host), (&LintKind::Little)]), + _ => return false, + }; + + let mut help = None; + + 'build_help: { + // all lints disallowed, don't give help here + if [&[lint], other_lints.as_slice()] + .concat() + .iter() + .all(|lint| !lint.allowed(cx, expr)) + { + break 'build_help; + } + + // ne_bytes and all other lints allowed + if lint.to_name(prefix) == ne && other_lints.iter().all(|lint| lint.allowed(cx, expr)) { + help = Some(Cow::Borrowed("specify the desired endianness explicitly")); + break 'build_help; + } + + // le_bytes where ne_bytes allowed but be_bytes is not, or le_bytes where ne_bytes allowed but + // le_bytes is not + if (lint.to_name(prefix) == le || lint.to_name(prefix) == be) && LintKind::Host.allowed(cx, expr) { + help = Some(Cow::Borrowed("use the native endianness instead")); + break 'build_help; + } + + let allowed_lints = other_lints.iter().filter(|lint| lint.allowed(cx, expr)); + let len = allowed_lints.clone().count(); + + let mut help_str = "use ".to_owned(); + + for (i, lint) in allowed_lints.enumerate() { + let only_one = len == 1; + if !only_one { + help_str.push_str("either of "); + } + + help_str.push_str(&format!("`{}` ", lint.to_name(prefix))); + + if i != len && !only_one { + help_str.push_str("or "); + } + } + + help = Some(Cow::Owned(help_str + "instead")); + } + + span_lint_and_then( + cx, + lint.as_lint(), + expr.span, + &format!("usage of the method `{}`", lint.to_name(prefix)), + move |diag| { + if let Some(help) = help { + diag.help(help); + } + }, + ); + + true +} diff --git a/tests/ui/endian_bytes.rs b/tests/ui/endian_bytes.rs index 1dfda9d53bf..ccee8e20a3c 100644 --- a/tests/ui/endian_bytes.rs +++ b/tests/ui/endian_bytes.rs @@ -2,162 +2,126 @@ #![allow(clippy::diverging_sub_expression)] #![no_main] +macro_rules! fn_body { + () => { + 2u8.to_ne_bytes(); + 2i8.to_ne_bytes(); + 2u16.to_ne_bytes(); + 2i16.to_ne_bytes(); + 2u32.to_ne_bytes(); + 2i32.to_ne_bytes(); + 2u64.to_ne_bytes(); + 2i64.to_ne_bytes(); + 2u128.to_ne_bytes(); + 2i128.to_ne_bytes(); + 2.0f32.to_ne_bytes(); + 2.0f64.to_ne_bytes(); + 2usize.to_ne_bytes(); + 2isize.to_ne_bytes(); + u8::from_ne_bytes(todo!()); + i8::from_ne_bytes(todo!()); + u16::from_ne_bytes(todo!()); + i16::from_ne_bytes(todo!()); + u32::from_ne_bytes(todo!()); + i32::from_ne_bytes(todo!()); + u64::from_ne_bytes(todo!()); + i64::from_ne_bytes(todo!()); + u128::from_ne_bytes(todo!()); + i128::from_ne_bytes(todo!()); + usize::from_ne_bytes(todo!()); + isize::from_ne_bytes(todo!()); + f32::from_ne_bytes(todo!()); + f64::from_ne_bytes(todo!()); + + 2u8.to_le_bytes(); + 2i8.to_le_bytes(); + 2u16.to_le_bytes(); + 2i16.to_le_bytes(); + 2u32.to_le_bytes(); + 2i32.to_le_bytes(); + 2u64.to_le_bytes(); + 2i64.to_le_bytes(); + 2u128.to_le_bytes(); + 2i128.to_le_bytes(); + 2.0f32.to_le_bytes(); + 2.0f64.to_le_bytes(); + 2usize.to_le_bytes(); + 2isize.to_le_bytes(); + u8::from_le_bytes(todo!()); + i8::from_le_bytes(todo!()); + u16::from_le_bytes(todo!()); + i16::from_le_bytes(todo!()); + u32::from_le_bytes(todo!()); + i32::from_le_bytes(todo!()); + u64::from_le_bytes(todo!()); + i64::from_le_bytes(todo!()); + u128::from_le_bytes(todo!()); + i128::from_le_bytes(todo!()); + usize::from_le_bytes(todo!()); + isize::from_le_bytes(todo!()); + f32::from_le_bytes(todo!()); + f64::from_le_bytes(todo!()); + }; +} + +// bless breaks if I use fn_body too much (oops) +macro_rules! fn_body_small { + () => { + 2u8.to_ne_bytes(); + u8::from_ne_bytes(todo!()); + + 2u8.to_le_bytes(); + u8::from_le_bytes(todo!()); + + 2u8.to_be_bytes(); + u8::from_be_bytes(todo!()); + }; +} + +#[rustfmt::skip] #[warn(clippy::host_endian_bytes)] -fn host() { - 2u8.to_ne_bytes(); - 2i8.to_ne_bytes(); - 2u16.to_ne_bytes(); - 2i16.to_ne_bytes(); - 2u32.to_ne_bytes(); - 2i32.to_ne_bytes(); - 2u64.to_ne_bytes(); - 2i64.to_ne_bytes(); - 2u128.to_ne_bytes(); - 2i128.to_ne_bytes(); - 2usize.to_ne_bytes(); - 2isize.to_ne_bytes(); - 2.0f32.to_ne_bytes(); - 2.0f64.to_ne_bytes(); - u8::from_ne_bytes(todo!()); - i8::from_ne_bytes(todo!()); - u16::from_ne_bytes(todo!()); - i16::from_ne_bytes(todo!()); - u32::from_ne_bytes(todo!()); - i32::from_ne_bytes(todo!()); - u64::from_ne_bytes(todo!()); - i64::from_ne_bytes(todo!()); - u128::from_ne_bytes(todo!()); - i128::from_ne_bytes(todo!()); - f32::from_ne_bytes(todo!()); - f64::from_ne_bytes(todo!()); -} +fn host() { fn_body!(); } +#[rustfmt::skip] #[warn(clippy::little_endian_bytes)] -fn little() { - 2u8.to_le_bytes(); - 2i8.to_le_bytes(); - 2u16.to_le_bytes(); - 2i16.to_le_bytes(); - 2u32.to_le_bytes(); - 2i32.to_le_bytes(); - 2u64.to_le_bytes(); - 2i64.to_le_bytes(); - 2u128.to_le_bytes(); - 2i128.to_le_bytes(); - 2usize.to_le_bytes(); - 2isize.to_le_bytes(); - 2.0f32.to_le_bytes(); - 2.0f64.to_le_bytes(); - u8::from_le_bytes(todo!()); - i8::from_le_bytes(todo!()); - u16::from_le_bytes(todo!()); - i16::from_le_bytes(todo!()); - u32::from_le_bytes(todo!()); - i32::from_le_bytes(todo!()); - u64::from_le_bytes(todo!()); - i64::from_le_bytes(todo!()); - u128::from_le_bytes(todo!()); - i128::from_le_bytes(todo!()); - usize::from_le_bytes(todo!()); - isize::from_le_bytes(todo!()); - f32::from_le_bytes(todo!()); - f64::from_le_bytes(todo!()); -} +fn little() { fn_body!(); } +#[rustfmt::skip] #[warn(clippy::big_endian_bytes)] -fn big() { - 2u8.to_be_bytes(); - 2i8.to_be_bytes(); - 2u16.to_be_bytes(); - 2i16.to_be_bytes(); - 2u32.to_be_bytes(); - 2i32.to_be_bytes(); - 2u64.to_be_bytes(); - 2i64.to_be_bytes(); - 2u128.to_be_bytes(); - 2i128.to_be_bytes(); - 2.0f32.to_be_bytes(); - 2.0f64.to_be_bytes(); - 2usize.to_be_bytes(); - 2isize.to_be_bytes(); - u8::from_be_bytes(todo!()); - i8::from_be_bytes(todo!()); - u16::from_be_bytes(todo!()); - i16::from_be_bytes(todo!()); - u32::from_be_bytes(todo!()); - i32::from_be_bytes(todo!()); - u64::from_be_bytes(todo!()); - i64::from_be_bytes(todo!()); - u128::from_be_bytes(todo!()); - i128::from_be_bytes(todo!()); - usize::from_be_bytes(todo!()); - isize::from_be_bytes(todo!()); - f32::from_be_bytes(todo!()); - f64::from_be_bytes(todo!()); -} +fn big() { fn_body!(); } +#[rustfmt::skip] +#[warn(clippy::host_endian_bytes)] +#[warn(clippy::big_endian_bytes)] +fn host_encourage_little() { fn_body_small!(); } + +#[rustfmt::skip] +#[warn(clippy::host_endian_bytes)] +#[warn(clippy::little_endian_bytes)] +fn host_encourage_big() { fn_body_small!(); } + +#[rustfmt::skip] +#[warn(clippy::host_endian_bytes)] #[warn(clippy::little_endian_bytes)] #[warn(clippy::big_endian_bytes)] -fn little_no_help() { - 2u8.to_le_bytes(); - 2i8.to_le_bytes(); - 2u16.to_le_bytes(); - 2i16.to_le_bytes(); - 2u32.to_le_bytes(); - 2i32.to_le_bytes(); - 2u64.to_le_bytes(); - 2i64.to_le_bytes(); - 2u128.to_le_bytes(); - 2i128.to_le_bytes(); - 2usize.to_le_bytes(); - 2isize.to_le_bytes(); - 2.0f32.to_le_bytes(); - 2.0f64.to_le_bytes(); - u8::from_le_bytes(todo!()); - i8::from_le_bytes(todo!()); - u16::from_le_bytes(todo!()); - i16::from_le_bytes(todo!()); - u32::from_le_bytes(todo!()); - i32::from_le_bytes(todo!()); - u64::from_le_bytes(todo!()); - i64::from_le_bytes(todo!()); - u128::from_le_bytes(todo!()); - i128::from_le_bytes(todo!()); - usize::from_le_bytes(todo!()); - isize::from_le_bytes(todo!()); - f32::from_le_bytes(todo!()); - f64::from_le_bytes(todo!()); -} +fn no_help() { fn_body_small!(); } +#[rustfmt::skip] +#[warn(clippy::little_endian_bytes)] +#[warn(clippy::big_endian_bytes)] +fn little_encourage_host() { fn_body_small!(); } + +#[rustfmt::skip] +#[warn(clippy::host_endian_bytes)] +#[warn(clippy::little_endian_bytes)] +fn little_encourage_big() { fn_body_small!(); } + +#[rustfmt::skip] #[warn(clippy::big_endian_bytes)] #[warn(clippy::little_endian_bytes)] -fn big_no_help() { - 2u8.to_be_bytes(); - 2i8.to_be_bytes(); - 2u16.to_be_bytes(); - 2i16.to_be_bytes(); - 2u32.to_be_bytes(); - 2i32.to_be_bytes(); - 2u64.to_be_bytes(); - 2i64.to_be_bytes(); - 2u128.to_be_bytes(); - 2i128.to_be_bytes(); - 2usize.to_be_bytes(); - 2isize.to_be_bytes(); - 2.0f32.to_be_bytes(); - 2.0f64.to_be_bytes(); - u8::from_be_bytes(todo!()); - i8::from_be_bytes(todo!()); - u16::from_be_bytes(todo!()); - i16::from_be_bytes(todo!()); - u32::from_be_bytes(todo!()); - i32::from_be_bytes(todo!()); - u64::from_be_bytes(todo!()); - i64::from_be_bytes(todo!()); - u128::from_be_bytes(todo!()); - i128::from_be_bytes(todo!()); - usize::from_be_bytes(todo!()); - isize::from_be_bytes(todo!()); - f32::from_be_bytes(todo!()); - f64::from_be_bytes(todo!()); -} +fn big_encourage_host() { fn_body_small!(); } + +#[rustfmt::skip] +#[warn(clippy::host_endian_bytes)] +#[warn(clippy::big_endian_bytes)] +fn big_encourage_little() { fn_body_small!(); } diff --git a/tests/ui/endian_bytes.stderr b/tests/ui/endian_bytes.stderr index afbb8e3b16c..ff8d1a98f4f 100644 --- a/tests/ui/endian_bytes.stderr +++ b/tests/ui/endian_bytes.stderr @@ -1,1152 +1,1031 @@ -error: use of the method `from_ne_bytes` - --> $DIR/endian_bytes.rs:6:11 +error: usage of the method `to_ne_bytes` + --> $DIR/endian_bytes.rs:7:9 | -LL | fn host() { - | ___________^ -LL | | 2u8.to_ne_bytes(); -LL | | 2i8.to_ne_bytes(); -LL | | 2u16.to_ne_bytes(); -... | -LL | | f64::from_ne_bytes(todo!()); -LL | | } - | |_^ +LL | 2u8.to_ne_bytes(); + | ^^^^^^^^^^^^^^^^^ +... +LL | fn host() { fn_body!(); } + | ---------- in this macro invocation | - = help: consider specifying the desired endianness: Expr { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).202), kind: Block(Block { stmts: [Stmt { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).4), kind: Semi(Expr { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).1), kind: MethodCall(PathSegment { ident: to_ne_bytes#0, hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).2), res: Err, args: None, infer_args: true }, Expr { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).3), kind: Lit(Spanned { node: Int(2, Unsigned(U8)), span: $DIR/endian_bytes.rs:7:5: 7:8 (#0) }), span: $DIR/endian_bytes.rs:7:5: 7:8 (#0) }, [], $DIR/endian_bytes.rs:7:9: 7:22 (#0)), span: $DIR/endian_bytes.rs:7:5: 7:22 (#0) }), span: $DIR/endian_bytes.rs:7:5: 7:23 (#0) }, Stmt { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).8), kind: Semi(Expr { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).5), kind: MethodCall(PathSegment { ident: to_ne_bytes#0, hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).6), res: Err, args: None, infer_args: true }, Expr { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).7), kind: Lit(Spanned { node: Int(2, Signed(I8)), span: $DIR/endian_bytes.rs:8:5: 8:8 (#0) }), span: $DIR/endian_bytes.rs:8:5: 8:8 (#0) }, [], $DIR/endian_bytes.rs:8:9: 8:22 (#0)), span: $DIR/endian_bytes.rs:8:5: 8:22 (#0) }), span: $DIR/endian_bytes.rs:8:5: 8:23 (#0) }, Stmt { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).12), kind: Semi(Expr { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).9), kind: MethodCall(PathSegment { ident: to_ne_bytes#0, hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).10), res: Err, args: None, infer_args: true }, Expr { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).11), kind: Lit(Spanned { node: Int(2, Unsigned(U16)), span: $DIR/endian_bytes.rs:9:5: 9:9 (#0) }), span: $DIR/endian_bytes.rs:9:5: 9:9 (#0) }, [], $DIR/endian_bytes.rs:9:10: 9:23 (#0)), span: $DIR/endian_bytes.rs:9:5: 9:23 (#0) }), span: $DIR/endian_bytes.rs:9:5: 9:24 (#0) }, Stmt { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).16), kind: Semi(Expr { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).13), kind: MethodCall(PathSegment { ident: to_ne_bytes#0, hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).14), res: Err, args: None, infer_args: true }, Expr { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).15), kind: Lit(Spanned { node: Int(2, Signed(I16)), span: $DIR/endian_bytes.rs:10:5: 10:9 (#0) }), span: $DIR/endian_bytes.rs:10:5: 10:9 (#0) }, [], $DIR/endian_bytes.rs:10:10: 10:23 (#0)), span: $DIR/endian_bytes.rs:10:5: 10:23 (#0) }), span: $DIR/endian_bytes.rs:10:5: 10:24 (#0) }, Stmt { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).20), kind: Semi(Expr { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).17), kind: MethodCall(PathSegment { ident: to_ne_bytes#0, hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).18), res: Err, args: None, infer_args: true }, Expr { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).19), kind: Lit(Spanned { node: Int(2, Unsigned(U32)), span: $DIR/endian_bytes.rs:11:5: 11:9 (#0) }), span: $DIR/endian_bytes.rs:11:5: 11:9 (#0) }, [], $DIR/endian_bytes.rs:11:10: 11:23 (#0)), span: $DIR/endian_bytes.rs:11:5: 11:23 (#0) }), span: $DIR/endian_bytes.rs:11:5: 11:24 (#0) }, Stmt { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).24), kind: Semi(Expr { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).21), kind: MethodCall(PathSegment { ident: to_ne_bytes#0, hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).22), res: Err, args: None, infer_args: true }, Expr { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).23), kind: Lit(Spanned { node: Int(2, Signed(I32)), span: $DIR/endian_bytes.rs:12:5: 12:9 (#0) }), span: $DIR/endian_bytes.rs:12:5: 12:9 (#0) }, [], $DIR/endian_bytes.rs:12:10: 12:23 (#0)), span: $DIR/endian_bytes.rs:12:5: 12:23 (#0) }), span: $DIR/endian_bytes.rs:12:5: 12:24 (#0) }, Stmt { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).28), kind: Semi(Expr { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).25), kind: MethodCall(PathSegment { ident: to_ne_bytes#0, hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).26), res: Err, args: None, infer_args: true }, Expr { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).27), kind: Lit(Spanned { node: Int(2, Unsigned(U64)), span: $DIR/endian_bytes.rs:13:5: 13:9 (#0) }), span: $DIR/endian_bytes.rs:13:5: 13:9 (#0) }, [], $DIR/endian_bytes.rs:13:10: 13:23 (#0)), span: $DIR/endian_bytes.rs:13:5: 13:23 (#0) }), span: $DIR/endian_bytes.rs:13:5: 13:24 (#0) }, Stmt { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).32), kind: Semi(Expr { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).29), kind: MethodCall(PathSegment { ident: to_ne_bytes#0, hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).30), res: Err, args: None, infer_args: true }, Expr { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).31), kind: Lit(Spanned { node: Int(2, Signed(I64)), span: $DIR/endian_bytes.rs:14:5: 14:9 (#0) }), span: $DIR/endian_bytes.rs:14:5: 14:9 (#0) }, [], $DIR/endian_bytes.rs:14:10: 14:23 (#0)), span: $DIR/endian_bytes.rs:14:5: 14:23 (#0) }), span: $DIR/endian_bytes.rs:14:5: 14:24 (#0) }, Stmt { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).36), kind: Semi(Expr { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).33), kind: MethodCall(PathSegment { ident: to_ne_bytes#0, hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).34), res: Err, args: None, infer_args: true }, Expr { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).35), kind: Lit(Spanned { node: Int(2, Unsigned(U128)), span: $DIR/endian_bytes.rs:15:5: 15:10 (#0) }), span: $DIR/endian_bytes.rs:15:5: 15:10 (#0) }, [], $DIR/endian_bytes.rs:15:11: 15:24 (#0)), span: $DIR/endian_bytes.rs:15:5: 15:24 (#0) }), span: $DIR/endian_bytes.rs:15:5: 15:25 (#0) }, Stmt { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).40), kind: Semi(Expr { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).37), kind: MethodCall(PathSegment { ident: to_ne_bytes#0, hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).38), res: Err, args: None, infer_args: true }, Expr { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).39), kind: Lit(Spanned { node: Int(2, Signed(I128)), span: $DIR/endian_bytes.rs:16:5: 16:10 (#0) }), span: $DIR/endian_bytes.rs:16:5: 16:10 (#0) }, [], $DIR/endian_bytes.rs:16:11: 16:24 (#0)), span: $DIR/endian_bytes.rs:16:5: 16:24 (#0) }), span: $DIR/endian_bytes.rs:16:5: 16:25 (#0) }, Stmt { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).44), kind: Semi(Expr { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).41), kind: MethodCall(PathSegment { ident: to_ne_bytes#0, hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).42), res: Err, args: None, infer_args: true }, Expr { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).43), kind: Lit(Spanned { node: Int(2, Unsigned(Usize)), span: $DIR/endian_bytes.rs:17:5: 17:11 (#0) }), span: $DIR/endian_bytes.rs:17:5: 17:11 (#0) }, [], $DIR/endian_bytes.rs:17:12: 17:25 (#0)), span: $DIR/endian_bytes.rs:17:5: 17:25 (#0) }), span: $DIR/endian_bytes.rs:17:5: 17:26 (#0) }, Stmt { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).48), kind: Semi(Expr { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).45), kind: MethodCall(PathSegment { ident: to_ne_bytes#0, hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).46), res: Err, args: None, infer_args: true }, Expr { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).47), kind: Lit(Spanned { node: Int(2, Signed(Isize)), span: $DIR/endian_bytes.rs:18:5: 18:11 (#0) }), span: $DIR/endian_bytes.rs:18:5: 18:11 (#0) }, [], $DIR/endian_bytes.rs:18:12: 18:25 (#0)), span: $DIR/endian_bytes.rs:18:5: 18:25 (#0) }), span: $DIR/endian_bytes.rs:18:5: 18:26 (#0) }, Stmt { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).52), kind: Semi(Expr { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).49), kind: MethodCall(PathSegment { ident: to_ne_bytes#0, hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).50), res: Err, args: None, infer_args: true }, Expr { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).51), kind: Lit(Spanned { node: Float("2.0", Suffixed(F32)), span: $DIR/endian_bytes.rs:19:5: 19:11 (#0) }), span: $DIR/endian_bytes.rs:19:5: 19:11 (#0) }, [], $DIR/endian_bytes.rs:19:12: 19:25 (#0)), span: $DIR/endian_bytes.rs:19:5: 19:25 (#0) }), span: $DIR/endian_bytes.rs:19:5: 19:26 (#0) }, Stmt { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).56), kind: Semi(Expr { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).53), kind: MethodCall(PathSegment { ident: to_ne_bytes#0, hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).54), res: Err, args: None, infer_args: true }, Expr { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).55), kind: Lit(Spanned { node: Float("2.0", Suffixed(F64)), span: $DIR/endian_bytes.rs:20:5: 20:11 (#0) }), span: $DIR/endian_bytes.rs:20:5: 20:11 (#0) }, [], $DIR/endian_bytes.rs:20:12: 20:25 (#0)), span: $DIR/endian_bytes.rs:20:5: 20:25 (#0) }), span: $DIR/endian_bytes.rs:20:5: 20:26 (#0) }, Stmt { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).68), kind: Semi(Expr { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).57), kind: Call(Expr { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).58), kind: Path(TypeRelative(Ty { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).60), kind: Path(Resolved(None, Path { span: $DIR/endian_bytes.rs:21:5: 21:7 (#0), res: PrimTy(Uint(U8)), segments: [PathSegment { ident: u8#0, hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).59), res: PrimTy(Uint(U8)), args: None, infer_args: true }] })), span: $DIR/endian_bytes.rs:21:5: 21:7 (#0) }, PathSegment { ident: from_ne_bytes#0, hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).61), res: Err, args: None, infer_args: true })), span: $DIR/endian_bytes.rs:21:5: 21:22 (#0) }, [Expr { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).62), kind: Call(Expr { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).63), kind: Path(Resolved(None, Path { span: /home/centri/.rustup/toolchains/nightly-2023-05-05-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/macros/mod.rs:773:9: 773:33 (#4), res: Def(Fn, DefId(2:8292 ~ core[690e]::panicking::panic)), segments: [PathSegment { ident: $crate#4, hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).64), res: Err, args: None, infer_args: true }, PathSegment { ident: panicking#4, hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).65), res: Def(Mod, DefId(2:8281 ~ core[690e]::panicking)), args: None, infer_args: true }, PathSegment { ident: panic#4, hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).66), res: Def(Fn, DefId(2:8292 ~ core[690e]::panicking::panic)), args: None, infer_args: true }] })), span: /home/centri/.rustup/toolchains/nightly-2023-05-05-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/macros/mod.rs:773:9: 773:33 (#4) }, [Expr { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).67), kind: Lit(Spanned { node: Str("not yet implemented", Cooked), span: /home/centri/.rustup/toolchains/nightly-2023-05-05-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/macros/mod.rs:773:34: 773:55 (#4) }), span: /home/centri/.rustup/toolchains/nightly-2023-05-05-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/macros/mod.rs:773:34: 773:55 (#4) }]), span: /home/centri/.rustup/toolchains/nightly-2023-05-05-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/macros/mod.rs:773:9: 773:56 (#4) }]), span: $DIR/endian_bytes.rs:21:5: 21:31 (#0) }), span: $DIR/endian_bytes.rs:21:5: 21:32 (#0) }, Stmt { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).80), kind: Semi(Expr { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).69), kind: Call(Expr { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).70), kind: Path(TypeRelative(Ty { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).72), kind: Path(Resolved(None, Path { span: $DIR/endian_bytes.rs:22:5: 22:7 (#0), res: PrimTy(Int(I8)), segments: [PathSegment { ident: i8#0, hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).71), res: PrimTy(Int(I8)), args: None, infer_args: true }] })), span: $DIR/endian_bytes.rs:22:5: 22:7 (#0) }, PathSegment { ident: from_ne_bytes#0, hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).73), res: Err, args: None, infer_args: true })), span: $DIR/endian_bytes.rs:22:5: 22:22 (#0) }, [Expr { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).74), kind: Call(Expr { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).75), kind: Path(Resolved(None, Path { span: /home/centri/.rustup/toolchains/nightly-2023-05-05-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/macros/mod.rs:773:9: 773:33 (#5), res: Def(Fn, DefId(2:8292 ~ core[690e]::panicking::panic)), segments: [PathSegment { ident: $crate#5, hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).76), res: Err, args: None, infer_args: true }, PathSegment { ident: panicking#5, hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).77), res: Def(Mod, DefId(2:8281 ~ core[690e]::panicking)), args: None, infer_args: true }, PathSegment { ident: panic#5, hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).78), res: Def(Fn, DefId(2:8292 ~ core[690e]::panicking::panic)), args: None, infer_args: true }] })), span: /home/centri/.rustup/toolchains/nightly-2023-05-05-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/macros/mod.rs:773:9: 773:33 (#5) }, [Expr { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).79), kind: Lit(Spanned { node: Str("not yet implemented", Cooked), span: /home/centri/.rustup/toolchains/nightly-2023-05-05-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/macros/mod.rs:773:34: 773:55 (#5) }), span: /home/centri/.rustup/toolchains/nightly-2023-05-05-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/macros/mod.rs:773:34: 773:55 (#5) }]), span: /home/centri/.rustup/toolchains/nightly-2023-05-05-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/macros/mod.rs:773:9: 773:56 (#5) }]), span: $DIR/endian_bytes.rs:22:5: 22:31 (#0) }), span: $DIR/endian_bytes.rs:22:5: 22:32 (#0) }, Stmt { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).92), kind: Semi(Expr { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).81), kind: Call(Expr { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).82), kind: Path(TypeRelative(Ty { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).84), kind: Path(Resolved(None, Path { span: $DIR/endian_bytes.rs:23:5: 23:8 (#0), res: PrimTy(Uint(U16)), segments: [PathSegment { ident: u16#0, hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).83), res: PrimTy(Uint(U16)), args: None, infer_args: true }] })), span: $DIR/endian_bytes.rs:23:5: 23:8 (#0) }, PathSegment { ident: from_ne_bytes#0, hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).85), res: Err, args: None, infer_args: true })), span: $DIR/endian_bytes.rs:23:5: 23:23 (#0) }, [Expr { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).86), kind: Call(Expr { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).87), kind: Path(Resolved(None, Path { span: /home/centri/.rustup/toolchains/nightly-2023-05-05-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/macros/mod.rs:773:9: 773:33 (#6), res: Def(Fn, DefId(2:8292 ~ core[690e]::panicking::panic)), segments: [PathSegment { ident: $crate#6, hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).88), res: Err, args: None, infer_args: true }, PathSegment { ident: panicking#6, hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).89), res: Def(Mod, DefId(2:8281 ~ core[690e]::panicking)), args: None, infer_args: true }, PathSegment { ident: panic#6, hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).90), res: Def(Fn, DefId(2:8292 ~ core[690e]::panicking::panic)), args: None, infer_args: true }] })), span: /home/centri/.rustup/toolchains/nightly-2023-05-05-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/macros/mod.rs:773:9: 773:33 (#6) }, [Expr { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).91), kind: Lit(Spanned { node: Str("not yet implemented", Cooked), span: /home/centri/.rustup/toolchains/nightly-2023-05-05-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/macros/mod.rs:773:34: 773:55 (#6) }), span: /home/centri/.rustup/toolchains/nightly-2023-05-05-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/macros/mod.rs:773:34: 773:55 (#6) }]), span: /home/centri/.rustup/toolchains/nightly-2023-05-05-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/macros/mod.rs:773:9: 773:56 (#6) }]), span: $DIR/endian_bytes.rs:23:5: 23:32 (#0) }), span: $DIR/endian_bytes.rs:23:5: 23:33 (#0) }, Stmt { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).104), kind: Semi(Expr { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).93), kind: Call(Expr { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).94), kind: Path(TypeRelative(Ty { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).96), kind: Path(Resolved(None, Path { span: $DIR/endian_bytes.rs:24:5: 24:8 (#0), res: PrimTy(Int(I16)), segments: [PathSegment { ident: i16#0, hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).95), res: PrimTy(Int(I16)), args: None, infer_args: true }] })), span: $DIR/endian_bytes.rs:24:5: 24:8 (#0) }, PathSegment { ident: from_ne_bytes#0, hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).97), res: Err, args: None, infer_args: true })), span: $DIR/endian_bytes.rs:24:5: 24:23 (#0) }, [Expr { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).98), kind: Call(Expr { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).99), kind: Path(Resolved(None, Path { span: /home/centri/.rustup/toolchains/nightly-2023-05-05-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/macros/mod.rs:773:9: 773:33 (#7), res: Def(Fn, DefId(2:8292 ~ core[690e]::panicking::panic)), segments: [PathSegment { ident: $crate#7, hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).100), res: Err, args: None, infer_args: true }, PathSegment { ident: panicking#7, hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).101), res: Def(Mod, DefId(2:8281 ~ core[690e]::panicking)), args: None, infer_args: true }, PathSegment { ident: panic#7, hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).102), res: Def(Fn, DefId(2:8292 ~ core[690e]::panicking::panic)), args: None, infer_args: true }] })), span: /home/centri/.rustup/toolchains/nightly-2023-05-05-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/macros/mod.rs:773:9: 773:33 (#7) }, [Expr { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).103), kind: Lit(Spanned { node: Str("not yet implemented", Cooked), span: /home/centri/.rustup/toolchains/nightly-2023-05-05-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/macros/mod.rs:773:34: 773:55 (#7) }), span: /home/centri/.rustup/toolchains/nightly-2023-05-05-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/macros/mod.rs:773:34: 773:55 (#7) }]), span: /home/centri/.rustup/toolchains/nightly-2023-05-05-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/macros/mod.rs:773:9: 773:56 (#7) }]), span: $DIR/endian_bytes.rs:24:5: 24:32 (#0) }), span: $DIR/endian_bytes.rs:24:5: 24:33 (#0) }, Stmt { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).116), kind: Semi(Expr { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).105), kind: Call(Expr { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).106), kind: Path(TypeRelative(Ty { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).108), kind: Path(Resolved(None, Path { span: $DIR/endian_bytes.rs:25:5: 25:8 (#0), res: PrimTy(Uint(U32)), segments: [PathSegment { ident: u32#0, hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).107), res: PrimTy(Uint(U32)), args: None, infer_args: true }] })), span: $DIR/endian_bytes.rs:25:5: 25:8 (#0) }, PathSegment { ident: from_ne_bytes#0, hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).109), res: Err, args: None, infer_args: true })), span: $DIR/endian_bytes.rs:25:5: 25:23 (#0) }, [Expr { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).110), kind: Call(Expr { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).111), kind: Path(Resolved(None, Path { span: /home/centri/.rustup/toolchains/nightly-2023-05-05-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/macros/mod.rs:773:9: 773:33 (#8), res: Def(Fn, DefId(2:8292 ~ core[690e]::panicking::panic)), segments: [PathSegment { ident: $crate#8, hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).112), res: Err, args: None, infer_args: true }, PathSegment { ident: panicking#8, hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).113), res: Def(Mod, DefId(2:8281 ~ core[690e]::panicking)), args: None, infer_args: true }, PathSegment { ident: panic#8, hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).114), res: Def(Fn, DefId(2:8292 ~ core[690e]::panicking::panic)), args: None, infer_args: true }] })), span: /home/centri/.rustup/toolchains/nightly-2023-05-05-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/macros/mod.rs:773:9: 773:33 (#8) }, [Expr { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).115), kind: Lit(Spanned { node: Str("not yet implemented", Cooked), span: /home/centri/.rustup/toolchains/nightly-2023-05-05-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/macros/mod.rs:773:34: 773:55 (#8) }), span: /home/centri/.rustup/toolchains/nightly-2023-05-05-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/macros/mod.rs:773:34: 773:55 (#8) }]), span: /home/centri/.rustup/toolchains/nightly-2023-05-05-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/macros/mod.rs:773:9: 773:56 (#8) }]), span: $DIR/endian_bytes.rs:25:5: 25:32 (#0) }), span: $DIR/endian_bytes.rs:25:5: 25:33 (#0) }, Stmt { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).128), kind: Semi(Expr { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).117), kind: Call(Expr { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).118), kind: Path(TypeRelative(Ty { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).120), kind: Path(Resolved(None, Path { span: $DIR/endian_bytes.rs:26:5: 26:8 (#0), res: PrimTy(Int(I32)), segments: [PathSegment { ident: i32#0, hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).119), res: PrimTy(Int(I32)), args: None, infer_args: true }] })), span: $DIR/endian_bytes.rs:26:5: 26:8 (#0) }, PathSegment { ident: from_ne_bytes#0, hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).121), res: Err, args: None, infer_args: true })), span: $DIR/endian_bytes.rs:26:5: 26:23 (#0) }, [Expr { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).122), kind: Call(Expr { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).123), kind: Path(Resolved(None, Path { span: /home/centri/.rustup/toolchains/nightly-2023-05-05-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/macros/mod.rs:773:9: 773:33 (#9), res: Def(Fn, DefId(2:8292 ~ core[690e]::panicking::panic)), segments: [PathSegment { ident: $crate#9, hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).124), res: Err, args: None, infer_args: true }, PathSegment { ident: panicking#9, hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).125), res: Def(Mod, DefId(2:8281 ~ core[690e]::panicking)), args: None, infer_args: true }, PathSegment { ident: panic#9, hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).126), res: Def(Fn, DefId(2:8292 ~ core[690e]::panicking::panic)), args: None, infer_args: true }] })), span: /home/centri/.rustup/toolchains/nightly-2023-05-05-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/macros/mod.rs:773:9: 773:33 (#9) }, [Expr { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).127), kind: Lit(Spanned { node: Str("not yet implemented", Cooked), span: /home/centri/.rustup/toolchains/nightly-2023-05-05-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/macros/mod.rs:773:34: 773:55 (#9) }), span: /home/centri/.rustup/toolchains/nightly-2023-05-05-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/macros/mod.rs:773:34: 773:55 (#9) }]), span: /home/centri/.rustup/toolchains/nightly-2023-05-05-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/macros/mod.rs:773:9: 773:56 (#9) }]), span: $DIR/endian_bytes.rs:26:5: 26:32 (#0) }), span: $DIR/endian_bytes.rs:26:5: 26:33 (#0) }, Stmt { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).140), kind: Semi(Expr { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).129), kind: Call(Expr { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).130), kind: Path(TypeRelative(Ty { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).132), kind: Path(Resolved(None, Path { span: $DIR/endian_bytes.rs:27:5: 27:8 (#0), res: PrimTy(Uint(U64)), segments: [PathSegment { ident: u64#0, hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).131), res: PrimTy(Uint(U64)), args: None, infer_args: true }] })), span: $DIR/endian_bytes.rs:27:5: 27:8 (#0) }, PathSegment { ident: from_ne_bytes#0, hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).133), res: Err, args: None, infer_args: true })), span: $DIR/endian_bytes.rs:27:5: 27:23 (#0) }, [Expr { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).134), kind: Call(Expr { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).135), kind: Path(Resolved(None, Path { span: /home/centri/.rustup/toolchains/nightly-2023-05-05-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/macros/mod.rs:773:9: 773:33 (#10), res: Def(Fn, DefId(2:8292 ~ core[690e]::panicking::panic)), segments: [PathSegment { ident: $crate#10, hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).136), res: Err, args: None, infer_args: true }, PathSegment { ident: panicking#10, hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).137), res: Def(Mod, DefId(2:8281 ~ core[690e]::panicking)), args: None, infer_args: true }, PathSegment { ident: panic#10, hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).138), res: Def(Fn, DefId(2:8292 ~ core[690e]::panicking::panic)), args: None, infer_args: true }] })), span: /home/centri/.rustup/toolchains/nightly-2023-05-05-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/macros/mod.rs:773:9: 773:33 (#10) }, [Expr { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).139), kind: Lit(Spanned { node: Str("not yet implemented", Cooked), span: /home/centri/.rustup/toolchains/nightly-2023-05-05-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/macros/mod.rs:773:34: 773:55 (#10) }), span: /home/centri/.rustup/toolchains/nightly-2023-05-05-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/macros/mod.rs:773:34: 773:55 (#10) }]), span: /home/centri/.rustup/toolchains/nightly-2023-05-05-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/macros/mod.rs:773:9: 773:56 (#10) }]), span: $DIR/endian_bytes.rs:27:5: 27:32 (#0) }), span: $DIR/endian_bytes.rs:27:5: 27:33 (#0) }, Stmt { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).152), kind: Semi(Expr { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).141), kind: Call(Expr { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).142), kind: Path(TypeRelative(Ty { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).144), kind: Path(Resolved(None, Path { span: $DIR/endian_bytes.rs:28:5: 28:8 (#0), res: PrimTy(Int(I64)), segments: [PathSegment { ident: i64#0, hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).143), res: PrimTy(Int(I64)), args: None, infer_args: true }] })), span: $DIR/endian_bytes.rs:28:5: 28:8 (#0) }, PathSegment { ident: from_ne_bytes#0, hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).145), res: Err, args: None, infer_args: true })), span: $DIR/endian_bytes.rs:28:5: 28:23 (#0) }, [Expr { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).146), kind: Call(Expr { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).147), kind: Path(Resolved(None, Path { span: /home/centri/.rustup/toolchains/nightly-2023-05-05-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/macros/mod.rs:773:9: 773:33 (#11), res: Def(Fn, DefId(2:8292 ~ core[690e]::panicking::panic)), segments: [PathSegment { ident: $crate#11, hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).148), res: Err, args: None, infer_args: true }, PathSegment { ident: panicking#11, hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).149), res: Def(Mod, DefId(2:8281 ~ core[690e]::panicking)), args: None, infer_args: true }, PathSegment { ident: panic#11, hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).150), res: Def(Fn, DefId(2:8292 ~ core[690e]::panicking::panic)), args: None, infer_args: true }] })), span: /home/centri/.rustup/toolchains/nightly-2023-05-05-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/macros/mod.rs:773:9: 773:33 (#11) }, [Expr { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).151), kind: Lit(Spanned { node: Str("not yet implemented", Cooked), span: /home/centri/.rustup/toolchains/nightly-2023-05-05-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/macros/mod.rs:773:34: 773:55 (#11) }), span: /home/centri/.rustup/toolchains/nightly-2023-05-05-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/macros/mod.rs:773:34: 773:55 (#11) }]), span: /home/centri/.rustup/toolchains/nightly-2023-05-05-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/macros/mod.rs:773:9: 773:56 (#11) }]), span: $DIR/endian_bytes.rs:28:5: 28:32 (#0) }), span: $DIR/endian_bytes.rs:28:5: 28:33 (#0) }, Stmt { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).164), kind: Semi(Expr { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).153), kind: Call(Expr { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).154), kind: Path(TypeRelative(Ty { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).156), kind: Path(Resolved(None, Path { span: $DIR/endian_bytes.rs:29:5: 29:9 (#0), res: PrimTy(Uint(U128)), segments: [PathSegment { ident: u128#0, hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).155), res: PrimTy(Uint(U128)), args: None, infer_args: true }] })), span: $DIR/endian_bytes.rs:29:5: 29:9 (#0) }, PathSegment { ident: from_ne_bytes#0, hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).157), res: Err, args: None, infer_args: true })), span: $DIR/endian_bytes.rs:29:5: 29:24 (#0) }, [Expr { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).158), kind: Call(Expr { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).159), kind: Path(Resolved(None, Path { span: /home/centri/.rustup/toolchains/nightly-2023-05-05-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/macros/mod.rs:773:9: 773:33 (#12), res: Def(Fn, DefId(2:8292 ~ core[690e]::panicking::panic)), segments: [PathSegment { ident: $crate#12, hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).160), res: Err, args: None, infer_args: true }, PathSegment { ident: panicking#12, hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).161), res: Def(Mod, DefId(2:8281 ~ core[690e]::panicking)), args: None, infer_args: true }, PathSegment { ident: panic#12, hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).162), res: Def(Fn, DefId(2:8292 ~ core[690e]::panicking::panic)), args: None, infer_args: true }] })), span: /home/centri/.rustup/toolchains/nightly-2023-05-05-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/macros/mod.rs:773:9: 773:33 (#12) }, [Expr { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).163), kind: Lit(Spanned { node: Str("not yet implemented", Cooked), span: /home/centri/.rustup/toolchains/nightly-2023-05-05-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/macros/mod.rs:773:34: 773:55 (#12) }), span: /home/centri/.rustup/toolchains/nightly-2023-05-05-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/macros/mod.rs:773:34: 773:55 (#12) }]), span: /home/centri/.rustup/toolchains/nightly-2023-05-05-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/macros/mod.rs:773:9: 773:56 (#12) }]), span: $DIR/endian_bytes.rs:29:5: 29:33 (#0) }), span: $DIR/endian_bytes.rs:29:5: 29:34 (#0) }, Stmt { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).176), kind: Semi(Expr { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).165), kind: Call(Expr { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).166), kind: Path(TypeRelative(Ty { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).168), kind: Path(Resolved(None, Path { span: $DIR/endian_bytes.rs:30:5: 30:9 (#0), res: PrimTy(Int(I128)), segments: [PathSegment { ident: i128#0, hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).167), res: PrimTy(Int(I128)), args: None, infer_args: true }] })), span: $DIR/endian_bytes.rs:30:5: 30:9 (#0) }, PathSegment { ident: from_ne_bytes#0, hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).169), res: Err, args: None, infer_args: true })), span: $DIR/endian_bytes.rs:30:5: 30:24 (#0) }, [Expr { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).170), kind: Call(Expr { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).171), kind: Path(Resolved(None, Path { span: /home/centri/.rustup/toolchains/nightly-2023-05-05-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/macros/mod.rs:773:9: 773:33 (#13), res: Def(Fn, DefId(2:8292 ~ core[690e]::panicking::panic)), segments: [PathSegment { ident: $crate#13, hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).172), res: Err, args: None, infer_args: true }, PathSegment { ident: panicking#13, hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).173), res: Def(Mod, DefId(2:8281 ~ core[690e]::panicking)), args: None, infer_args: true }, PathSegment { ident: panic#13, hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).174), res: Def(Fn, DefId(2:8292 ~ core[690e]::panicking::panic)), args: None, infer_args: true }] })), span: /home/centri/.rustup/toolchains/nightly-2023-05-05-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/macros/mod.rs:773:9: 773:33 (#13) }, [Expr { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).175), kind: Lit(Spanned { node: Str("not yet implemented", Cooked), span: /home/centri/.rustup/toolchains/nightly-2023-05-05-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/macros/mod.rs:773:34: 773:55 (#13) }), span: /home/centri/.rustup/toolchains/nightly-2023-05-05-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/macros/mod.rs:773:34: 773:55 (#13) }]), span: /home/centri/.rustup/toolchains/nightly-2023-05-05-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/macros/mod.rs:773:9: 773:56 (#13) }]), span: $DIR/endian_bytes.rs:30:5: 30:33 (#0) }), span: $DIR/endian_bytes.rs:30:5: 30:34 (#0) }, Stmt { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).188), kind: Semi(Expr { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).177), kind: Call(Expr { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).178), kind: Path(TypeRelative(Ty { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).180), kind: Path(Resolved(None, Path { span: $DIR/endian_bytes.rs:31:5: 31:8 (#0), res: PrimTy(Float(F32)), segments: [PathSegment { ident: f32#0, hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).179), res: PrimTy(Float(F32)), args: None, infer_args: true }] })), span: $DIR/endian_bytes.rs:31:5: 31:8 (#0) }, PathSegment { ident: from_ne_bytes#0, hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).181), res: Err, args: None, infer_args: true })), span: $DIR/endian_bytes.rs:31:5: 31:23 (#0) }, [Expr { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).182), kind: Call(Expr { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).183), kind: Path(Resolved(None, Path { span: /home/centri/.rustup/toolchains/nightly-2023-05-05-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/macros/mod.rs:773:9: 773:33 (#14), res: Def(Fn, DefId(2:8292 ~ core[690e]::panicking::panic)), segments: [PathSegment { ident: $crate#14, hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).184), res: Err, args: None, infer_args: true }, PathSegment { ident: panicking#14, hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).185), res: Def(Mod, DefId(2:8281 ~ core[690e]::panicking)), args: None, infer_args: true }, PathSegment { ident: panic#14, hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).186), res: Def(Fn, DefId(2:8292 ~ core[690e]::panicking::panic)), args: None, infer_args: true }] })), span: /home/centri/.rustup/toolchains/nightly-2023-05-05-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/macros/mod.rs:773:9: 773:33 (#14) }, [Expr { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).187), kind: Lit(Spanned { node: Str("not yet implemented", Cooked), span: /home/centri/.rustup/toolchains/nightly-2023-05-05-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/macros/mod.rs:773:34: 773:55 (#14) }), span: /home/centri/.rustup/toolchains/nightly-2023-05-05-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/macros/mod.rs:773:34: 773:55 (#14) }]), span: /home/centri/.rustup/toolchains/nightly-2023-05-05-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/macros/mod.rs:773:9: 773:56 (#14) }]), span: $DIR/endian_bytes.rs:31:5: 31:32 (#0) }), span: $DIR/endian_bytes.rs:31:5: 31:33 (#0) }, Stmt { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).200), kind: Semi(Expr { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).189), kind: Call(Expr { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).190), kind: Path(TypeRelative(Ty { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).192), kind: Path(Resolved(None, Path { span: $DIR/endian_bytes.rs:32:5: 32:8 (#0), res: PrimTy(Float(F64)), segments: [PathSegment { ident: f64#0, hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).191), res: PrimTy(Float(F64)), args: None, infer_args: true }] })), span: $DIR/endian_bytes.rs:32:5: 32:8 (#0) }, PathSegment { ident: from_ne_bytes#0, hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).193), res: Err, args: None, infer_args: true })), span: $DIR/endian_bytes.rs:32:5: 32:23 (#0) }, [Expr { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).194), kind: Call(Expr { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).195), kind: Path(Resolved(None, Path { span: /home/centri/.rustup/toolchains/nightly-2023-05-05-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/macros/mod.rs:773:9: 773:33 (#15), res: Def(Fn, DefId(2:8292 ~ core[690e]::panicking::panic)), segments: [PathSegment { ident: $crate#15, hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).196), res: Err, args: None, infer_args: true }, PathSegment { ident: panicking#15, hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).197), res: Def(Mod, DefId(2:8281 ~ core[690e]::panicking)), args: None, infer_args: true }, PathSegment { ident: panic#15, hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).198), res: Def(Fn, DefId(2:8292 ~ core[690e]::panicking::panic)), args: None, infer_args: true }] })), span: /home/centri/.rustup/toolchains/nightly-2023-05-05-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/macros/mod.rs:773:9: 773:33 (#15) }, [Expr { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).199), kind: Lit(Spanned { node: Str("not yet implemented", Cooked), span: /home/centri/.rustup/toolchains/nightly-2023-05-05-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/macros/mod.rs:773:34: 773:55 (#15) }), span: /home/centri/.rustup/toolchains/nightly-2023-05-05-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/macros/mod.rs:773:34: 773:55 (#15) }]), span: /home/centri/.rustup/toolchains/nightly-2023-05-05-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/macros/mod.rs:773:9: 773:56 (#15) }]), span: $DIR/endian_bytes.rs:32:5: 32:32 (#0) }), span: $DIR/endian_bytes.rs:32:5: 32:33 (#0) }], expr: None, hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).201), rules: DefaultBlock, span: $DIR/endian_bytes.rs:6:11: 33:2 (#0), targeted_by_break: false }, None), span: $DIR/endian_bytes.rs:6:11: 33:2 (#0) } + = help: specify the desired endianness explicitly = note: `-D clippy::host-endian-bytes` implied by `-D warnings` + = note: this error originates in the macro `fn_body` (in Nightly builds, run with -Z macro-backtrace for more info) -error: use of the method `to_ne_bytes` - --> $DIR/endian_bytes.rs:7:5 +error: usage of the method `to_ne_bytes` + --> $DIR/endian_bytes.rs:8:9 | -LL | 2u8.to_ne_bytes(); - | ^^^^^^^^^^^^^^^^^ +LL | 2i8.to_ne_bytes(); + | ^^^^^^^^^^^^^^^^^ +... +LL | fn host() { fn_body!(); } + | ---------- in this macro invocation | - = help: consider specifying the desired endianness + = help: specify the desired endianness explicitly + = note: this error originates in the macro `fn_body` (in Nightly builds, run with -Z macro-backtrace for more info) -error: use of the method `from_ne_bytes` - --> $DIR/endian_bytes.rs:7:5 +error: usage of the method `to_ne_bytes` + --> $DIR/endian_bytes.rs:9:9 | -LL | 2u8.to_ne_bytes(); - | ^^^ +LL | 2u16.to_ne_bytes(); + | ^^^^^^^^^^^^^^^^^^ +... +LL | fn host() { fn_body!(); } + | ---------- in this macro invocation | - = help: consider specifying the desired endianness: Expr { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).3), kind: Lit(Spanned { node: Int(2, Unsigned(U8)), span: $DIR/endian_bytes.rs:7:5: 7:8 (#0) }), span: $DIR/endian_bytes.rs:7:5: 7:8 (#0) } + = help: specify the desired endianness explicitly + = note: this error originates in the macro `fn_body` (in Nightly builds, run with -Z macro-backtrace for more info) -error: use of the method `to_ne_bytes` - --> $DIR/endian_bytes.rs:8:5 +error: usage of the method `to_ne_bytes` + --> $DIR/endian_bytes.rs:10:9 | -LL | 2i8.to_ne_bytes(); - | ^^^^^^^^^^^^^^^^^ +LL | 2i16.to_ne_bytes(); + | ^^^^^^^^^^^^^^^^^^ +... +LL | fn host() { fn_body!(); } + | ---------- in this macro invocation | - = help: consider specifying the desired endianness + = help: specify the desired endianness explicitly + = note: this error originates in the macro `fn_body` (in Nightly builds, run with -Z macro-backtrace for more info) -error: use of the method `from_ne_bytes` - --> $DIR/endian_bytes.rs:8:5 +error: usage of the method `to_ne_bytes` + --> $DIR/endian_bytes.rs:11:9 | -LL | 2i8.to_ne_bytes(); - | ^^^ +LL | 2u32.to_ne_bytes(); + | ^^^^^^^^^^^^^^^^^^ +... +LL | fn host() { fn_body!(); } + | ---------- in this macro invocation | - = help: consider specifying the desired endianness: Expr { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).7), kind: Lit(Spanned { node: Int(2, Signed(I8)), span: $DIR/endian_bytes.rs:8:5: 8:8 (#0) }), span: $DIR/endian_bytes.rs:8:5: 8:8 (#0) } + = help: specify the desired endianness explicitly + = note: this error originates in the macro `fn_body` (in Nightly builds, run with -Z macro-backtrace for more info) -error: use of the method `to_ne_bytes` - --> $DIR/endian_bytes.rs:9:5 +error: usage of the method `to_ne_bytes` + --> $DIR/endian_bytes.rs:12:9 | -LL | 2u16.to_ne_bytes(); - | ^^^^^^^^^^^^^^^^^^ +LL | 2i32.to_ne_bytes(); + | ^^^^^^^^^^^^^^^^^^ +... +LL | fn host() { fn_body!(); } + | ---------- in this macro invocation | - = help: consider specifying the desired endianness + = help: specify the desired endianness explicitly + = note: this error originates in the macro `fn_body` (in Nightly builds, run with -Z macro-backtrace for more info) -error: use of the method `from_ne_bytes` - --> $DIR/endian_bytes.rs:9:5 +error: usage of the method `to_ne_bytes` + --> $DIR/endian_bytes.rs:13:9 | -LL | 2u16.to_ne_bytes(); - | ^^^^ +LL | 2u64.to_ne_bytes(); + | ^^^^^^^^^^^^^^^^^^ +... +LL | fn host() { fn_body!(); } + | ---------- in this macro invocation | - = help: consider specifying the desired endianness: Expr { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).11), kind: Lit(Spanned { node: Int(2, Unsigned(U16)), span: $DIR/endian_bytes.rs:9:5: 9:9 (#0) }), span: $DIR/endian_bytes.rs:9:5: 9:9 (#0) } + = help: specify the desired endianness explicitly + = note: this error originates in the macro `fn_body` (in Nightly builds, run with -Z macro-backtrace for more info) -error: use of the method `to_ne_bytes` - --> $DIR/endian_bytes.rs:10:5 +error: usage of the method `to_ne_bytes` + --> $DIR/endian_bytes.rs:14:9 | -LL | 2i16.to_ne_bytes(); - | ^^^^^^^^^^^^^^^^^^ +LL | 2i64.to_ne_bytes(); + | ^^^^^^^^^^^^^^^^^^ +... +LL | fn host() { fn_body!(); } + | ---------- in this macro invocation | - = help: consider specifying the desired endianness + = help: specify the desired endianness explicitly + = note: this error originates in the macro `fn_body` (in Nightly builds, run with -Z macro-backtrace for more info) -error: use of the method `from_ne_bytes` - --> $DIR/endian_bytes.rs:10:5 +error: usage of the method `to_ne_bytes` + --> $DIR/endian_bytes.rs:15:9 | -LL | 2i16.to_ne_bytes(); - | ^^^^ +LL | 2u128.to_ne_bytes(); + | ^^^^^^^^^^^^^^^^^^^ +... +LL | fn host() { fn_body!(); } + | ---------- in this macro invocation | - = help: consider specifying the desired endianness: Expr { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).15), kind: Lit(Spanned { node: Int(2, Signed(I16)), span: $DIR/endian_bytes.rs:10:5: 10:9 (#0) }), span: $DIR/endian_bytes.rs:10:5: 10:9 (#0) } + = help: specify the desired endianness explicitly + = note: this error originates in the macro `fn_body` (in Nightly builds, run with -Z macro-backtrace for more info) -error: use of the method `to_ne_bytes` - --> $DIR/endian_bytes.rs:11:5 +error: usage of the method `to_ne_bytes` + --> $DIR/endian_bytes.rs:16:9 | -LL | 2u32.to_ne_bytes(); - | ^^^^^^^^^^^^^^^^^^ +LL | 2i128.to_ne_bytes(); + | ^^^^^^^^^^^^^^^^^^^ +... +LL | fn host() { fn_body!(); } + | ---------- in this macro invocation | - = help: consider specifying the desired endianness + = help: specify the desired endianness explicitly + = note: this error originates in the macro `fn_body` (in Nightly builds, run with -Z macro-backtrace for more info) -error: use of the method `from_ne_bytes` - --> $DIR/endian_bytes.rs:11:5 +error: usage of the method `to_ne_bytes` + --> $DIR/endian_bytes.rs:17:9 | -LL | 2u32.to_ne_bytes(); - | ^^^^ +LL | 2.0f32.to_ne_bytes(); + | ^^^^^^^^^^^^^^^^^^^^ +... +LL | fn host() { fn_body!(); } + | ---------- in this macro invocation | - = help: consider specifying the desired endianness: Expr { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).19), kind: Lit(Spanned { node: Int(2, Unsigned(U32)), span: $DIR/endian_bytes.rs:11:5: 11:9 (#0) }), span: $DIR/endian_bytes.rs:11:5: 11:9 (#0) } + = help: specify the desired endianness explicitly + = note: this error originates in the macro `fn_body` (in Nightly builds, run with -Z macro-backtrace for more info) -error: use of the method `to_ne_bytes` - --> $DIR/endian_bytes.rs:12:5 +error: usage of the method `to_ne_bytes` + --> $DIR/endian_bytes.rs:18:9 | -LL | 2i32.to_ne_bytes(); - | ^^^^^^^^^^^^^^^^^^ +LL | 2.0f64.to_ne_bytes(); + | ^^^^^^^^^^^^^^^^^^^^ +... +LL | fn host() { fn_body!(); } + | ---------- in this macro invocation | - = help: consider specifying the desired endianness + = help: specify the desired endianness explicitly + = note: this error originates in the macro `fn_body` (in Nightly builds, run with -Z macro-backtrace for more info) -error: use of the method `from_ne_bytes` - --> $DIR/endian_bytes.rs:12:5 +error: usage of the method `to_ne_bytes` + --> $DIR/endian_bytes.rs:19:9 | -LL | 2i32.to_ne_bytes(); - | ^^^^ +LL | 2usize.to_ne_bytes(); + | ^^^^^^^^^^^^^^^^^^^^ +... +LL | fn host() { fn_body!(); } + | ---------- in this macro invocation | - = help: consider specifying the desired endianness: Expr { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).23), kind: Lit(Spanned { node: Int(2, Signed(I32)), span: $DIR/endian_bytes.rs:12:5: 12:9 (#0) }), span: $DIR/endian_bytes.rs:12:5: 12:9 (#0) } + = help: specify the desired endianness explicitly + = note: this error originates in the macro `fn_body` (in Nightly builds, run with -Z macro-backtrace for more info) -error: use of the method `to_ne_bytes` - --> $DIR/endian_bytes.rs:13:5 +error: usage of the method `to_ne_bytes` + --> $DIR/endian_bytes.rs:20:9 | -LL | 2u64.to_ne_bytes(); - | ^^^^^^^^^^^^^^^^^^ +LL | 2isize.to_ne_bytes(); + | ^^^^^^^^^^^^^^^^^^^^ +... +LL | fn host() { fn_body!(); } + | ---------- in this macro invocation | - = help: consider specifying the desired endianness + = help: specify the desired endianness explicitly + = note: this error originates in the macro `fn_body` (in Nightly builds, run with -Z macro-backtrace for more info) -error: use of the method `from_ne_bytes` - --> $DIR/endian_bytes.rs:13:5 +error: usage of the method `from_ne_bytes` + --> $DIR/endian_bytes.rs:21:9 | -LL | 2u64.to_ne_bytes(); - | ^^^^ +LL | u8::from_ne_bytes(todo!()); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ +... +LL | fn host() { fn_body!(); } + | ---------- in this macro invocation | - = help: consider specifying the desired endianness: Expr { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).27), kind: Lit(Spanned { node: Int(2, Unsigned(U64)), span: $DIR/endian_bytes.rs:13:5: 13:9 (#0) }), span: $DIR/endian_bytes.rs:13:5: 13:9 (#0) } + = help: specify the desired endianness explicitly + = note: this error originates in the macro `fn_body` (in Nightly builds, run with -Z macro-backtrace for more info) -error: use of the method `to_ne_bytes` - --> $DIR/endian_bytes.rs:14:5 +error: usage of the method `from_ne_bytes` + --> $DIR/endian_bytes.rs:22:9 | -LL | 2i64.to_ne_bytes(); - | ^^^^^^^^^^^^^^^^^^ +LL | i8::from_ne_bytes(todo!()); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ +... +LL | fn host() { fn_body!(); } + | ---------- in this macro invocation | - = help: consider specifying the desired endianness + = help: specify the desired endianness explicitly + = note: this error originates in the macro `fn_body` (in Nightly builds, run with -Z macro-backtrace for more info) -error: use of the method `from_ne_bytes` - --> $DIR/endian_bytes.rs:14:5 +error: usage of the method `from_ne_bytes` + --> $DIR/endian_bytes.rs:23:9 | -LL | 2i64.to_ne_bytes(); - | ^^^^ +LL | u16::from_ne_bytes(todo!()); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ +... +LL | fn host() { fn_body!(); } + | ---------- in this macro invocation | - = help: consider specifying the desired endianness: Expr { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).31), kind: Lit(Spanned { node: Int(2, Signed(I64)), span: $DIR/endian_bytes.rs:14:5: 14:9 (#0) }), span: $DIR/endian_bytes.rs:14:5: 14:9 (#0) } + = help: specify the desired endianness explicitly + = note: this error originates in the macro `fn_body` (in Nightly builds, run with -Z macro-backtrace for more info) -error: use of the method `to_ne_bytes` - --> $DIR/endian_bytes.rs:15:5 +error: usage of the method `from_ne_bytes` + --> $DIR/endian_bytes.rs:24:9 | -LL | 2u128.to_ne_bytes(); - | ^^^^^^^^^^^^^^^^^^^ +LL | i16::from_ne_bytes(todo!()); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ +... +LL | fn host() { fn_body!(); } + | ---------- in this macro invocation | - = help: consider specifying the desired endianness + = help: specify the desired endianness explicitly + = note: this error originates in the macro `fn_body` (in Nightly builds, run with -Z macro-backtrace for more info) -error: use of the method `from_ne_bytes` - --> $DIR/endian_bytes.rs:15:5 +error: usage of the method `from_ne_bytes` + --> $DIR/endian_bytes.rs:25:9 | -LL | 2u128.to_ne_bytes(); - | ^^^^^ +LL | u32::from_ne_bytes(todo!()); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ +... +LL | fn host() { fn_body!(); } + | ---------- in this macro invocation | - = help: consider specifying the desired endianness: Expr { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).35), kind: Lit(Spanned { node: Int(2, Unsigned(U128)), span: $DIR/endian_bytes.rs:15:5: 15:10 (#0) }), span: $DIR/endian_bytes.rs:15:5: 15:10 (#0) } + = help: specify the desired endianness explicitly + = note: this error originates in the macro `fn_body` (in Nightly builds, run with -Z macro-backtrace for more info) -error: use of the method `to_ne_bytes` - --> $DIR/endian_bytes.rs:16:5 +error: usage of the method `from_ne_bytes` + --> $DIR/endian_bytes.rs:26:9 | -LL | 2i128.to_ne_bytes(); - | ^^^^^^^^^^^^^^^^^^^ +LL | i32::from_ne_bytes(todo!()); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ +... +LL | fn host() { fn_body!(); } + | ---------- in this macro invocation | - = help: consider specifying the desired endianness + = help: specify the desired endianness explicitly + = note: this error originates in the macro `fn_body` (in Nightly builds, run with -Z macro-backtrace for more info) -error: use of the method `from_ne_bytes` - --> $DIR/endian_bytes.rs:16:5 +error: usage of the method `from_ne_bytes` + --> $DIR/endian_bytes.rs:27:9 | -LL | 2i128.to_ne_bytes(); - | ^^^^^ +LL | u64::from_ne_bytes(todo!()); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ +... +LL | fn host() { fn_body!(); } + | ---------- in this macro invocation | - = help: consider specifying the desired endianness: Expr { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).39), kind: Lit(Spanned { node: Int(2, Signed(I128)), span: $DIR/endian_bytes.rs:16:5: 16:10 (#0) }), span: $DIR/endian_bytes.rs:16:5: 16:10 (#0) } + = help: specify the desired endianness explicitly + = note: this error originates in the macro `fn_body` (in Nightly builds, run with -Z macro-backtrace for more info) -error: use of the method `to_ne_bytes` - --> $DIR/endian_bytes.rs:17:5 +error: usage of the method `from_ne_bytes` + --> $DIR/endian_bytes.rs:28:9 | -LL | 2usize.to_ne_bytes(); - | ^^^^^^^^^^^^^^^^^^^^ +LL | i64::from_ne_bytes(todo!()); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ +... +LL | fn host() { fn_body!(); } + | ---------- in this macro invocation | - = help: consider specifying the desired endianness + = help: specify the desired endianness explicitly + = note: this error originates in the macro `fn_body` (in Nightly builds, run with -Z macro-backtrace for more info) -error: use of the method `from_ne_bytes` - --> $DIR/endian_bytes.rs:17:5 +error: usage of the method `from_ne_bytes` + --> $DIR/endian_bytes.rs:29:9 | -LL | 2usize.to_ne_bytes(); - | ^^^^^^ +LL | u128::from_ne_bytes(todo!()); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +... +LL | fn host() { fn_body!(); } + | ---------- in this macro invocation | - = help: consider specifying the desired endianness: Expr { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).43), kind: Lit(Spanned { node: Int(2, Unsigned(Usize)), span: $DIR/endian_bytes.rs:17:5: 17:11 (#0) }), span: $DIR/endian_bytes.rs:17:5: 17:11 (#0) } + = help: specify the desired endianness explicitly + = note: this error originates in the macro `fn_body` (in Nightly builds, run with -Z macro-backtrace for more info) -error: use of the method `to_ne_bytes` - --> $DIR/endian_bytes.rs:18:5 +error: usage of the method `from_ne_bytes` + --> $DIR/endian_bytes.rs:30:9 | -LL | 2isize.to_ne_bytes(); - | ^^^^^^^^^^^^^^^^^^^^ +LL | i128::from_ne_bytes(todo!()); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +... +LL | fn host() { fn_body!(); } + | ---------- in this macro invocation | - = help: consider specifying the desired endianness + = help: specify the desired endianness explicitly + = note: this error originates in the macro `fn_body` (in Nightly builds, run with -Z macro-backtrace for more info) -error: use of the method `from_ne_bytes` - --> $DIR/endian_bytes.rs:18:5 +error: usage of the method `from_ne_bytes` + --> $DIR/endian_bytes.rs:31:9 | -LL | 2isize.to_ne_bytes(); - | ^^^^^^ +LL | usize::from_ne_bytes(todo!()); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +... +LL | fn host() { fn_body!(); } + | ---------- in this macro invocation | - = help: consider specifying the desired endianness: Expr { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).47), kind: Lit(Spanned { node: Int(2, Signed(Isize)), span: $DIR/endian_bytes.rs:18:5: 18:11 (#0) }), span: $DIR/endian_bytes.rs:18:5: 18:11 (#0) } + = help: specify the desired endianness explicitly + = note: this error originates in the macro `fn_body` (in Nightly builds, run with -Z macro-backtrace for more info) -error: use of the method `to_ne_bytes` - --> $DIR/endian_bytes.rs:19:5 +error: usage of the method `from_ne_bytes` + --> $DIR/endian_bytes.rs:32:9 | -LL | 2.0f32.to_ne_bytes(); - | ^^^^^^^^^^^^^^^^^^^^ +LL | isize::from_ne_bytes(todo!()); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +... +LL | fn host() { fn_body!(); } + | ---------- in this macro invocation | - = help: consider specifying the desired endianness + = help: specify the desired endianness explicitly + = note: this error originates in the macro `fn_body` (in Nightly builds, run with -Z macro-backtrace for more info) -error: use of the method `from_ne_bytes` - --> $DIR/endian_bytes.rs:19:5 +error: usage of the method `from_ne_bytes` + --> $DIR/endian_bytes.rs:33:9 | -LL | 2.0f32.to_ne_bytes(); - | ^^^^^^ +LL | f32::from_ne_bytes(todo!()); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ +... +LL | fn host() { fn_body!(); } + | ---------- in this macro invocation | - = help: consider specifying the desired endianness: Expr { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).51), kind: Lit(Spanned { node: Float("2.0", Suffixed(F32)), span: $DIR/endian_bytes.rs:19:5: 19:11 (#0) }), span: $DIR/endian_bytes.rs:19:5: 19:11 (#0) } + = help: specify the desired endianness explicitly + = note: this error originates in the macro `fn_body` (in Nightly builds, run with -Z macro-backtrace for more info) -error: use of the method `to_ne_bytes` - --> $DIR/endian_bytes.rs:20:5 +error: usage of the method `from_ne_bytes` + --> $DIR/endian_bytes.rs:34:9 | -LL | 2.0f64.to_ne_bytes(); - | ^^^^^^^^^^^^^^^^^^^^ +LL | f64::from_ne_bytes(todo!()); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ +... +LL | fn host() { fn_body!(); } + | ---------- in this macro invocation | - = help: consider specifying the desired endianness + = help: specify the desired endianness explicitly + = note: this error originates in the macro `fn_body` (in Nightly builds, run with -Z macro-backtrace for more info) -error: use of the method `from_ne_bytes` - --> $DIR/endian_bytes.rs:20:5 +error: usage of the method `to_le_bytes` + --> $DIR/endian_bytes.rs:36:9 | -LL | 2.0f64.to_ne_bytes(); - | ^^^^^^ +LL | 2u8.to_le_bytes(); + | ^^^^^^^^^^^^^^^^^ +... +LL | fn little() { fn_body!(); } + | ---------- in this macro invocation | - = help: consider specifying the desired endianness: Expr { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).55), kind: Lit(Spanned { node: Float("2.0", Suffixed(F64)), span: $DIR/endian_bytes.rs:20:5: 20:11 (#0) }), span: $DIR/endian_bytes.rs:20:5: 20:11 (#0) } - -error: use of the method `from_ne_bytes` - --> $DIR/endian_bytes.rs:21:5 - | -LL | u8::from_ne_bytes(todo!()); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = help: consider specifying the desired endianness: Expr { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).57), kind: Call(Expr { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).58), kind: Path(TypeRelative(Ty { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).60), kind: Path(Resolved(None, Path { span: $DIR/endian_bytes.rs:21:5: 21:7 (#0), res: PrimTy(Uint(U8)), segments: [PathSegment { ident: u8#0, hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).59), res: PrimTy(Uint(U8)), args: None, infer_args: true }] })), span: $DIR/endian_bytes.rs:21:5: 21:7 (#0) }, PathSegment { ident: from_ne_bytes#0, hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).61), res: Err, args: None, infer_args: true })), span: $DIR/endian_bytes.rs:21:5: 21:22 (#0) }, [Expr { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).62), kind: Call(Expr { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).63), kind: Path(Resolved(None, Path { span: /home/centri/.rustup/toolchains/nightly-2023-05-05-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/macros/mod.rs:773:9: 773:33 (#4), res: Def(Fn, DefId(2:8292 ~ core[690e]::panicking::panic)), segments: [PathSegment { ident: $crate#4, hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).64), res: Err, args: None, infer_args: true }, PathSegment { ident: panicking#4, hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).65), res: Def(Mod, DefId(2:8281 ~ core[690e]::panicking)), args: None, infer_args: true }, PathSegment { ident: panic#4, hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).66), res: Def(Fn, DefId(2:8292 ~ core[690e]::panicking::panic)), args: None, infer_args: true }] })), span: /home/centri/.rustup/toolchains/nightly-2023-05-05-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/macros/mod.rs:773:9: 773:33 (#4) }, [Expr { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).67), kind: Lit(Spanned { node: Str("not yet implemented", Cooked), span: /home/centri/.rustup/toolchains/nightly-2023-05-05-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/macros/mod.rs:773:34: 773:55 (#4) }), span: /home/centri/.rustup/toolchains/nightly-2023-05-05-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/macros/mod.rs:773:34: 773:55 (#4) }]), span: /home/centri/.rustup/toolchains/nightly-2023-05-05-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/macros/mod.rs:773:9: 773:56 (#4) }]), span: $DIR/endian_bytes.rs:21:5: 21:31 (#0) } - -error: use of the method `from_ne_bytes` - --> $DIR/endian_bytes.rs:21:5 - | -LL | u8::from_ne_bytes(todo!()); - | ^^^^^^^^^^^^^^^^^ - | - = help: consider specifying the desired endianness: Expr { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).58), kind: Path(TypeRelative(Ty { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).60), kind: Path(Resolved(None, Path { span: $DIR/endian_bytes.rs:21:5: 21:7 (#0), res: PrimTy(Uint(U8)), segments: [PathSegment { ident: u8#0, hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).59), res: PrimTy(Uint(U8)), args: None, infer_args: true }] })), span: $DIR/endian_bytes.rs:21:5: 21:7 (#0) }, PathSegment { ident: from_ne_bytes#0, hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).61), res: Err, args: None, infer_args: true })), span: $DIR/endian_bytes.rs:21:5: 21:22 (#0) } - -error: use of the method `from_ne_bytes` - --> $DIR/endian_bytes.rs:21:23 - | -LL | u8::from_ne_bytes(todo!()); - | ^^^^^^^ - | - = help: consider specifying the desired endianness: Expr { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).62), kind: Call(Expr { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).63), kind: Path(Resolved(None, Path { span: /home/centri/.rustup/toolchains/nightly-2023-05-05-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/macros/mod.rs:773:9: 773:33 (#4), res: Def(Fn, DefId(2:8292 ~ core[690e]::panicking::panic)), segments: [PathSegment { ident: $crate#4, hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).64), res: Err, args: None, infer_args: true }, PathSegment { ident: panicking#4, hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).65), res: Def(Mod, DefId(2:8281 ~ core[690e]::panicking)), args: None, infer_args: true }, PathSegment { ident: panic#4, hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).66), res: Def(Fn, DefId(2:8292 ~ core[690e]::panicking::panic)), args: None, infer_args: true }] })), span: /home/centri/.rustup/toolchains/nightly-2023-05-05-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/macros/mod.rs:773:9: 773:33 (#4) }, [Expr { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).67), kind: Lit(Spanned { node: Str("not yet implemented", Cooked), span: /home/centri/.rustup/toolchains/nightly-2023-05-05-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/macros/mod.rs:773:34: 773:55 (#4) }), span: /home/centri/.rustup/toolchains/nightly-2023-05-05-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/macros/mod.rs:773:34: 773:55 (#4) }]), span: /home/centri/.rustup/toolchains/nightly-2023-05-05-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/macros/mod.rs:773:9: 773:56 (#4) } - = note: this error originates in the macro `todo` (in Nightly builds, run with -Z macro-backtrace for more info) - -error: use of the method `from_ne_bytes` - --> $DIR/endian_bytes.rs:21:23 - | -LL | u8::from_ne_bytes(todo!()); - | ^^^^^^^ - | - = help: consider specifying the desired endianness: Expr { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).63), kind: Path(Resolved(None, Path { span: /home/centri/.rustup/toolchains/nightly-2023-05-05-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/macros/mod.rs:773:9: 773:33 (#4), res: Def(Fn, DefId(2:8292 ~ core[690e]::panicking::panic)), segments: [PathSegment { ident: $crate#4, hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).64), res: Err, args: None, infer_args: true }, PathSegment { ident: panicking#4, hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).65), res: Def(Mod, DefId(2:8281 ~ core[690e]::panicking)), args: None, infer_args: true }, PathSegment { ident: panic#4, hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).66), res: Def(Fn, DefId(2:8292 ~ core[690e]::panicking::panic)), args: None, infer_args: true }] })), span: /home/centri/.rustup/toolchains/nightly-2023-05-05-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/macros/mod.rs:773:9: 773:33 (#4) } - = note: this error originates in the macro `todo` (in Nightly builds, run with -Z macro-backtrace for more info) - -error: use of the method `from_ne_bytes` - --> $DIR/endian_bytes.rs:21:23 - | -LL | u8::from_ne_bytes(todo!()); - | ^^^^^^^ - | - = help: consider specifying the desired endianness: Expr { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).67), kind: Lit(Spanned { node: Str("not yet implemented", Cooked), span: /home/centri/.rustup/toolchains/nightly-2023-05-05-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/macros/mod.rs:773:34: 773:55 (#4) }), span: /home/centri/.rustup/toolchains/nightly-2023-05-05-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/macros/mod.rs:773:34: 773:55 (#4) } - = note: this error originates in the macro `todo` (in Nightly builds, run with -Z macro-backtrace for more info) - -error: use of the method `from_ne_bytes` - --> $DIR/endian_bytes.rs:22:5 - | -LL | i8::from_ne_bytes(todo!()); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = help: consider specifying the desired endianness: Expr { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).69), kind: Call(Expr { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).70), kind: Path(TypeRelative(Ty { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).72), kind: Path(Resolved(None, Path { span: $DIR/endian_bytes.rs:22:5: 22:7 (#0), res: PrimTy(Int(I8)), segments: [PathSegment { ident: i8#0, hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).71), res: PrimTy(Int(I8)), args: None, infer_args: true }] })), span: $DIR/endian_bytes.rs:22:5: 22:7 (#0) }, PathSegment { ident: from_ne_bytes#0, hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).73), res: Err, args: None, infer_args: true })), span: $DIR/endian_bytes.rs:22:5: 22:22 (#0) }, [Expr { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).74), kind: Call(Expr { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).75), kind: Path(Resolved(None, Path { span: /home/centri/.rustup/toolchains/nightly-2023-05-05-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/macros/mod.rs:773:9: 773:33 (#5), res: Def(Fn, DefId(2:8292 ~ core[690e]::panicking::panic)), segments: [PathSegment { ident: $crate#5, hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).76), res: Err, args: None, infer_args: true }, PathSegment { ident: panicking#5, hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).77), res: Def(Mod, DefId(2:8281 ~ core[690e]::panicking)), args: None, infer_args: true }, PathSegment { ident: panic#5, hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).78), res: Def(Fn, DefId(2:8292 ~ core[690e]::panicking::panic)), args: None, infer_args: true }] })), span: /home/centri/.rustup/toolchains/nightly-2023-05-05-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/macros/mod.rs:773:9: 773:33 (#5) }, [Expr { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).79), kind: Lit(Spanned { node: Str("not yet implemented", Cooked), span: /home/centri/.rustup/toolchains/nightly-2023-05-05-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/macros/mod.rs:773:34: 773:55 (#5) }), span: /home/centri/.rustup/toolchains/nightly-2023-05-05-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/macros/mod.rs:773:34: 773:55 (#5) }]), span: /home/centri/.rustup/toolchains/nightly-2023-05-05-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/macros/mod.rs:773:9: 773:56 (#5) }]), span: $DIR/endian_bytes.rs:22:5: 22:31 (#0) } - -error: use of the method `from_ne_bytes` - --> $DIR/endian_bytes.rs:22:5 - | -LL | i8::from_ne_bytes(todo!()); - | ^^^^^^^^^^^^^^^^^ - | - = help: consider specifying the desired endianness: Expr { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).70), kind: Path(TypeRelative(Ty { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).72), kind: Path(Resolved(None, Path { span: $DIR/endian_bytes.rs:22:5: 22:7 (#0), res: PrimTy(Int(I8)), segments: [PathSegment { ident: i8#0, hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).71), res: PrimTy(Int(I8)), args: None, infer_args: true }] })), span: $DIR/endian_bytes.rs:22:5: 22:7 (#0) }, PathSegment { ident: from_ne_bytes#0, hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).73), res: Err, args: None, infer_args: true })), span: $DIR/endian_bytes.rs:22:5: 22:22 (#0) } - -error: use of the method `from_ne_bytes` - --> $DIR/endian_bytes.rs:22:23 - | -LL | i8::from_ne_bytes(todo!()); - | ^^^^^^^ - | - = help: consider specifying the desired endianness: Expr { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).74), kind: Call(Expr { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).75), kind: Path(Resolved(None, Path { span: /home/centri/.rustup/toolchains/nightly-2023-05-05-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/macros/mod.rs:773:9: 773:33 (#5), res: Def(Fn, DefId(2:8292 ~ core[690e]::panicking::panic)), segments: [PathSegment { ident: $crate#5, hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).76), res: Err, args: None, infer_args: true }, PathSegment { ident: panicking#5, hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).77), res: Def(Mod, DefId(2:8281 ~ core[690e]::panicking)), args: None, infer_args: true }, PathSegment { ident: panic#5, hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).78), res: Def(Fn, DefId(2:8292 ~ core[690e]::panicking::panic)), args: None, infer_args: true }] })), span: /home/centri/.rustup/toolchains/nightly-2023-05-05-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/macros/mod.rs:773:9: 773:33 (#5) }, [Expr { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).79), kind: Lit(Spanned { node: Str("not yet implemented", Cooked), span: /home/centri/.rustup/toolchains/nightly-2023-05-05-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/macros/mod.rs:773:34: 773:55 (#5) }), span: /home/centri/.rustup/toolchains/nightly-2023-05-05-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/macros/mod.rs:773:34: 773:55 (#5) }]), span: /home/centri/.rustup/toolchains/nightly-2023-05-05-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/macros/mod.rs:773:9: 773:56 (#5) } - = note: this error originates in the macro `todo` (in Nightly builds, run with -Z macro-backtrace for more info) - -error: use of the method `from_ne_bytes` - --> $DIR/endian_bytes.rs:22:23 - | -LL | i8::from_ne_bytes(todo!()); - | ^^^^^^^ - | - = help: consider specifying the desired endianness: Expr { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).75), kind: Path(Resolved(None, Path { span: /home/centri/.rustup/toolchains/nightly-2023-05-05-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/macros/mod.rs:773:9: 773:33 (#5), res: Def(Fn, DefId(2:8292 ~ core[690e]::panicking::panic)), segments: [PathSegment { ident: $crate#5, hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).76), res: Err, args: None, infer_args: true }, PathSegment { ident: panicking#5, hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).77), res: Def(Mod, DefId(2:8281 ~ core[690e]::panicking)), args: None, infer_args: true }, PathSegment { ident: panic#5, hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).78), res: Def(Fn, DefId(2:8292 ~ core[690e]::panicking::panic)), args: None, infer_args: true }] })), span: /home/centri/.rustup/toolchains/nightly-2023-05-05-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/macros/mod.rs:773:9: 773:33 (#5) } - = note: this error originates in the macro `todo` (in Nightly builds, run with -Z macro-backtrace for more info) - -error: use of the method `from_ne_bytes` - --> $DIR/endian_bytes.rs:22:23 - | -LL | i8::from_ne_bytes(todo!()); - | ^^^^^^^ - | - = help: consider specifying the desired endianness: Expr { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).79), kind: Lit(Spanned { node: Str("not yet implemented", Cooked), span: /home/centri/.rustup/toolchains/nightly-2023-05-05-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/macros/mod.rs:773:34: 773:55 (#5) }), span: /home/centri/.rustup/toolchains/nightly-2023-05-05-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/macros/mod.rs:773:34: 773:55 (#5) } - = note: this error originates in the macro `todo` (in Nightly builds, run with -Z macro-backtrace for more info) - -error: use of the method `from_ne_bytes` - --> $DIR/endian_bytes.rs:23:5 - | -LL | u16::from_ne_bytes(todo!()); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = help: consider specifying the desired endianness: Expr { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).81), kind: Call(Expr { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).82), kind: Path(TypeRelative(Ty { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).84), kind: Path(Resolved(None, Path { span: $DIR/endian_bytes.rs:23:5: 23:8 (#0), res: PrimTy(Uint(U16)), segments: [PathSegment { ident: u16#0, hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).83), res: PrimTy(Uint(U16)), args: None, infer_args: true }] })), span: $DIR/endian_bytes.rs:23:5: 23:8 (#0) }, PathSegment { ident: from_ne_bytes#0, hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).85), res: Err, args: None, infer_args: true })), span: $DIR/endian_bytes.rs:23:5: 23:23 (#0) }, [Expr { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).86), kind: Call(Expr { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).87), kind: Path(Resolved(None, Path { span: /home/centri/.rustup/toolchains/nightly-2023-05-05-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/macros/mod.rs:773:9: 773:33 (#6), res: Def(Fn, DefId(2:8292 ~ core[690e]::panicking::panic)), segments: [PathSegment { ident: $crate#6, hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).88), res: Err, args: None, infer_args: true }, PathSegment { ident: panicking#6, hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).89), res: Def(Mod, DefId(2:8281 ~ core[690e]::panicking)), args: None, infer_args: true }, PathSegment { ident: panic#6, hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).90), res: Def(Fn, DefId(2:8292 ~ core[690e]::panicking::panic)), args: None, infer_args: true }] })), span: /home/centri/.rustup/toolchains/nightly-2023-05-05-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/macros/mod.rs:773:9: 773:33 (#6) }, [Expr { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).91), kind: Lit(Spanned { node: Str("not yet implemented", Cooked), span: /home/centri/.rustup/toolchains/nightly-2023-05-05-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/macros/mod.rs:773:34: 773:55 (#6) }), span: /home/centri/.rustup/toolchains/nightly-2023-05-05-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/macros/mod.rs:773:34: 773:55 (#6) }]), span: /home/centri/.rustup/toolchains/nightly-2023-05-05-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/macros/mod.rs:773:9: 773:56 (#6) }]), span: $DIR/endian_bytes.rs:23:5: 23:32 (#0) } - -error: use of the method `from_ne_bytes` - --> $DIR/endian_bytes.rs:23:5 - | -LL | u16::from_ne_bytes(todo!()); - | ^^^^^^^^^^^^^^^^^^ - | - = help: consider specifying the desired endianness: Expr { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).82), kind: Path(TypeRelative(Ty { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).84), kind: Path(Resolved(None, Path { span: $DIR/endian_bytes.rs:23:5: 23:8 (#0), res: PrimTy(Uint(U16)), segments: [PathSegment { ident: u16#0, hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).83), res: PrimTy(Uint(U16)), args: None, infer_args: true }] })), span: $DIR/endian_bytes.rs:23:5: 23:8 (#0) }, PathSegment { ident: from_ne_bytes#0, hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).85), res: Err, args: None, infer_args: true })), span: $DIR/endian_bytes.rs:23:5: 23:23 (#0) } - -error: use of the method `from_ne_bytes` - --> $DIR/endian_bytes.rs:23:24 - | -LL | u16::from_ne_bytes(todo!()); - | ^^^^^^^ - | - = help: consider specifying the desired endianness: Expr { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).86), kind: Call(Expr { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).87), kind: Path(Resolved(None, Path { span: /home/centri/.rustup/toolchains/nightly-2023-05-05-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/macros/mod.rs:773:9: 773:33 (#6), res: Def(Fn, DefId(2:8292 ~ core[690e]::panicking::panic)), segments: [PathSegment { ident: $crate#6, hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).88), res: Err, args: None, infer_args: true }, PathSegment { ident: panicking#6, hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).89), res: Def(Mod, DefId(2:8281 ~ core[690e]::panicking)), args: None, infer_args: true }, PathSegment { ident: panic#6, hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).90), res: Def(Fn, DefId(2:8292 ~ core[690e]::panicking::panic)), args: None, infer_args: true }] })), span: /home/centri/.rustup/toolchains/nightly-2023-05-05-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/macros/mod.rs:773:9: 773:33 (#6) }, [Expr { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).91), kind: Lit(Spanned { node: Str("not yet implemented", Cooked), span: /home/centri/.rustup/toolchains/nightly-2023-05-05-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/macros/mod.rs:773:34: 773:55 (#6) }), span: /home/centri/.rustup/toolchains/nightly-2023-05-05-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/macros/mod.rs:773:34: 773:55 (#6) }]), span: /home/centri/.rustup/toolchains/nightly-2023-05-05-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/macros/mod.rs:773:9: 773:56 (#6) } - = note: this error originates in the macro `todo` (in Nightly builds, run with -Z macro-backtrace for more info) - -error: use of the method `from_ne_bytes` - --> $DIR/endian_bytes.rs:23:24 - | -LL | u16::from_ne_bytes(todo!()); - | ^^^^^^^ - | - = help: consider specifying the desired endianness: Expr { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).87), kind: Path(Resolved(None, Path { span: /home/centri/.rustup/toolchains/nightly-2023-05-05-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/macros/mod.rs:773:9: 773:33 (#6), res: Def(Fn, DefId(2:8292 ~ core[690e]::panicking::panic)), segments: [PathSegment { ident: $crate#6, hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).88), res: Err, args: None, infer_args: true }, PathSegment { ident: panicking#6, hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).89), res: Def(Mod, DefId(2:8281 ~ core[690e]::panicking)), args: None, infer_args: true }, PathSegment { ident: panic#6, hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).90), res: Def(Fn, DefId(2:8292 ~ core[690e]::panicking::panic)), args: None, infer_args: true }] })), span: /home/centri/.rustup/toolchains/nightly-2023-05-05-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/macros/mod.rs:773:9: 773:33 (#6) } - = note: this error originates in the macro `todo` (in Nightly builds, run with -Z macro-backtrace for more info) - -error: use of the method `from_ne_bytes` - --> $DIR/endian_bytes.rs:23:24 - | -LL | u16::from_ne_bytes(todo!()); - | ^^^^^^^ - | - = help: consider specifying the desired endianness: Expr { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).91), kind: Lit(Spanned { node: Str("not yet implemented", Cooked), span: /home/centri/.rustup/toolchains/nightly-2023-05-05-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/macros/mod.rs:773:34: 773:55 (#6) }), span: /home/centri/.rustup/toolchains/nightly-2023-05-05-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/macros/mod.rs:773:34: 773:55 (#6) } - = note: this error originates in the macro `todo` (in Nightly builds, run with -Z macro-backtrace for more info) - -error: use of the method `from_ne_bytes` - --> $DIR/endian_bytes.rs:24:5 - | -LL | i16::from_ne_bytes(todo!()); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = help: consider specifying the desired endianness: Expr { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).93), kind: Call(Expr { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).94), kind: Path(TypeRelative(Ty { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).96), kind: Path(Resolved(None, Path { span: $DIR/endian_bytes.rs:24:5: 24:8 (#0), res: PrimTy(Int(I16)), segments: [PathSegment { ident: i16#0, hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).95), res: PrimTy(Int(I16)), args: None, infer_args: true }] })), span: $DIR/endian_bytes.rs:24:5: 24:8 (#0) }, PathSegment { ident: from_ne_bytes#0, hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).97), res: Err, args: None, infer_args: true })), span: $DIR/endian_bytes.rs:24:5: 24:23 (#0) }, [Expr { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).98), kind: Call(Expr { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).99), kind: Path(Resolved(None, Path { span: /home/centri/.rustup/toolchains/nightly-2023-05-05-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/macros/mod.rs:773:9: 773:33 (#7), res: Def(Fn, DefId(2:8292 ~ core[690e]::panicking::panic)), segments: [PathSegment { ident: $crate#7, hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).100), res: Err, args: None, infer_args: true }, PathSegment { ident: panicking#7, hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).101), res: Def(Mod, DefId(2:8281 ~ core[690e]::panicking)), args: None, infer_args: true }, PathSegment { ident: panic#7, hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).102), res: Def(Fn, DefId(2:8292 ~ core[690e]::panicking::panic)), args: None, infer_args: true }] })), span: /home/centri/.rustup/toolchains/nightly-2023-05-05-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/macros/mod.rs:773:9: 773:33 (#7) }, [Expr { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).103), kind: Lit(Spanned { node: Str("not yet implemented", Cooked), span: /home/centri/.rustup/toolchains/nightly-2023-05-05-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/macros/mod.rs:773:34: 773:55 (#7) }), span: /home/centri/.rustup/toolchains/nightly-2023-05-05-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/macros/mod.rs:773:34: 773:55 (#7) }]), span: /home/centri/.rustup/toolchains/nightly-2023-05-05-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/macros/mod.rs:773:9: 773:56 (#7) }]), span: $DIR/endian_bytes.rs:24:5: 24:32 (#0) } - -error: use of the method `from_ne_bytes` - --> $DIR/endian_bytes.rs:24:5 - | -LL | i16::from_ne_bytes(todo!()); - | ^^^^^^^^^^^^^^^^^^ - | - = help: consider specifying the desired endianness: Expr { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).94), kind: Path(TypeRelative(Ty { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).96), kind: Path(Resolved(None, Path { span: $DIR/endian_bytes.rs:24:5: 24:8 (#0), res: PrimTy(Int(I16)), segments: [PathSegment { ident: i16#0, hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).95), res: PrimTy(Int(I16)), args: None, infer_args: true }] })), span: $DIR/endian_bytes.rs:24:5: 24:8 (#0) }, PathSegment { ident: from_ne_bytes#0, hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).97), res: Err, args: None, infer_args: true })), span: $DIR/endian_bytes.rs:24:5: 24:23 (#0) } - -error: use of the method `from_ne_bytes` - --> $DIR/endian_bytes.rs:24:24 - | -LL | i16::from_ne_bytes(todo!()); - | ^^^^^^^ - | - = help: consider specifying the desired endianness: Expr { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).98), kind: Call(Expr { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).99), kind: Path(Resolved(None, Path { span: /home/centri/.rustup/toolchains/nightly-2023-05-05-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/macros/mod.rs:773:9: 773:33 (#7), res: Def(Fn, DefId(2:8292 ~ core[690e]::panicking::panic)), segments: [PathSegment { ident: $crate#7, hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).100), res: Err, args: None, infer_args: true }, PathSegment { ident: panicking#7, hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).101), res: Def(Mod, DefId(2:8281 ~ core[690e]::panicking)), args: None, infer_args: true }, PathSegment { ident: panic#7, hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).102), res: Def(Fn, DefId(2:8292 ~ core[690e]::panicking::panic)), args: None, infer_args: true }] })), span: /home/centri/.rustup/toolchains/nightly-2023-05-05-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/macros/mod.rs:773:9: 773:33 (#7) }, [Expr { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).103), kind: Lit(Spanned { node: Str("not yet implemented", Cooked), span: /home/centri/.rustup/toolchains/nightly-2023-05-05-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/macros/mod.rs:773:34: 773:55 (#7) }), span: /home/centri/.rustup/toolchains/nightly-2023-05-05-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/macros/mod.rs:773:34: 773:55 (#7) }]), span: /home/centri/.rustup/toolchains/nightly-2023-05-05-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/macros/mod.rs:773:9: 773:56 (#7) } - = note: this error originates in the macro `todo` (in Nightly builds, run with -Z macro-backtrace for more info) - -error: use of the method `from_ne_bytes` - --> $DIR/endian_bytes.rs:24:24 - | -LL | i16::from_ne_bytes(todo!()); - | ^^^^^^^ - | - = help: consider specifying the desired endianness: Expr { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).99), kind: Path(Resolved(None, Path { span: /home/centri/.rustup/toolchains/nightly-2023-05-05-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/macros/mod.rs:773:9: 773:33 (#7), res: Def(Fn, DefId(2:8292 ~ core[690e]::panicking::panic)), segments: [PathSegment { ident: $crate#7, hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).100), res: Err, args: None, infer_args: true }, PathSegment { ident: panicking#7, hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).101), res: Def(Mod, DefId(2:8281 ~ core[690e]::panicking)), args: None, infer_args: true }, PathSegment { ident: panic#7, hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).102), res: Def(Fn, DefId(2:8292 ~ core[690e]::panicking::panic)), args: None, infer_args: true }] })), span: /home/centri/.rustup/toolchains/nightly-2023-05-05-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/macros/mod.rs:773:9: 773:33 (#7) } - = note: this error originates in the macro `todo` (in Nightly builds, run with -Z macro-backtrace for more info) - -error: use of the method `from_ne_bytes` - --> $DIR/endian_bytes.rs:24:24 - | -LL | i16::from_ne_bytes(todo!()); - | ^^^^^^^ - | - = help: consider specifying the desired endianness: Expr { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).103), kind: Lit(Spanned { node: Str("not yet implemented", Cooked), span: /home/centri/.rustup/toolchains/nightly-2023-05-05-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/macros/mod.rs:773:34: 773:55 (#7) }), span: /home/centri/.rustup/toolchains/nightly-2023-05-05-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/macros/mod.rs:773:34: 773:55 (#7) } - = note: this error originates in the macro `todo` (in Nightly builds, run with -Z macro-backtrace for more info) - -error: use of the method `from_ne_bytes` - --> $DIR/endian_bytes.rs:25:5 - | -LL | u32::from_ne_bytes(todo!()); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = help: consider specifying the desired endianness: Expr { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).105), kind: Call(Expr { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).106), kind: Path(TypeRelative(Ty { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).108), kind: Path(Resolved(None, Path { span: $DIR/endian_bytes.rs:25:5: 25:8 (#0), res: PrimTy(Uint(U32)), segments: [PathSegment { ident: u32#0, hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).107), res: PrimTy(Uint(U32)), args: None, infer_args: true }] })), span: $DIR/endian_bytes.rs:25:5: 25:8 (#0) }, PathSegment { ident: from_ne_bytes#0, hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).109), res: Err, args: None, infer_args: true })), span: $DIR/endian_bytes.rs:25:5: 25:23 (#0) }, [Expr { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).110), kind: Call(Expr { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).111), kind: Path(Resolved(None, Path { span: /home/centri/.rustup/toolchains/nightly-2023-05-05-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/macros/mod.rs:773:9: 773:33 (#8), res: Def(Fn, DefId(2:8292 ~ core[690e]::panicking::panic)), segments: [PathSegment { ident: $crate#8, hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).112), res: Err, args: None, infer_args: true }, PathSegment { ident: panicking#8, hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).113), res: Def(Mod, DefId(2:8281 ~ core[690e]::panicking)), args: None, infer_args: true }, PathSegment { ident: panic#8, hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).114), res: Def(Fn, DefId(2:8292 ~ core[690e]::panicking::panic)), args: None, infer_args: true }] })), span: /home/centri/.rustup/toolchains/nightly-2023-05-05-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/macros/mod.rs:773:9: 773:33 (#8) }, [Expr { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).115), kind: Lit(Spanned { node: Str("not yet implemented", Cooked), span: /home/centri/.rustup/toolchains/nightly-2023-05-05-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/macros/mod.rs:773:34: 773:55 (#8) }), span: /home/centri/.rustup/toolchains/nightly-2023-05-05-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/macros/mod.rs:773:34: 773:55 (#8) }]), span: /home/centri/.rustup/toolchains/nightly-2023-05-05-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/macros/mod.rs:773:9: 773:56 (#8) }]), span: $DIR/endian_bytes.rs:25:5: 25:32 (#0) } - -error: use of the method `from_ne_bytes` - --> $DIR/endian_bytes.rs:25:5 - | -LL | u32::from_ne_bytes(todo!()); - | ^^^^^^^^^^^^^^^^^^ - | - = help: consider specifying the desired endianness: Expr { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).106), kind: Path(TypeRelative(Ty { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).108), kind: Path(Resolved(None, Path { span: $DIR/endian_bytes.rs:25:5: 25:8 (#0), res: PrimTy(Uint(U32)), segments: [PathSegment { ident: u32#0, hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).107), res: PrimTy(Uint(U32)), args: None, infer_args: true }] })), span: $DIR/endian_bytes.rs:25:5: 25:8 (#0) }, PathSegment { ident: from_ne_bytes#0, hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).109), res: Err, args: None, infer_args: true })), span: $DIR/endian_bytes.rs:25:5: 25:23 (#0) } - -error: use of the method `from_ne_bytes` - --> $DIR/endian_bytes.rs:25:24 - | -LL | u32::from_ne_bytes(todo!()); - | ^^^^^^^ - | - = help: consider specifying the desired endianness: Expr { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).110), kind: Call(Expr { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).111), kind: Path(Resolved(None, Path { span: /home/centri/.rustup/toolchains/nightly-2023-05-05-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/macros/mod.rs:773:9: 773:33 (#8), res: Def(Fn, DefId(2:8292 ~ core[690e]::panicking::panic)), segments: [PathSegment { ident: $crate#8, hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).112), res: Err, args: None, infer_args: true }, PathSegment { ident: panicking#8, hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).113), res: Def(Mod, DefId(2:8281 ~ core[690e]::panicking)), args: None, infer_args: true }, PathSegment { ident: panic#8, hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).114), res: Def(Fn, DefId(2:8292 ~ core[690e]::panicking::panic)), args: None, infer_args: true }] })), span: /home/centri/.rustup/toolchains/nightly-2023-05-05-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/macros/mod.rs:773:9: 773:33 (#8) }, [Expr { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).115), kind: Lit(Spanned { node: Str("not yet implemented", Cooked), span: /home/centri/.rustup/toolchains/nightly-2023-05-05-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/macros/mod.rs:773:34: 773:55 (#8) }), span: /home/centri/.rustup/toolchains/nightly-2023-05-05-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/macros/mod.rs:773:34: 773:55 (#8) }]), span: /home/centri/.rustup/toolchains/nightly-2023-05-05-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/macros/mod.rs:773:9: 773:56 (#8) } - = note: this error originates in the macro `todo` (in Nightly builds, run with -Z macro-backtrace for more info) - -error: use of the method `from_ne_bytes` - --> $DIR/endian_bytes.rs:25:24 - | -LL | u32::from_ne_bytes(todo!()); - | ^^^^^^^ - | - = help: consider specifying the desired endianness: Expr { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).111), kind: Path(Resolved(None, Path { span: /home/centri/.rustup/toolchains/nightly-2023-05-05-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/macros/mod.rs:773:9: 773:33 (#8), res: Def(Fn, DefId(2:8292 ~ core[690e]::panicking::panic)), segments: [PathSegment { ident: $crate#8, hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).112), res: Err, args: None, infer_args: true }, PathSegment { ident: panicking#8, hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).113), res: Def(Mod, DefId(2:8281 ~ core[690e]::panicking)), args: None, infer_args: true }, PathSegment { ident: panic#8, hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).114), res: Def(Fn, DefId(2:8292 ~ core[690e]::panicking::panic)), args: None, infer_args: true }] })), span: /home/centri/.rustup/toolchains/nightly-2023-05-05-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/macros/mod.rs:773:9: 773:33 (#8) } - = note: this error originates in the macro `todo` (in Nightly builds, run with -Z macro-backtrace for more info) - -error: use of the method `from_ne_bytes` - --> $DIR/endian_bytes.rs:25:24 - | -LL | u32::from_ne_bytes(todo!()); - | ^^^^^^^ - | - = help: consider specifying the desired endianness: Expr { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).115), kind: Lit(Spanned { node: Str("not yet implemented", Cooked), span: /home/centri/.rustup/toolchains/nightly-2023-05-05-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/macros/mod.rs:773:34: 773:55 (#8) }), span: /home/centri/.rustup/toolchains/nightly-2023-05-05-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/macros/mod.rs:773:34: 773:55 (#8) } - = note: this error originates in the macro `todo` (in Nightly builds, run with -Z macro-backtrace for more info) - -error: use of the method `from_ne_bytes` - --> $DIR/endian_bytes.rs:26:5 - | -LL | i32::from_ne_bytes(todo!()); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = help: consider specifying the desired endianness: Expr { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).117), kind: Call(Expr { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).118), kind: Path(TypeRelative(Ty { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).120), kind: Path(Resolved(None, Path { span: $DIR/endian_bytes.rs:26:5: 26:8 (#0), res: PrimTy(Int(I32)), segments: [PathSegment { ident: i32#0, hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).119), res: PrimTy(Int(I32)), args: None, infer_args: true }] })), span: $DIR/endian_bytes.rs:26:5: 26:8 (#0) }, PathSegment { ident: from_ne_bytes#0, hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).121), res: Err, args: None, infer_args: true })), span: $DIR/endian_bytes.rs:26:5: 26:23 (#0) }, [Expr { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).122), kind: Call(Expr { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).123), kind: Path(Resolved(None, Path { span: /home/centri/.rustup/toolchains/nightly-2023-05-05-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/macros/mod.rs:773:9: 773:33 (#9), res: Def(Fn, DefId(2:8292 ~ core[690e]::panicking::panic)), segments: [PathSegment { ident: $crate#9, hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).124), res: Err, args: None, infer_args: true }, PathSegment { ident: panicking#9, hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).125), res: Def(Mod, DefId(2:8281 ~ core[690e]::panicking)), args: None, infer_args: true }, PathSegment { ident: panic#9, hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).126), res: Def(Fn, DefId(2:8292 ~ core[690e]::panicking::panic)), args: None, infer_args: true }] })), span: /home/centri/.rustup/toolchains/nightly-2023-05-05-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/macros/mod.rs:773:9: 773:33 (#9) }, [Expr { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).127), kind: Lit(Spanned { node: Str("not yet implemented", Cooked), span: /home/centri/.rustup/toolchains/nightly-2023-05-05-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/macros/mod.rs:773:34: 773:55 (#9) }), span: /home/centri/.rustup/toolchains/nightly-2023-05-05-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/macros/mod.rs:773:34: 773:55 (#9) }]), span: /home/centri/.rustup/toolchains/nightly-2023-05-05-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/macros/mod.rs:773:9: 773:56 (#9) }]), span: $DIR/endian_bytes.rs:26:5: 26:32 (#0) } - -error: use of the method `from_ne_bytes` - --> $DIR/endian_bytes.rs:26:5 - | -LL | i32::from_ne_bytes(todo!()); - | ^^^^^^^^^^^^^^^^^^ - | - = help: consider specifying the desired endianness: Expr { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).118), kind: Path(TypeRelative(Ty { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).120), kind: Path(Resolved(None, Path { span: $DIR/endian_bytes.rs:26:5: 26:8 (#0), res: PrimTy(Int(I32)), segments: [PathSegment { ident: i32#0, hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).119), res: PrimTy(Int(I32)), args: None, infer_args: true }] })), span: $DIR/endian_bytes.rs:26:5: 26:8 (#0) }, PathSegment { ident: from_ne_bytes#0, hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).121), res: Err, args: None, infer_args: true })), span: $DIR/endian_bytes.rs:26:5: 26:23 (#0) } - -error: use of the method `from_ne_bytes` - --> $DIR/endian_bytes.rs:26:24 - | -LL | i32::from_ne_bytes(todo!()); - | ^^^^^^^ - | - = help: consider specifying the desired endianness: Expr { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).122), kind: Call(Expr { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).123), kind: Path(Resolved(None, Path { span: /home/centri/.rustup/toolchains/nightly-2023-05-05-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/macros/mod.rs:773:9: 773:33 (#9), res: Def(Fn, DefId(2:8292 ~ core[690e]::panicking::panic)), segments: [PathSegment { ident: $crate#9, hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).124), res: Err, args: None, infer_args: true }, PathSegment { ident: panicking#9, hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).125), res: Def(Mod, DefId(2:8281 ~ core[690e]::panicking)), args: None, infer_args: true }, PathSegment { ident: panic#9, hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).126), res: Def(Fn, DefId(2:8292 ~ core[690e]::panicking::panic)), args: None, infer_args: true }] })), span: /home/centri/.rustup/toolchains/nightly-2023-05-05-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/macros/mod.rs:773:9: 773:33 (#9) }, [Expr { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).127), kind: Lit(Spanned { node: Str("not yet implemented", Cooked), span: /home/centri/.rustup/toolchains/nightly-2023-05-05-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/macros/mod.rs:773:34: 773:55 (#9) }), span: /home/centri/.rustup/toolchains/nightly-2023-05-05-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/macros/mod.rs:773:34: 773:55 (#9) }]), span: /home/centri/.rustup/toolchains/nightly-2023-05-05-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/macros/mod.rs:773:9: 773:56 (#9) } - = note: this error originates in the macro `todo` (in Nightly builds, run with -Z macro-backtrace for more info) - -error: use of the method `from_ne_bytes` - --> $DIR/endian_bytes.rs:26:24 - | -LL | i32::from_ne_bytes(todo!()); - | ^^^^^^^ - | - = help: consider specifying the desired endianness: Expr { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).123), kind: Path(Resolved(None, Path { span: /home/centri/.rustup/toolchains/nightly-2023-05-05-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/macros/mod.rs:773:9: 773:33 (#9), res: Def(Fn, DefId(2:8292 ~ core[690e]::panicking::panic)), segments: [PathSegment { ident: $crate#9, hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).124), res: Err, args: None, infer_args: true }, PathSegment { ident: panicking#9, hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).125), res: Def(Mod, DefId(2:8281 ~ core[690e]::panicking)), args: None, infer_args: true }, PathSegment { ident: panic#9, hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).126), res: Def(Fn, DefId(2:8292 ~ core[690e]::panicking::panic)), args: None, infer_args: true }] })), span: /home/centri/.rustup/toolchains/nightly-2023-05-05-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/macros/mod.rs:773:9: 773:33 (#9) } - = note: this error originates in the macro `todo` (in Nightly builds, run with -Z macro-backtrace for more info) - -error: use of the method `from_ne_bytes` - --> $DIR/endian_bytes.rs:26:24 - | -LL | i32::from_ne_bytes(todo!()); - | ^^^^^^^ - | - = help: consider specifying the desired endianness: Expr { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).127), kind: Lit(Spanned { node: Str("not yet implemented", Cooked), span: /home/centri/.rustup/toolchains/nightly-2023-05-05-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/macros/mod.rs:773:34: 773:55 (#9) }), span: /home/centri/.rustup/toolchains/nightly-2023-05-05-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/macros/mod.rs:773:34: 773:55 (#9) } - = note: this error originates in the macro `todo` (in Nightly builds, run with -Z macro-backtrace for more info) - -error: use of the method `from_ne_bytes` - --> $DIR/endian_bytes.rs:27:5 - | -LL | u64::from_ne_bytes(todo!()); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = help: consider specifying the desired endianness: Expr { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).129), kind: Call(Expr { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).130), kind: Path(TypeRelative(Ty { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).132), kind: Path(Resolved(None, Path { span: $DIR/endian_bytes.rs:27:5: 27:8 (#0), res: PrimTy(Uint(U64)), segments: [PathSegment { ident: u64#0, hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).131), res: PrimTy(Uint(U64)), args: None, infer_args: true }] })), span: $DIR/endian_bytes.rs:27:5: 27:8 (#0) }, PathSegment { ident: from_ne_bytes#0, hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).133), res: Err, args: None, infer_args: true })), span: $DIR/endian_bytes.rs:27:5: 27:23 (#0) }, [Expr { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).134), kind: Call(Expr { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).135), kind: Path(Resolved(None, Path { span: /home/centri/.rustup/toolchains/nightly-2023-05-05-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/macros/mod.rs:773:9: 773:33 (#10), res: Def(Fn, DefId(2:8292 ~ core[690e]::panicking::panic)), segments: [PathSegment { ident: $crate#10, hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).136), res: Err, args: None, infer_args: true }, PathSegment { ident: panicking#10, hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).137), res: Def(Mod, DefId(2:8281 ~ core[690e]::panicking)), args: None, infer_args: true }, PathSegment { ident: panic#10, hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).138), res: Def(Fn, DefId(2:8292 ~ core[690e]::panicking::panic)), args: None, infer_args: true }] })), span: /home/centri/.rustup/toolchains/nightly-2023-05-05-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/macros/mod.rs:773:9: 773:33 (#10) }, [Expr { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).139), kind: Lit(Spanned { node: Str("not yet implemented", Cooked), span: /home/centri/.rustup/toolchains/nightly-2023-05-05-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/macros/mod.rs:773:34: 773:55 (#10) }), span: /home/centri/.rustup/toolchains/nightly-2023-05-05-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/macros/mod.rs:773:34: 773:55 (#10) }]), span: /home/centri/.rustup/toolchains/nightly-2023-05-05-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/macros/mod.rs:773:9: 773:56 (#10) }]), span: $DIR/endian_bytes.rs:27:5: 27:32 (#0) } - -error: use of the method `from_ne_bytes` - --> $DIR/endian_bytes.rs:27:5 - | -LL | u64::from_ne_bytes(todo!()); - | ^^^^^^^^^^^^^^^^^^ - | - = help: consider specifying the desired endianness: Expr { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).130), kind: Path(TypeRelative(Ty { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).132), kind: Path(Resolved(None, Path { span: $DIR/endian_bytes.rs:27:5: 27:8 (#0), res: PrimTy(Uint(U64)), segments: [PathSegment { ident: u64#0, hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).131), res: PrimTy(Uint(U64)), args: None, infer_args: true }] })), span: $DIR/endian_bytes.rs:27:5: 27:8 (#0) }, PathSegment { ident: from_ne_bytes#0, hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).133), res: Err, args: None, infer_args: true })), span: $DIR/endian_bytes.rs:27:5: 27:23 (#0) } - -error: use of the method `from_ne_bytes` - --> $DIR/endian_bytes.rs:27:24 - | -LL | u64::from_ne_bytes(todo!()); - | ^^^^^^^ - | - = help: consider specifying the desired endianness: Expr { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).134), kind: Call(Expr { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).135), kind: Path(Resolved(None, Path { span: /home/centri/.rustup/toolchains/nightly-2023-05-05-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/macros/mod.rs:773:9: 773:33 (#10), res: Def(Fn, DefId(2:8292 ~ core[690e]::panicking::panic)), segments: [PathSegment { ident: $crate#10, hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).136), res: Err, args: None, infer_args: true }, PathSegment { ident: panicking#10, hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).137), res: Def(Mod, DefId(2:8281 ~ core[690e]::panicking)), args: None, infer_args: true }, PathSegment { ident: panic#10, hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).138), res: Def(Fn, DefId(2:8292 ~ core[690e]::panicking::panic)), args: None, infer_args: true }] })), span: /home/centri/.rustup/toolchains/nightly-2023-05-05-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/macros/mod.rs:773:9: 773:33 (#10) }, [Expr { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).139), kind: Lit(Spanned { node: Str("not yet implemented", Cooked), span: /home/centri/.rustup/toolchains/nightly-2023-05-05-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/macros/mod.rs:773:34: 773:55 (#10) }), span: /home/centri/.rustup/toolchains/nightly-2023-05-05-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/macros/mod.rs:773:34: 773:55 (#10) }]), span: /home/centri/.rustup/toolchains/nightly-2023-05-05-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/macros/mod.rs:773:9: 773:56 (#10) } - = note: this error originates in the macro `todo` (in Nightly builds, run with -Z macro-backtrace for more info) - -error: use of the method `from_ne_bytes` - --> $DIR/endian_bytes.rs:27:24 - | -LL | u64::from_ne_bytes(todo!()); - | ^^^^^^^ - | - = help: consider specifying the desired endianness: Expr { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).135), kind: Path(Resolved(None, Path { span: /home/centri/.rustup/toolchains/nightly-2023-05-05-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/macros/mod.rs:773:9: 773:33 (#10), res: Def(Fn, DefId(2:8292 ~ core[690e]::panicking::panic)), segments: [PathSegment { ident: $crate#10, hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).136), res: Err, args: None, infer_args: true }, PathSegment { ident: panicking#10, hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).137), res: Def(Mod, DefId(2:8281 ~ core[690e]::panicking)), args: None, infer_args: true }, PathSegment { ident: panic#10, hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).138), res: Def(Fn, DefId(2:8292 ~ core[690e]::panicking::panic)), args: None, infer_args: true }] })), span: /home/centri/.rustup/toolchains/nightly-2023-05-05-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/macros/mod.rs:773:9: 773:33 (#10) } - = note: this error originates in the macro `todo` (in Nightly builds, run with -Z macro-backtrace for more info) - -error: use of the method `from_ne_bytes` - --> $DIR/endian_bytes.rs:27:24 - | -LL | u64::from_ne_bytes(todo!()); - | ^^^^^^^ - | - = help: consider specifying the desired endianness: Expr { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).139), kind: Lit(Spanned { node: Str("not yet implemented", Cooked), span: /home/centri/.rustup/toolchains/nightly-2023-05-05-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/macros/mod.rs:773:34: 773:55 (#10) }), span: /home/centri/.rustup/toolchains/nightly-2023-05-05-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/macros/mod.rs:773:34: 773:55 (#10) } - = note: this error originates in the macro `todo` (in Nightly builds, run with -Z macro-backtrace for more info) - -error: use of the method `from_ne_bytes` - --> $DIR/endian_bytes.rs:28:5 - | -LL | i64::from_ne_bytes(todo!()); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = help: consider specifying the desired endianness: Expr { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).141), kind: Call(Expr { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).142), kind: Path(TypeRelative(Ty { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).144), kind: Path(Resolved(None, Path { span: $DIR/endian_bytes.rs:28:5: 28:8 (#0), res: PrimTy(Int(I64)), segments: [PathSegment { ident: i64#0, hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).143), res: PrimTy(Int(I64)), args: None, infer_args: true }] })), span: $DIR/endian_bytes.rs:28:5: 28:8 (#0) }, PathSegment { ident: from_ne_bytes#0, hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).145), res: Err, args: None, infer_args: true })), span: $DIR/endian_bytes.rs:28:5: 28:23 (#0) }, [Expr { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).146), kind: Call(Expr { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).147), kind: Path(Resolved(None, Path { span: /home/centri/.rustup/toolchains/nightly-2023-05-05-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/macros/mod.rs:773:9: 773:33 (#11), res: Def(Fn, DefId(2:8292 ~ core[690e]::panicking::panic)), segments: [PathSegment { ident: $crate#11, hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).148), res: Err, args: None, infer_args: true }, PathSegment { ident: panicking#11, hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).149), res: Def(Mod, DefId(2:8281 ~ core[690e]::panicking)), args: None, infer_args: true }, PathSegment { ident: panic#11, hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).150), res: Def(Fn, DefId(2:8292 ~ core[690e]::panicking::panic)), args: None, infer_args: true }] })), span: /home/centri/.rustup/toolchains/nightly-2023-05-05-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/macros/mod.rs:773:9: 773:33 (#11) }, [Expr { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).151), kind: Lit(Spanned { node: Str("not yet implemented", Cooked), span: /home/centri/.rustup/toolchains/nightly-2023-05-05-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/macros/mod.rs:773:34: 773:55 (#11) }), span: /home/centri/.rustup/toolchains/nightly-2023-05-05-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/macros/mod.rs:773:34: 773:55 (#11) }]), span: /home/centri/.rustup/toolchains/nightly-2023-05-05-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/macros/mod.rs:773:9: 773:56 (#11) }]), span: $DIR/endian_bytes.rs:28:5: 28:32 (#0) } - -error: use of the method `from_ne_bytes` - --> $DIR/endian_bytes.rs:28:5 - | -LL | i64::from_ne_bytes(todo!()); - | ^^^^^^^^^^^^^^^^^^ - | - = help: consider specifying the desired endianness: Expr { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).142), kind: Path(TypeRelative(Ty { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).144), kind: Path(Resolved(None, Path { span: $DIR/endian_bytes.rs:28:5: 28:8 (#0), res: PrimTy(Int(I64)), segments: [PathSegment { ident: i64#0, hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).143), res: PrimTy(Int(I64)), args: None, infer_args: true }] })), span: $DIR/endian_bytes.rs:28:5: 28:8 (#0) }, PathSegment { ident: from_ne_bytes#0, hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).145), res: Err, args: None, infer_args: true })), span: $DIR/endian_bytes.rs:28:5: 28:23 (#0) } - -error: use of the method `from_ne_bytes` - --> $DIR/endian_bytes.rs:28:24 - | -LL | i64::from_ne_bytes(todo!()); - | ^^^^^^^ - | - = help: consider specifying the desired endianness: Expr { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).146), kind: Call(Expr { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).147), kind: Path(Resolved(None, Path { span: /home/centri/.rustup/toolchains/nightly-2023-05-05-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/macros/mod.rs:773:9: 773:33 (#11), res: Def(Fn, DefId(2:8292 ~ core[690e]::panicking::panic)), segments: [PathSegment { ident: $crate#11, hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).148), res: Err, args: None, infer_args: true }, PathSegment { ident: panicking#11, hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).149), res: Def(Mod, DefId(2:8281 ~ core[690e]::panicking)), args: None, infer_args: true }, PathSegment { ident: panic#11, hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).150), res: Def(Fn, DefId(2:8292 ~ core[690e]::panicking::panic)), args: None, infer_args: true }] })), span: /home/centri/.rustup/toolchains/nightly-2023-05-05-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/macros/mod.rs:773:9: 773:33 (#11) }, [Expr { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).151), kind: Lit(Spanned { node: Str("not yet implemented", Cooked), span: /home/centri/.rustup/toolchains/nightly-2023-05-05-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/macros/mod.rs:773:34: 773:55 (#11) }), span: /home/centri/.rustup/toolchains/nightly-2023-05-05-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/macros/mod.rs:773:34: 773:55 (#11) }]), span: /home/centri/.rustup/toolchains/nightly-2023-05-05-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/macros/mod.rs:773:9: 773:56 (#11) } - = note: this error originates in the macro `todo` (in Nightly builds, run with -Z macro-backtrace for more info) - -error: use of the method `from_ne_bytes` - --> $DIR/endian_bytes.rs:28:24 - | -LL | i64::from_ne_bytes(todo!()); - | ^^^^^^^ - | - = help: consider specifying the desired endianness: Expr { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).147), kind: Path(Resolved(None, Path { span: /home/centri/.rustup/toolchains/nightly-2023-05-05-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/macros/mod.rs:773:9: 773:33 (#11), res: Def(Fn, DefId(2:8292 ~ core[690e]::panicking::panic)), segments: [PathSegment { ident: $crate#11, hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).148), res: Err, args: None, infer_args: true }, PathSegment { ident: panicking#11, hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).149), res: Def(Mod, DefId(2:8281 ~ core[690e]::panicking)), args: None, infer_args: true }, PathSegment { ident: panic#11, hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).150), res: Def(Fn, DefId(2:8292 ~ core[690e]::panicking::panic)), args: None, infer_args: true }] })), span: /home/centri/.rustup/toolchains/nightly-2023-05-05-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/macros/mod.rs:773:9: 773:33 (#11) } - = note: this error originates in the macro `todo` (in Nightly builds, run with -Z macro-backtrace for more info) - -error: use of the method `from_ne_bytes` - --> $DIR/endian_bytes.rs:28:24 - | -LL | i64::from_ne_bytes(todo!()); - | ^^^^^^^ - | - = help: consider specifying the desired endianness: Expr { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).151), kind: Lit(Spanned { node: Str("not yet implemented", Cooked), span: /home/centri/.rustup/toolchains/nightly-2023-05-05-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/macros/mod.rs:773:34: 773:55 (#11) }), span: /home/centri/.rustup/toolchains/nightly-2023-05-05-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/macros/mod.rs:773:34: 773:55 (#11) } - = note: this error originates in the macro `todo` (in Nightly builds, run with -Z macro-backtrace for more info) - -error: use of the method `from_ne_bytes` - --> $DIR/endian_bytes.rs:29:5 - | -LL | u128::from_ne_bytes(todo!()); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = help: consider specifying the desired endianness: Expr { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).153), kind: Call(Expr { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).154), kind: Path(TypeRelative(Ty { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).156), kind: Path(Resolved(None, Path { span: $DIR/endian_bytes.rs:29:5: 29:9 (#0), res: PrimTy(Uint(U128)), segments: [PathSegment { ident: u128#0, hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).155), res: PrimTy(Uint(U128)), args: None, infer_args: true }] })), span: $DIR/endian_bytes.rs:29:5: 29:9 (#0) }, PathSegment { ident: from_ne_bytes#0, hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).157), res: Err, args: None, infer_args: true })), span: $DIR/endian_bytes.rs:29:5: 29:24 (#0) }, [Expr { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).158), kind: Call(Expr { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).159), kind: Path(Resolved(None, Path { span: /home/centri/.rustup/toolchains/nightly-2023-05-05-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/macros/mod.rs:773:9: 773:33 (#12), res: Def(Fn, DefId(2:8292 ~ core[690e]::panicking::panic)), segments: [PathSegment { ident: $crate#12, hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).160), res: Err, args: None, infer_args: true }, PathSegment { ident: panicking#12, hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).161), res: Def(Mod, DefId(2:8281 ~ core[690e]::panicking)), args: None, infer_args: true }, PathSegment { ident: panic#12, hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).162), res: Def(Fn, DefId(2:8292 ~ core[690e]::panicking::panic)), args: None, infer_args: true }] })), span: /home/centri/.rustup/toolchains/nightly-2023-05-05-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/macros/mod.rs:773:9: 773:33 (#12) }, [Expr { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).163), kind: Lit(Spanned { node: Str("not yet implemented", Cooked), span: /home/centri/.rustup/toolchains/nightly-2023-05-05-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/macros/mod.rs:773:34: 773:55 (#12) }), span: /home/centri/.rustup/toolchains/nightly-2023-05-05-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/macros/mod.rs:773:34: 773:55 (#12) }]), span: /home/centri/.rustup/toolchains/nightly-2023-05-05-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/macros/mod.rs:773:9: 773:56 (#12) }]), span: $DIR/endian_bytes.rs:29:5: 29:33 (#0) } - -error: use of the method `from_ne_bytes` - --> $DIR/endian_bytes.rs:29:5 - | -LL | u128::from_ne_bytes(todo!()); - | ^^^^^^^^^^^^^^^^^^^ - | - = help: consider specifying the desired endianness: Expr { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).154), kind: Path(TypeRelative(Ty { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).156), kind: Path(Resolved(None, Path { span: $DIR/endian_bytes.rs:29:5: 29:9 (#0), res: PrimTy(Uint(U128)), segments: [PathSegment { ident: u128#0, hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).155), res: PrimTy(Uint(U128)), args: None, infer_args: true }] })), span: $DIR/endian_bytes.rs:29:5: 29:9 (#0) }, PathSegment { ident: from_ne_bytes#0, hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).157), res: Err, args: None, infer_args: true })), span: $DIR/endian_bytes.rs:29:5: 29:24 (#0) } - -error: use of the method `from_ne_bytes` - --> $DIR/endian_bytes.rs:29:25 - | -LL | u128::from_ne_bytes(todo!()); - | ^^^^^^^ - | - = help: consider specifying the desired endianness: Expr { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).158), kind: Call(Expr { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).159), kind: Path(Resolved(None, Path { span: /home/centri/.rustup/toolchains/nightly-2023-05-05-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/macros/mod.rs:773:9: 773:33 (#12), res: Def(Fn, DefId(2:8292 ~ core[690e]::panicking::panic)), segments: [PathSegment { ident: $crate#12, hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).160), res: Err, args: None, infer_args: true }, PathSegment { ident: panicking#12, hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).161), res: Def(Mod, DefId(2:8281 ~ core[690e]::panicking)), args: None, infer_args: true }, PathSegment { ident: panic#12, hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).162), res: Def(Fn, DefId(2:8292 ~ core[690e]::panicking::panic)), args: None, infer_args: true }] })), span: /home/centri/.rustup/toolchains/nightly-2023-05-05-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/macros/mod.rs:773:9: 773:33 (#12) }, [Expr { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).163), kind: Lit(Spanned { node: Str("not yet implemented", Cooked), span: /home/centri/.rustup/toolchains/nightly-2023-05-05-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/macros/mod.rs:773:34: 773:55 (#12) }), span: /home/centri/.rustup/toolchains/nightly-2023-05-05-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/macros/mod.rs:773:34: 773:55 (#12) }]), span: /home/centri/.rustup/toolchains/nightly-2023-05-05-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/macros/mod.rs:773:9: 773:56 (#12) } - = note: this error originates in the macro `todo` (in Nightly builds, run with -Z macro-backtrace for more info) - -error: use of the method `from_ne_bytes` - --> $DIR/endian_bytes.rs:29:25 - | -LL | u128::from_ne_bytes(todo!()); - | ^^^^^^^ - | - = help: consider specifying the desired endianness: Expr { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).159), kind: Path(Resolved(None, Path { span: /home/centri/.rustup/toolchains/nightly-2023-05-05-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/macros/mod.rs:773:9: 773:33 (#12), res: Def(Fn, DefId(2:8292 ~ core[690e]::panicking::panic)), segments: [PathSegment { ident: $crate#12, hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).160), res: Err, args: None, infer_args: true }, PathSegment { ident: panicking#12, hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).161), res: Def(Mod, DefId(2:8281 ~ core[690e]::panicking)), args: None, infer_args: true }, PathSegment { ident: panic#12, hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).162), res: Def(Fn, DefId(2:8292 ~ core[690e]::panicking::panic)), args: None, infer_args: true }] })), span: /home/centri/.rustup/toolchains/nightly-2023-05-05-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/macros/mod.rs:773:9: 773:33 (#12) } - = note: this error originates in the macro `todo` (in Nightly builds, run with -Z macro-backtrace for more info) - -error: use of the method `from_ne_bytes` - --> $DIR/endian_bytes.rs:29:25 - | -LL | u128::from_ne_bytes(todo!()); - | ^^^^^^^ - | - = help: consider specifying the desired endianness: Expr { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).163), kind: Lit(Spanned { node: Str("not yet implemented", Cooked), span: /home/centri/.rustup/toolchains/nightly-2023-05-05-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/macros/mod.rs:773:34: 773:55 (#12) }), span: /home/centri/.rustup/toolchains/nightly-2023-05-05-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/macros/mod.rs:773:34: 773:55 (#12) } - = note: this error originates in the macro `todo` (in Nightly builds, run with -Z macro-backtrace for more info) - -error: use of the method `from_ne_bytes` - --> $DIR/endian_bytes.rs:30:5 - | -LL | i128::from_ne_bytes(todo!()); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = help: consider specifying the desired endianness: Expr { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).165), kind: Call(Expr { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).166), kind: Path(TypeRelative(Ty { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).168), kind: Path(Resolved(None, Path { span: $DIR/endian_bytes.rs:30:5: 30:9 (#0), res: PrimTy(Int(I128)), segments: [PathSegment { ident: i128#0, hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).167), res: PrimTy(Int(I128)), args: None, infer_args: true }] })), span: $DIR/endian_bytes.rs:30:5: 30:9 (#0) }, PathSegment { ident: from_ne_bytes#0, hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).169), res: Err, args: None, infer_args: true })), span: $DIR/endian_bytes.rs:30:5: 30:24 (#0) }, [Expr { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).170), kind: Call(Expr { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).171), kind: Path(Resolved(None, Path { span: /home/centri/.rustup/toolchains/nightly-2023-05-05-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/macros/mod.rs:773:9: 773:33 (#13), res: Def(Fn, DefId(2:8292 ~ core[690e]::panicking::panic)), segments: [PathSegment { ident: $crate#13, hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).172), res: Err, args: None, infer_args: true }, PathSegment { ident: panicking#13, hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).173), res: Def(Mod, DefId(2:8281 ~ core[690e]::panicking)), args: None, infer_args: true }, PathSegment { ident: panic#13, hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).174), res: Def(Fn, DefId(2:8292 ~ core[690e]::panicking::panic)), args: None, infer_args: true }] })), span: /home/centri/.rustup/toolchains/nightly-2023-05-05-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/macros/mod.rs:773:9: 773:33 (#13) }, [Expr { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).175), kind: Lit(Spanned { node: Str("not yet implemented", Cooked), span: /home/centri/.rustup/toolchains/nightly-2023-05-05-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/macros/mod.rs:773:34: 773:55 (#13) }), span: /home/centri/.rustup/toolchains/nightly-2023-05-05-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/macros/mod.rs:773:34: 773:55 (#13) }]), span: /home/centri/.rustup/toolchains/nightly-2023-05-05-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/macros/mod.rs:773:9: 773:56 (#13) }]), span: $DIR/endian_bytes.rs:30:5: 30:33 (#0) } - -error: use of the method `from_ne_bytes` - --> $DIR/endian_bytes.rs:30:5 - | -LL | i128::from_ne_bytes(todo!()); - | ^^^^^^^^^^^^^^^^^^^ - | - = help: consider specifying the desired endianness: Expr { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).166), kind: Path(TypeRelative(Ty { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).168), kind: Path(Resolved(None, Path { span: $DIR/endian_bytes.rs:30:5: 30:9 (#0), res: PrimTy(Int(I128)), segments: [PathSegment { ident: i128#0, hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).167), res: PrimTy(Int(I128)), args: None, infer_args: true }] })), span: $DIR/endian_bytes.rs:30:5: 30:9 (#0) }, PathSegment { ident: from_ne_bytes#0, hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).169), res: Err, args: None, infer_args: true })), span: $DIR/endian_bytes.rs:30:5: 30:24 (#0) } - -error: use of the method `from_ne_bytes` - --> $DIR/endian_bytes.rs:30:25 - | -LL | i128::from_ne_bytes(todo!()); - | ^^^^^^^ - | - = help: consider specifying the desired endianness: Expr { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).170), kind: Call(Expr { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).171), kind: Path(Resolved(None, Path { span: /home/centri/.rustup/toolchains/nightly-2023-05-05-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/macros/mod.rs:773:9: 773:33 (#13), res: Def(Fn, DefId(2:8292 ~ core[690e]::panicking::panic)), segments: [PathSegment { ident: $crate#13, hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).172), res: Err, args: None, infer_args: true }, PathSegment { ident: panicking#13, hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).173), res: Def(Mod, DefId(2:8281 ~ core[690e]::panicking)), args: None, infer_args: true }, PathSegment { ident: panic#13, hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).174), res: Def(Fn, DefId(2:8292 ~ core[690e]::panicking::panic)), args: None, infer_args: true }] })), span: /home/centri/.rustup/toolchains/nightly-2023-05-05-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/macros/mod.rs:773:9: 773:33 (#13) }, [Expr { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).175), kind: Lit(Spanned { node: Str("not yet implemented", Cooked), span: /home/centri/.rustup/toolchains/nightly-2023-05-05-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/macros/mod.rs:773:34: 773:55 (#13) }), span: /home/centri/.rustup/toolchains/nightly-2023-05-05-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/macros/mod.rs:773:34: 773:55 (#13) }]), span: /home/centri/.rustup/toolchains/nightly-2023-05-05-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/macros/mod.rs:773:9: 773:56 (#13) } - = note: this error originates in the macro `todo` (in Nightly builds, run with -Z macro-backtrace for more info) - -error: use of the method `from_ne_bytes` - --> $DIR/endian_bytes.rs:30:25 - | -LL | i128::from_ne_bytes(todo!()); - | ^^^^^^^ - | - = help: consider specifying the desired endianness: Expr { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).171), kind: Path(Resolved(None, Path { span: /home/centri/.rustup/toolchains/nightly-2023-05-05-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/macros/mod.rs:773:9: 773:33 (#13), res: Def(Fn, DefId(2:8292 ~ core[690e]::panicking::panic)), segments: [PathSegment { ident: $crate#13, hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).172), res: Err, args: None, infer_args: true }, PathSegment { ident: panicking#13, hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).173), res: Def(Mod, DefId(2:8281 ~ core[690e]::panicking)), args: None, infer_args: true }, PathSegment { ident: panic#13, hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).174), res: Def(Fn, DefId(2:8292 ~ core[690e]::panicking::panic)), args: None, infer_args: true }] })), span: /home/centri/.rustup/toolchains/nightly-2023-05-05-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/macros/mod.rs:773:9: 773:33 (#13) } - = note: this error originates in the macro `todo` (in Nightly builds, run with -Z macro-backtrace for more info) - -error: use of the method `from_ne_bytes` - --> $DIR/endian_bytes.rs:30:25 - | -LL | i128::from_ne_bytes(todo!()); - | ^^^^^^^ - | - = help: consider specifying the desired endianness: Expr { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).175), kind: Lit(Spanned { node: Str("not yet implemented", Cooked), span: /home/centri/.rustup/toolchains/nightly-2023-05-05-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/macros/mod.rs:773:34: 773:55 (#13) }), span: /home/centri/.rustup/toolchains/nightly-2023-05-05-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/macros/mod.rs:773:34: 773:55 (#13) } - = note: this error originates in the macro `todo` (in Nightly builds, run with -Z macro-backtrace for more info) - -error: use of the method `from_ne_bytes` - --> $DIR/endian_bytes.rs:31:5 - | -LL | f32::from_ne_bytes(todo!()); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = help: consider specifying the desired endianness: Expr { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).177), kind: Call(Expr { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).178), kind: Path(TypeRelative(Ty { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).180), kind: Path(Resolved(None, Path { span: $DIR/endian_bytes.rs:31:5: 31:8 (#0), res: PrimTy(Float(F32)), segments: [PathSegment { ident: f32#0, hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).179), res: PrimTy(Float(F32)), args: None, infer_args: true }] })), span: $DIR/endian_bytes.rs:31:5: 31:8 (#0) }, PathSegment { ident: from_ne_bytes#0, hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).181), res: Err, args: None, infer_args: true })), span: $DIR/endian_bytes.rs:31:5: 31:23 (#0) }, [Expr { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).182), kind: Call(Expr { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).183), kind: Path(Resolved(None, Path { span: /home/centri/.rustup/toolchains/nightly-2023-05-05-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/macros/mod.rs:773:9: 773:33 (#14), res: Def(Fn, DefId(2:8292 ~ core[690e]::panicking::panic)), segments: [PathSegment { ident: $crate#14, hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).184), res: Err, args: None, infer_args: true }, PathSegment { ident: panicking#14, hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).185), res: Def(Mod, DefId(2:8281 ~ core[690e]::panicking)), args: None, infer_args: true }, PathSegment { ident: panic#14, hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).186), res: Def(Fn, DefId(2:8292 ~ core[690e]::panicking::panic)), args: None, infer_args: true }] })), span: /home/centri/.rustup/toolchains/nightly-2023-05-05-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/macros/mod.rs:773:9: 773:33 (#14) }, [Expr { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).187), kind: Lit(Spanned { node: Str("not yet implemented", Cooked), span: /home/centri/.rustup/toolchains/nightly-2023-05-05-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/macros/mod.rs:773:34: 773:55 (#14) }), span: /home/centri/.rustup/toolchains/nightly-2023-05-05-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/macros/mod.rs:773:34: 773:55 (#14) }]), span: /home/centri/.rustup/toolchains/nightly-2023-05-05-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/macros/mod.rs:773:9: 773:56 (#14) }]), span: $DIR/endian_bytes.rs:31:5: 31:32 (#0) } - -error: use of the method `from_ne_bytes` - --> $DIR/endian_bytes.rs:31:5 - | -LL | f32::from_ne_bytes(todo!()); - | ^^^^^^^^^^^^^^^^^^ - | - = help: consider specifying the desired endianness: Expr { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).178), kind: Path(TypeRelative(Ty { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).180), kind: Path(Resolved(None, Path { span: $DIR/endian_bytes.rs:31:5: 31:8 (#0), res: PrimTy(Float(F32)), segments: [PathSegment { ident: f32#0, hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).179), res: PrimTy(Float(F32)), args: None, infer_args: true }] })), span: $DIR/endian_bytes.rs:31:5: 31:8 (#0) }, PathSegment { ident: from_ne_bytes#0, hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).181), res: Err, args: None, infer_args: true })), span: $DIR/endian_bytes.rs:31:5: 31:23 (#0) } - -error: use of the method `from_ne_bytes` - --> $DIR/endian_bytes.rs:31:24 - | -LL | f32::from_ne_bytes(todo!()); - | ^^^^^^^ - | - = help: consider specifying the desired endianness: Expr { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).182), kind: Call(Expr { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).183), kind: Path(Resolved(None, Path { span: /home/centri/.rustup/toolchains/nightly-2023-05-05-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/macros/mod.rs:773:9: 773:33 (#14), res: Def(Fn, DefId(2:8292 ~ core[690e]::panicking::panic)), segments: [PathSegment { ident: $crate#14, hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).184), res: Err, args: None, infer_args: true }, PathSegment { ident: panicking#14, hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).185), res: Def(Mod, DefId(2:8281 ~ core[690e]::panicking)), args: None, infer_args: true }, PathSegment { ident: panic#14, hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).186), res: Def(Fn, DefId(2:8292 ~ core[690e]::panicking::panic)), args: None, infer_args: true }] })), span: /home/centri/.rustup/toolchains/nightly-2023-05-05-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/macros/mod.rs:773:9: 773:33 (#14) }, [Expr { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).187), kind: Lit(Spanned { node: Str("not yet implemented", Cooked), span: /home/centri/.rustup/toolchains/nightly-2023-05-05-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/macros/mod.rs:773:34: 773:55 (#14) }), span: /home/centri/.rustup/toolchains/nightly-2023-05-05-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/macros/mod.rs:773:34: 773:55 (#14) }]), span: /home/centri/.rustup/toolchains/nightly-2023-05-05-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/macros/mod.rs:773:9: 773:56 (#14) } - = note: this error originates in the macro `todo` (in Nightly builds, run with -Z macro-backtrace for more info) - -error: use of the method `from_ne_bytes` - --> $DIR/endian_bytes.rs:31:24 - | -LL | f32::from_ne_bytes(todo!()); - | ^^^^^^^ - | - = help: consider specifying the desired endianness: Expr { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).183), kind: Path(Resolved(None, Path { span: /home/centri/.rustup/toolchains/nightly-2023-05-05-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/macros/mod.rs:773:9: 773:33 (#14), res: Def(Fn, DefId(2:8292 ~ core[690e]::panicking::panic)), segments: [PathSegment { ident: $crate#14, hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).184), res: Err, args: None, infer_args: true }, PathSegment { ident: panicking#14, hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).185), res: Def(Mod, DefId(2:8281 ~ core[690e]::panicking)), args: None, infer_args: true }, PathSegment { ident: panic#14, hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).186), res: Def(Fn, DefId(2:8292 ~ core[690e]::panicking::panic)), args: None, infer_args: true }] })), span: /home/centri/.rustup/toolchains/nightly-2023-05-05-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/macros/mod.rs:773:9: 773:33 (#14) } - = note: this error originates in the macro `todo` (in Nightly builds, run with -Z macro-backtrace for more info) - -error: use of the method `from_ne_bytes` - --> $DIR/endian_bytes.rs:31:24 - | -LL | f32::from_ne_bytes(todo!()); - | ^^^^^^^ - | - = help: consider specifying the desired endianness: Expr { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).187), kind: Lit(Spanned { node: Str("not yet implemented", Cooked), span: /home/centri/.rustup/toolchains/nightly-2023-05-05-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/macros/mod.rs:773:34: 773:55 (#14) }), span: /home/centri/.rustup/toolchains/nightly-2023-05-05-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/macros/mod.rs:773:34: 773:55 (#14) } - = note: this error originates in the macro `todo` (in Nightly builds, run with -Z macro-backtrace for more info) - -error: use of the method `from_ne_bytes` - --> $DIR/endian_bytes.rs:32:5 - | -LL | f64::from_ne_bytes(todo!()); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = help: consider specifying the desired endianness: Expr { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).189), kind: Call(Expr { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).190), kind: Path(TypeRelative(Ty { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).192), kind: Path(Resolved(None, Path { span: $DIR/endian_bytes.rs:32:5: 32:8 (#0), res: PrimTy(Float(F64)), segments: [PathSegment { ident: f64#0, hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).191), res: PrimTy(Float(F64)), args: None, infer_args: true }] })), span: $DIR/endian_bytes.rs:32:5: 32:8 (#0) }, PathSegment { ident: from_ne_bytes#0, hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).193), res: Err, args: None, infer_args: true })), span: $DIR/endian_bytes.rs:32:5: 32:23 (#0) }, [Expr { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).194), kind: Call(Expr { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).195), kind: Path(Resolved(None, Path { span: /home/centri/.rustup/toolchains/nightly-2023-05-05-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/macros/mod.rs:773:9: 773:33 (#15), res: Def(Fn, DefId(2:8292 ~ core[690e]::panicking::panic)), segments: [PathSegment { ident: $crate#15, hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).196), res: Err, args: None, infer_args: true }, PathSegment { ident: panicking#15, hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).197), res: Def(Mod, DefId(2:8281 ~ core[690e]::panicking)), args: None, infer_args: true }, PathSegment { ident: panic#15, hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).198), res: Def(Fn, DefId(2:8292 ~ core[690e]::panicking::panic)), args: None, infer_args: true }] })), span: /home/centri/.rustup/toolchains/nightly-2023-05-05-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/macros/mod.rs:773:9: 773:33 (#15) }, [Expr { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).199), kind: Lit(Spanned { node: Str("not yet implemented", Cooked), span: /home/centri/.rustup/toolchains/nightly-2023-05-05-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/macros/mod.rs:773:34: 773:55 (#15) }), span: /home/centri/.rustup/toolchains/nightly-2023-05-05-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/macros/mod.rs:773:34: 773:55 (#15) }]), span: /home/centri/.rustup/toolchains/nightly-2023-05-05-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/macros/mod.rs:773:9: 773:56 (#15) }]), span: $DIR/endian_bytes.rs:32:5: 32:32 (#0) } - -error: use of the method `from_ne_bytes` - --> $DIR/endian_bytes.rs:32:5 - | -LL | f64::from_ne_bytes(todo!()); - | ^^^^^^^^^^^^^^^^^^ - | - = help: consider specifying the desired endianness: Expr { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).190), kind: Path(TypeRelative(Ty { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).192), kind: Path(Resolved(None, Path { span: $DIR/endian_bytes.rs:32:5: 32:8 (#0), res: PrimTy(Float(F64)), segments: [PathSegment { ident: f64#0, hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).191), res: PrimTy(Float(F64)), args: None, infer_args: true }] })), span: $DIR/endian_bytes.rs:32:5: 32:8 (#0) }, PathSegment { ident: from_ne_bytes#0, hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).193), res: Err, args: None, infer_args: true })), span: $DIR/endian_bytes.rs:32:5: 32:23 (#0) } - -error: use of the method `from_ne_bytes` - --> $DIR/endian_bytes.rs:32:24 - | -LL | f64::from_ne_bytes(todo!()); - | ^^^^^^^ - | - = help: consider specifying the desired endianness: Expr { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).194), kind: Call(Expr { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).195), kind: Path(Resolved(None, Path { span: /home/centri/.rustup/toolchains/nightly-2023-05-05-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/macros/mod.rs:773:9: 773:33 (#15), res: Def(Fn, DefId(2:8292 ~ core[690e]::panicking::panic)), segments: [PathSegment { ident: $crate#15, hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).196), res: Err, args: None, infer_args: true }, PathSegment { ident: panicking#15, hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).197), res: Def(Mod, DefId(2:8281 ~ core[690e]::panicking)), args: None, infer_args: true }, PathSegment { ident: panic#15, hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).198), res: Def(Fn, DefId(2:8292 ~ core[690e]::panicking::panic)), args: None, infer_args: true }] })), span: /home/centri/.rustup/toolchains/nightly-2023-05-05-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/macros/mod.rs:773:9: 773:33 (#15) }, [Expr { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).199), kind: Lit(Spanned { node: Str("not yet implemented", Cooked), span: /home/centri/.rustup/toolchains/nightly-2023-05-05-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/macros/mod.rs:773:34: 773:55 (#15) }), span: /home/centri/.rustup/toolchains/nightly-2023-05-05-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/macros/mod.rs:773:34: 773:55 (#15) }]), span: /home/centri/.rustup/toolchains/nightly-2023-05-05-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/macros/mod.rs:773:9: 773:56 (#15) } - = note: this error originates in the macro `todo` (in Nightly builds, run with -Z macro-backtrace for more info) - -error: use of the method `from_ne_bytes` - --> $DIR/endian_bytes.rs:32:24 - | -LL | f64::from_ne_bytes(todo!()); - | ^^^^^^^ - | - = help: consider specifying the desired endianness: Expr { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).195), kind: Path(Resolved(None, Path { span: /home/centri/.rustup/toolchains/nightly-2023-05-05-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/macros/mod.rs:773:9: 773:33 (#15), res: Def(Fn, DefId(2:8292 ~ core[690e]::panicking::panic)), segments: [PathSegment { ident: $crate#15, hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).196), res: Err, args: None, infer_args: true }, PathSegment { ident: panicking#15, hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).197), res: Def(Mod, DefId(2:8281 ~ core[690e]::panicking)), args: None, infer_args: true }, PathSegment { ident: panic#15, hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).198), res: Def(Fn, DefId(2:8292 ~ core[690e]::panicking::panic)), args: None, infer_args: true }] })), span: /home/centri/.rustup/toolchains/nightly-2023-05-05-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/macros/mod.rs:773:9: 773:33 (#15) } - = note: this error originates in the macro `todo` (in Nightly builds, run with -Z macro-backtrace for more info) - -error: use of the method `from_ne_bytes` - --> $DIR/endian_bytes.rs:32:24 - | -LL | f64::from_ne_bytes(todo!()); - | ^^^^^^^ - | - = help: consider specifying the desired endianness: Expr { hir_id: HirId(DefId(0:3 ~ endian_bytes[6e38]::host).199), kind: Lit(Spanned { node: Str("not yet implemented", Cooked), span: /home/centri/.rustup/toolchains/nightly-2023-05-05-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/macros/mod.rs:773:34: 773:55 (#15) }), span: /home/centri/.rustup/toolchains/nightly-2023-05-05-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/macros/mod.rs:773:34: 773:55 (#15) } - = note: this error originates in the macro `todo` (in Nightly builds, run with -Z macro-backtrace for more info) - -error: use of the method `to_le_bytes` - --> $DIR/endian_bytes.rs:37:5 - | -LL | 2u8.to_le_bytes(); - | ^^^^^^^^^^^^^^^^^ - | - = help: use `to_be_bytes` instead + = help: use the native endianness instead = note: `-D clippy::little-endian-bytes` implied by `-D warnings` + = note: this error originates in the macro `fn_body` (in Nightly builds, run with -Z macro-backtrace for more info) -error: use of the method `to_le_bytes` - --> $DIR/endian_bytes.rs:38:5 +error: usage of the method `to_le_bytes` + --> $DIR/endian_bytes.rs:37:9 | -LL | 2i8.to_le_bytes(); - | ^^^^^^^^^^^^^^^^^ +LL | 2i8.to_le_bytes(); + | ^^^^^^^^^^^^^^^^^ +... +LL | fn little() { fn_body!(); } + | ---------- in this macro invocation | - = help: use `to_be_bytes` instead + = help: use the native endianness instead + = note: this error originates in the macro `fn_body` (in Nightly builds, run with -Z macro-backtrace for more info) -error: use of the method `to_le_bytes` - --> $DIR/endian_bytes.rs:39:5 +error: usage of the method `to_le_bytes` + --> $DIR/endian_bytes.rs:38:9 | -LL | 2u16.to_le_bytes(); - | ^^^^^^^^^^^^^^^^^^ +LL | 2u16.to_le_bytes(); + | ^^^^^^^^^^^^^^^^^^ +... +LL | fn little() { fn_body!(); } + | ---------- in this macro invocation | - = help: use `to_be_bytes` instead + = help: use the native endianness instead + = note: this error originates in the macro `fn_body` (in Nightly builds, run with -Z macro-backtrace for more info) -error: use of the method `to_le_bytes` - --> $DIR/endian_bytes.rs:40:5 +error: usage of the method `to_le_bytes` + --> $DIR/endian_bytes.rs:39:9 | -LL | 2i16.to_le_bytes(); - | ^^^^^^^^^^^^^^^^^^ +LL | 2i16.to_le_bytes(); + | ^^^^^^^^^^^^^^^^^^ +... +LL | fn little() { fn_body!(); } + | ---------- in this macro invocation | - = help: use `to_be_bytes` instead + = help: use the native endianness instead + = note: this error originates in the macro `fn_body` (in Nightly builds, run with -Z macro-backtrace for more info) -error: use of the method `to_le_bytes` - --> $DIR/endian_bytes.rs:41:5 +error: usage of the method `to_le_bytes` + --> $DIR/endian_bytes.rs:40:9 | -LL | 2u32.to_le_bytes(); - | ^^^^^^^^^^^^^^^^^^ +LL | 2u32.to_le_bytes(); + | ^^^^^^^^^^^^^^^^^^ +... +LL | fn little() { fn_body!(); } + | ---------- in this macro invocation | - = help: use `to_be_bytes` instead + = help: use the native endianness instead + = note: this error originates in the macro `fn_body` (in Nightly builds, run with -Z macro-backtrace for more info) -error: use of the method `to_le_bytes` - --> $DIR/endian_bytes.rs:42:5 +error: usage of the method `to_le_bytes` + --> $DIR/endian_bytes.rs:41:9 | -LL | 2i32.to_le_bytes(); - | ^^^^^^^^^^^^^^^^^^ +LL | 2i32.to_le_bytes(); + | ^^^^^^^^^^^^^^^^^^ +... +LL | fn little() { fn_body!(); } + | ---------- in this macro invocation | - = help: use `to_be_bytes` instead + = help: use the native endianness instead + = note: this error originates in the macro `fn_body` (in Nightly builds, run with -Z macro-backtrace for more info) -error: use of the method `to_le_bytes` - --> $DIR/endian_bytes.rs:43:5 +error: usage of the method `to_le_bytes` + --> $DIR/endian_bytes.rs:42:9 | -LL | 2u64.to_le_bytes(); - | ^^^^^^^^^^^^^^^^^^ +LL | 2u64.to_le_bytes(); + | ^^^^^^^^^^^^^^^^^^ +... +LL | fn little() { fn_body!(); } + | ---------- in this macro invocation | - = help: use `to_be_bytes` instead + = help: use the native endianness instead + = note: this error originates in the macro `fn_body` (in Nightly builds, run with -Z macro-backtrace for more info) -error: use of the method `to_le_bytes` - --> $DIR/endian_bytes.rs:44:5 +error: usage of the method `to_le_bytes` + --> $DIR/endian_bytes.rs:43:9 | -LL | 2i64.to_le_bytes(); - | ^^^^^^^^^^^^^^^^^^ +LL | 2i64.to_le_bytes(); + | ^^^^^^^^^^^^^^^^^^ +... +LL | fn little() { fn_body!(); } + | ---------- in this macro invocation | - = help: use `to_be_bytes` instead + = help: use the native endianness instead + = note: this error originates in the macro `fn_body` (in Nightly builds, run with -Z macro-backtrace for more info) -error: use of the method `to_le_bytes` - --> $DIR/endian_bytes.rs:45:5 +error: usage of the method `to_le_bytes` + --> $DIR/endian_bytes.rs:44:9 | -LL | 2u128.to_le_bytes(); - | ^^^^^^^^^^^^^^^^^^^ +LL | 2u128.to_le_bytes(); + | ^^^^^^^^^^^^^^^^^^^ +... +LL | fn little() { fn_body!(); } + | ---------- in this macro invocation | - = help: use `to_be_bytes` instead + = help: use the native endianness instead + = note: this error originates in the macro `fn_body` (in Nightly builds, run with -Z macro-backtrace for more info) -error: use of the method `to_le_bytes` - --> $DIR/endian_bytes.rs:46:5 +error: usage of the method `to_le_bytes` + --> $DIR/endian_bytes.rs:45:9 | -LL | 2i128.to_le_bytes(); - | ^^^^^^^^^^^^^^^^^^^ +LL | 2i128.to_le_bytes(); + | ^^^^^^^^^^^^^^^^^^^ +... +LL | fn little() { fn_body!(); } + | ---------- in this macro invocation | - = help: use `to_be_bytes` instead + = help: use the native endianness instead + = note: this error originates in the macro `fn_body` (in Nightly builds, run with -Z macro-backtrace for more info) -error: use of the method `to_le_bytes` - --> $DIR/endian_bytes.rs:47:5 +error: usage of the method `to_le_bytes` + --> $DIR/endian_bytes.rs:46:9 | -LL | 2usize.to_le_bytes(); - | ^^^^^^^^^^^^^^^^^^^^ +LL | 2.0f32.to_le_bytes(); + | ^^^^^^^^^^^^^^^^^^^^ +... +LL | fn little() { fn_body!(); } + | ---------- in this macro invocation | - = help: use `to_be_bytes` instead + = help: use the native endianness instead + = note: this error originates in the macro `fn_body` (in Nightly builds, run with -Z macro-backtrace for more info) -error: use of the method `to_le_bytes` - --> $DIR/endian_bytes.rs:48:5 +error: usage of the method `to_le_bytes` + --> $DIR/endian_bytes.rs:47:9 | -LL | 2isize.to_le_bytes(); - | ^^^^^^^^^^^^^^^^^^^^ +LL | 2.0f64.to_le_bytes(); + | ^^^^^^^^^^^^^^^^^^^^ +... +LL | fn little() { fn_body!(); } + | ---------- in this macro invocation | - = help: use `to_be_bytes` instead + = help: use the native endianness instead + = note: this error originates in the macro `fn_body` (in Nightly builds, run with -Z macro-backtrace for more info) -error: use of the method `to_le_bytes` - --> $DIR/endian_bytes.rs:49:5 +error: usage of the method `to_le_bytes` + --> $DIR/endian_bytes.rs:48:9 | -LL | 2.0f32.to_le_bytes(); - | ^^^^^^^^^^^^^^^^^^^^ +LL | 2usize.to_le_bytes(); + | ^^^^^^^^^^^^^^^^^^^^ +... +LL | fn little() { fn_body!(); } + | ---------- in this macro invocation | - = help: use `to_be_bytes` instead + = help: use the native endianness instead + = note: this error originates in the macro `fn_body` (in Nightly builds, run with -Z macro-backtrace for more info) -error: use of the method `to_le_bytes` - --> $DIR/endian_bytes.rs:50:5 +error: usage of the method `to_le_bytes` + --> $DIR/endian_bytes.rs:49:9 | -LL | 2.0f64.to_le_bytes(); - | ^^^^^^^^^^^^^^^^^^^^ +LL | 2isize.to_le_bytes(); + | ^^^^^^^^^^^^^^^^^^^^ +... +LL | fn little() { fn_body!(); } + | ---------- in this macro invocation | - = help: use `to_be_bytes` instead + = help: use the native endianness instead + = note: this error originates in the macro `fn_body` (in Nightly builds, run with -Z macro-backtrace for more info) -error: use of the method `to_be_bytes` - --> $DIR/endian_bytes.rs:69:5 +error: usage of the method `from_le_bytes` + --> $DIR/endian_bytes.rs:50:9 | -LL | 2u8.to_be_bytes(); - | ^^^^^^^^^^^^^^^^^ +LL | u8::from_le_bytes(todo!()); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ +... +LL | fn little() { fn_body!(); } + | ---------- in this macro invocation + | + = help: use the native endianness instead + = note: this error originates in the macro `fn_body` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: usage of the method `from_le_bytes` + --> $DIR/endian_bytes.rs:51:9 + | +LL | i8::from_le_bytes(todo!()); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ +... +LL | fn little() { fn_body!(); } + | ---------- in this macro invocation + | + = help: use the native endianness instead + = note: this error originates in the macro `fn_body` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: usage of the method `from_le_bytes` + --> $DIR/endian_bytes.rs:52:9 + | +LL | u16::from_le_bytes(todo!()); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ +... +LL | fn little() { fn_body!(); } + | ---------- in this macro invocation + | + = help: use the native endianness instead + = note: this error originates in the macro `fn_body` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: usage of the method `from_le_bytes` + --> $DIR/endian_bytes.rs:53:9 + | +LL | i16::from_le_bytes(todo!()); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ +... +LL | fn little() { fn_body!(); } + | ---------- in this macro invocation + | + = help: use the native endianness instead + = note: this error originates in the macro `fn_body` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: usage of the method `from_le_bytes` + --> $DIR/endian_bytes.rs:54:9 + | +LL | u32::from_le_bytes(todo!()); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ +... +LL | fn little() { fn_body!(); } + | ---------- in this macro invocation + | + = help: use the native endianness instead + = note: this error originates in the macro `fn_body` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: usage of the method `from_le_bytes` + --> $DIR/endian_bytes.rs:55:9 + | +LL | i32::from_le_bytes(todo!()); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ +... +LL | fn little() { fn_body!(); } + | ---------- in this macro invocation + | + = help: use the native endianness instead + = note: this error originates in the macro `fn_body` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: usage of the method `from_le_bytes` + --> $DIR/endian_bytes.rs:56:9 + | +LL | u64::from_le_bytes(todo!()); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ +... +LL | fn little() { fn_body!(); } + | ---------- in this macro invocation + | + = help: use the native endianness instead + = note: this error originates in the macro `fn_body` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: usage of the method `from_le_bytes` + --> $DIR/endian_bytes.rs:57:9 + | +LL | i64::from_le_bytes(todo!()); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ +... +LL | fn little() { fn_body!(); } + | ---------- in this macro invocation + | + = help: use the native endianness instead + = note: this error originates in the macro `fn_body` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: usage of the method `from_le_bytes` + --> $DIR/endian_bytes.rs:58:9 + | +LL | u128::from_le_bytes(todo!()); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +... +LL | fn little() { fn_body!(); } + | ---------- in this macro invocation + | + = help: use the native endianness instead + = note: this error originates in the macro `fn_body` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: usage of the method `from_le_bytes` + --> $DIR/endian_bytes.rs:59:9 + | +LL | i128::from_le_bytes(todo!()); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +... +LL | fn little() { fn_body!(); } + | ---------- in this macro invocation + | + = help: use the native endianness instead + = note: this error originates in the macro `fn_body` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: usage of the method `from_le_bytes` + --> $DIR/endian_bytes.rs:60:9 + | +LL | usize::from_le_bytes(todo!()); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +... +LL | fn little() { fn_body!(); } + | ---------- in this macro invocation + | + = help: use the native endianness instead + = note: this error originates in the macro `fn_body` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: usage of the method `from_le_bytes` + --> $DIR/endian_bytes.rs:61:9 + | +LL | isize::from_le_bytes(todo!()); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +... +LL | fn little() { fn_body!(); } + | ---------- in this macro invocation + | + = help: use the native endianness instead + = note: this error originates in the macro `fn_body` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: usage of the method `from_le_bytes` + --> $DIR/endian_bytes.rs:62:9 + | +LL | f32::from_le_bytes(todo!()); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ +... +LL | fn little() { fn_body!(); } + | ---------- in this macro invocation + | + = help: use the native endianness instead + = note: this error originates in the macro `fn_body` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: usage of the method `from_le_bytes` + --> $DIR/endian_bytes.rs:63:9 + | +LL | f64::from_le_bytes(todo!()); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ +... +LL | fn little() { fn_body!(); } + | ---------- in this macro invocation + | + = help: use the native endianness instead + = note: this error originates in the macro `fn_body` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: usage of the method `to_ne_bytes` + --> $DIR/endian_bytes.rs:70:9 + | +LL | 2u8.to_ne_bytes(); + | ^^^^^^^^^^^^^^^^^ +... +LL | fn host_encourage_little() { fn_body_small!(); } + | ---------------- in this macro invocation + | + = help: use `to_le_bytes` instead + = note: this error originates in the macro `fn_body_small` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: usage of the method `from_ne_bytes` + --> $DIR/endian_bytes.rs:71:9 + | +LL | u8::from_ne_bytes(todo!()); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ +... +LL | fn host_encourage_little() { fn_body_small!(); } + | ---------------- in this macro invocation + | + = help: use `from_le_bytes` instead + = note: this error originates in the macro `fn_body_small` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: usage of the method `to_be_bytes` + --> $DIR/endian_bytes.rs:76:9 + | +LL | 2u8.to_be_bytes(); + | ^^^^^^^^^^^^^^^^^ +... +LL | fn host_encourage_little() { fn_body_small!(); } + | ---------------- in this macro invocation | = help: use `to_le_bytes` instead = note: `-D clippy::big-endian-bytes` implied by `-D warnings` + = note: this error originates in the macro `fn_body_small` (in Nightly builds, run with -Z macro-backtrace for more info) -error: use of the method `to_be_bytes` - --> $DIR/endian_bytes.rs:70:5 +error: usage of the method `from_be_bytes` + --> $DIR/endian_bytes.rs:77:9 | -LL | 2i8.to_be_bytes(); - | ^^^^^^^^^^^^^^^^^ +LL | u8::from_be_bytes(todo!()); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ +... +LL | fn host_encourage_little() { fn_body_small!(); } + | ---------------- in this macro invocation + | + = help: use `from_le_bytes` instead + = note: this error originates in the macro `fn_body_small` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: usage of the method `to_ne_bytes` + --> $DIR/endian_bytes.rs:70:9 + | +LL | 2u8.to_ne_bytes(); + | ^^^^^^^^^^^^^^^^^ +... +LL | fn host_encourage_big() { fn_body_small!(); } + | ---------------- in this macro invocation + | + = help: use `to_be_bytes` instead + = note: this error originates in the macro `fn_body_small` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: usage of the method `from_ne_bytes` + --> $DIR/endian_bytes.rs:71:9 + | +LL | u8::from_ne_bytes(todo!()); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ +... +LL | fn host_encourage_big() { fn_body_small!(); } + | ---------------- in this macro invocation + | + = help: use `from_be_bytes` instead + = note: this error originates in the macro `fn_body_small` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: usage of the method `to_le_bytes` + --> $DIR/endian_bytes.rs:73:9 + | +LL | 2u8.to_le_bytes(); + | ^^^^^^^^^^^^^^^^^ +... +LL | fn host_encourage_big() { fn_body_small!(); } + | ---------------- in this macro invocation + | + = help: use `to_be_bytes` instead + = note: this error originates in the macro `fn_body_small` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: usage of the method `from_le_bytes` + --> $DIR/endian_bytes.rs:74:9 + | +LL | u8::from_le_bytes(todo!()); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ +... +LL | fn host_encourage_big() { fn_body_small!(); } + | ---------------- in this macro invocation + | + = help: use `from_be_bytes` instead + = note: this error originates in the macro `fn_body_small` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: usage of the method `to_ne_bytes` + --> $DIR/endian_bytes.rs:70:9 + | +LL | 2u8.to_ne_bytes(); + | ^^^^^^^^^^^^^^^^^ +... +LL | fn no_help() { fn_body_small!(); } + | ---------------- in this macro invocation + | + = note: this error originates in the macro `fn_body_small` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: usage of the method `from_ne_bytes` + --> $DIR/endian_bytes.rs:71:9 + | +LL | u8::from_ne_bytes(todo!()); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ +... +LL | fn no_help() { fn_body_small!(); } + | ---------------- in this macro invocation + | + = note: this error originates in the macro `fn_body_small` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: usage of the method `to_le_bytes` + --> $DIR/endian_bytes.rs:73:9 + | +LL | 2u8.to_le_bytes(); + | ^^^^^^^^^^^^^^^^^ +... +LL | fn no_help() { fn_body_small!(); } + | ---------------- in this macro invocation + | + = note: this error originates in the macro `fn_body_small` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: usage of the method `from_le_bytes` + --> $DIR/endian_bytes.rs:74:9 + | +LL | u8::from_le_bytes(todo!()); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ +... +LL | fn no_help() { fn_body_small!(); } + | ---------------- in this macro invocation + | + = note: this error originates in the macro `fn_body_small` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: usage of the method `to_be_bytes` + --> $DIR/endian_bytes.rs:76:9 + | +LL | 2u8.to_be_bytes(); + | ^^^^^^^^^^^^^^^^^ +... +LL | fn no_help() { fn_body_small!(); } + | ---------------- in this macro invocation + | + = note: this error originates in the macro `fn_body_small` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: usage of the method `from_be_bytes` + --> $DIR/endian_bytes.rs:77:9 + | +LL | u8::from_be_bytes(todo!()); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ +... +LL | fn no_help() { fn_body_small!(); } + | ---------------- in this macro invocation + | + = note: this error originates in the macro `fn_body_small` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: usage of the method `to_le_bytes` + --> $DIR/endian_bytes.rs:73:9 + | +LL | 2u8.to_le_bytes(); + | ^^^^^^^^^^^^^^^^^ +... +LL | fn little_encourage_host() { fn_body_small!(); } + | ---------------- in this macro invocation + | + = help: use the native endianness instead + = note: this error originates in the macro `fn_body_small` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: usage of the method `from_le_bytes` + --> $DIR/endian_bytes.rs:74:9 + | +LL | u8::from_le_bytes(todo!()); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ +... +LL | fn little_encourage_host() { fn_body_small!(); } + | ---------------- in this macro invocation + | + = help: use the native endianness instead + = note: this error originates in the macro `fn_body_small` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: usage of the method `to_be_bytes` + --> $DIR/endian_bytes.rs:76:9 + | +LL | 2u8.to_be_bytes(); + | ^^^^^^^^^^^^^^^^^ +... +LL | fn little_encourage_host() { fn_body_small!(); } + | ---------------- in this macro invocation + | + = help: use the native endianness instead + = note: this error originates in the macro `fn_body_small` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: usage of the method `from_be_bytes` + --> $DIR/endian_bytes.rs:77:9 + | +LL | u8::from_be_bytes(todo!()); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ +... +LL | fn little_encourage_host() { fn_body_small!(); } + | ---------------- in this macro invocation + | + = help: use the native endianness instead + = note: this error originates in the macro `fn_body_small` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: usage of the method `to_ne_bytes` + --> $DIR/endian_bytes.rs:70:9 + | +LL | 2u8.to_ne_bytes(); + | ^^^^^^^^^^^^^^^^^ +... +LL | fn little_encourage_big() { fn_body_small!(); } + | ---------------- in this macro invocation + | + = help: use `to_be_bytes` instead + = note: this error originates in the macro `fn_body_small` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: usage of the method `from_ne_bytes` + --> $DIR/endian_bytes.rs:71:9 + | +LL | u8::from_ne_bytes(todo!()); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ +... +LL | fn little_encourage_big() { fn_body_small!(); } + | ---------------- in this macro invocation + | + = help: use `from_be_bytes` instead + = note: this error originates in the macro `fn_body_small` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: usage of the method `to_le_bytes` + --> $DIR/endian_bytes.rs:73:9 + | +LL | 2u8.to_le_bytes(); + | ^^^^^^^^^^^^^^^^^ +... +LL | fn little_encourage_big() { fn_body_small!(); } + | ---------------- in this macro invocation + | + = help: use `to_be_bytes` instead + = note: this error originates in the macro `fn_body_small` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: usage of the method `from_le_bytes` + --> $DIR/endian_bytes.rs:74:9 + | +LL | u8::from_le_bytes(todo!()); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ +... +LL | fn little_encourage_big() { fn_body_small!(); } + | ---------------- in this macro invocation + | + = help: use `from_be_bytes` instead + = note: this error originates in the macro `fn_body_small` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: usage of the method `to_le_bytes` + --> $DIR/endian_bytes.rs:73:9 + | +LL | 2u8.to_le_bytes(); + | ^^^^^^^^^^^^^^^^^ +... +LL | fn big_encourage_host() { fn_body_small!(); } + | ---------------- in this macro invocation + | + = help: use the native endianness instead + = note: this error originates in the macro `fn_body_small` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: usage of the method `from_le_bytes` + --> $DIR/endian_bytes.rs:74:9 + | +LL | u8::from_le_bytes(todo!()); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ +... +LL | fn big_encourage_host() { fn_body_small!(); } + | ---------------- in this macro invocation + | + = help: use the native endianness instead + = note: this error originates in the macro `fn_body_small` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: usage of the method `to_be_bytes` + --> $DIR/endian_bytes.rs:76:9 + | +LL | 2u8.to_be_bytes(); + | ^^^^^^^^^^^^^^^^^ +... +LL | fn big_encourage_host() { fn_body_small!(); } + | ---------------- in this macro invocation + | + = help: use the native endianness instead + = note: this error originates in the macro `fn_body_small` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: usage of the method `from_be_bytes` + --> $DIR/endian_bytes.rs:77:9 + | +LL | u8::from_be_bytes(todo!()); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ +... +LL | fn big_encourage_host() { fn_body_small!(); } + | ---------------- in this macro invocation + | + = help: use the native endianness instead + = note: this error originates in the macro `fn_body_small` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: usage of the method `to_ne_bytes` + --> $DIR/endian_bytes.rs:70:9 + | +LL | 2u8.to_ne_bytes(); + | ^^^^^^^^^^^^^^^^^ +... +LL | fn big_encourage_little() { fn_body_small!(); } + | ---------------- in this macro invocation | = help: use `to_le_bytes` instead + = note: this error originates in the macro `fn_body_small` (in Nightly builds, run with -Z macro-backtrace for more info) -error: use of the method `to_be_bytes` - --> $DIR/endian_bytes.rs:71:5 +error: usage of the method `from_ne_bytes` + --> $DIR/endian_bytes.rs:71:9 | -LL | 2u16.to_be_bytes(); - | ^^^^^^^^^^^^^^^^^^ +LL | u8::from_ne_bytes(todo!()); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ +... +LL | fn big_encourage_little() { fn_body_small!(); } + | ---------------- in this macro invocation + | + = help: use `from_le_bytes` instead + = note: this error originates in the macro `fn_body_small` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: usage of the method `to_be_bytes` + --> $DIR/endian_bytes.rs:76:9 + | +LL | 2u8.to_be_bytes(); + | ^^^^^^^^^^^^^^^^^ +... +LL | fn big_encourage_little() { fn_body_small!(); } + | ---------------- in this macro invocation | = help: use `to_le_bytes` instead + = note: this error originates in the macro `fn_body_small` (in Nightly builds, run with -Z macro-backtrace for more info) -error: use of the method `to_be_bytes` - --> $DIR/endian_bytes.rs:72:5 +error: usage of the method `from_be_bytes` + --> $DIR/endian_bytes.rs:77:9 | -LL | 2i16.to_be_bytes(); - | ^^^^^^^^^^^^^^^^^^ +LL | u8::from_be_bytes(todo!()); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ +... +LL | fn big_encourage_little() { fn_body_small!(); } + | ---------------- in this macro invocation | - = help: use `to_le_bytes` instead + = help: use `from_le_bytes` instead + = note: this error originates in the macro `fn_body_small` (in Nightly builds, run with -Z macro-backtrace for more info) -error: use of the method `to_be_bytes` - --> $DIR/endian_bytes.rs:73:5 - | -LL | 2u32.to_be_bytes(); - | ^^^^^^^^^^^^^^^^^^ - | - = help: use `to_le_bytes` instead - -error: use of the method `to_be_bytes` - --> $DIR/endian_bytes.rs:74:5 - | -LL | 2i32.to_be_bytes(); - | ^^^^^^^^^^^^^^^^^^ - | - = help: use `to_le_bytes` instead - -error: use of the method `to_be_bytes` - --> $DIR/endian_bytes.rs:75:5 - | -LL | 2u64.to_be_bytes(); - | ^^^^^^^^^^^^^^^^^^ - | - = help: use `to_le_bytes` instead - -error: use of the method `to_be_bytes` - --> $DIR/endian_bytes.rs:76:5 - | -LL | 2i64.to_be_bytes(); - | ^^^^^^^^^^^^^^^^^^ - | - = help: use `to_le_bytes` instead - -error: use of the method `to_be_bytes` - --> $DIR/endian_bytes.rs:77:5 - | -LL | 2u128.to_be_bytes(); - | ^^^^^^^^^^^^^^^^^^^ - | - = help: use `to_le_bytes` instead - -error: use of the method `to_be_bytes` - --> $DIR/endian_bytes.rs:78:5 - | -LL | 2i128.to_be_bytes(); - | ^^^^^^^^^^^^^^^^^^^ - | - = help: use `to_le_bytes` instead - -error: use of the method `to_be_bytes` - --> $DIR/endian_bytes.rs:79:5 - | -LL | 2.0f32.to_be_bytes(); - | ^^^^^^^^^^^^^^^^^^^^ - | - = help: use `to_le_bytes` instead - -error: use of the method `to_be_bytes` - --> $DIR/endian_bytes.rs:80:5 - | -LL | 2.0f64.to_be_bytes(); - | ^^^^^^^^^^^^^^^^^^^^ - | - = help: use `to_le_bytes` instead - -error: use of the method `to_be_bytes` - --> $DIR/endian_bytes.rs:81:5 - | -LL | 2usize.to_be_bytes(); - | ^^^^^^^^^^^^^^^^^^^^ - | - = help: use `to_le_bytes` instead - -error: use of the method `to_be_bytes` - --> $DIR/endian_bytes.rs:82:5 - | -LL | 2isize.to_be_bytes(); - | ^^^^^^^^^^^^^^^^^^^^ - | - = help: use `to_le_bytes` instead - -error: use of the method `to_le_bytes` - --> $DIR/endian_bytes.rs:102:5 - | -LL | 2u8.to_le_bytes(); - | ^^^^^^^^^^^^^^^^^ - -error: use of the method `to_le_bytes` - --> $DIR/endian_bytes.rs:103:5 - | -LL | 2i8.to_le_bytes(); - | ^^^^^^^^^^^^^^^^^ - -error: use of the method `to_le_bytes` - --> $DIR/endian_bytes.rs:104:5 - | -LL | 2u16.to_le_bytes(); - | ^^^^^^^^^^^^^^^^^^ - -error: use of the method `to_le_bytes` - --> $DIR/endian_bytes.rs:105:5 - | -LL | 2i16.to_le_bytes(); - | ^^^^^^^^^^^^^^^^^^ - -error: use of the method `to_le_bytes` - --> $DIR/endian_bytes.rs:106:5 - | -LL | 2u32.to_le_bytes(); - | ^^^^^^^^^^^^^^^^^^ - -error: use of the method `to_le_bytes` - --> $DIR/endian_bytes.rs:107:5 - | -LL | 2i32.to_le_bytes(); - | ^^^^^^^^^^^^^^^^^^ - -error: use of the method `to_le_bytes` - --> $DIR/endian_bytes.rs:108:5 - | -LL | 2u64.to_le_bytes(); - | ^^^^^^^^^^^^^^^^^^ - -error: use of the method `to_le_bytes` - --> $DIR/endian_bytes.rs:109:5 - | -LL | 2i64.to_le_bytes(); - | ^^^^^^^^^^^^^^^^^^ - -error: use of the method `to_le_bytes` - --> $DIR/endian_bytes.rs:110:5 - | -LL | 2u128.to_le_bytes(); - | ^^^^^^^^^^^^^^^^^^^ - -error: use of the method `to_le_bytes` - --> $DIR/endian_bytes.rs:111:5 - | -LL | 2i128.to_le_bytes(); - | ^^^^^^^^^^^^^^^^^^^ - -error: use of the method `to_le_bytes` - --> $DIR/endian_bytes.rs:112:5 - | -LL | 2usize.to_le_bytes(); - | ^^^^^^^^^^^^^^^^^^^^ - -error: use of the method `to_le_bytes` - --> $DIR/endian_bytes.rs:113:5 - | -LL | 2isize.to_le_bytes(); - | ^^^^^^^^^^^^^^^^^^^^ - -error: use of the method `to_le_bytes` - --> $DIR/endian_bytes.rs:114:5 - | -LL | 2.0f32.to_le_bytes(); - | ^^^^^^^^^^^^^^^^^^^^ - -error: use of the method `to_le_bytes` - --> $DIR/endian_bytes.rs:115:5 - | -LL | 2.0f64.to_le_bytes(); - | ^^^^^^^^^^^^^^^^^^^^ - -error: use of the method `to_be_bytes` - --> $DIR/endian_bytes.rs:135:5 - | -LL | 2u8.to_be_bytes(); - | ^^^^^^^^^^^^^^^^^ - -error: use of the method `to_be_bytes` - --> $DIR/endian_bytes.rs:136:5 - | -LL | 2i8.to_be_bytes(); - | ^^^^^^^^^^^^^^^^^ - -error: use of the method `to_be_bytes` - --> $DIR/endian_bytes.rs:137:5 - | -LL | 2u16.to_be_bytes(); - | ^^^^^^^^^^^^^^^^^^ - -error: use of the method `to_be_bytes` - --> $DIR/endian_bytes.rs:138:5 - | -LL | 2i16.to_be_bytes(); - | ^^^^^^^^^^^^^^^^^^ - -error: use of the method `to_be_bytes` - --> $DIR/endian_bytes.rs:139:5 - | -LL | 2u32.to_be_bytes(); - | ^^^^^^^^^^^^^^^^^^ - -error: use of the method `to_be_bytes` - --> $DIR/endian_bytes.rs:140:5 - | -LL | 2i32.to_be_bytes(); - | ^^^^^^^^^^^^^^^^^^ - -error: use of the method `to_be_bytes` - --> $DIR/endian_bytes.rs:141:5 - | -LL | 2u64.to_be_bytes(); - | ^^^^^^^^^^^^^^^^^^ - -error: use of the method `to_be_bytes` - --> $DIR/endian_bytes.rs:142:5 - | -LL | 2i64.to_be_bytes(); - | ^^^^^^^^^^^^^^^^^^ - -error: use of the method `to_be_bytes` - --> $DIR/endian_bytes.rs:143:5 - | -LL | 2u128.to_be_bytes(); - | ^^^^^^^^^^^^^^^^^^^ - -error: use of the method `to_be_bytes` - --> $DIR/endian_bytes.rs:144:5 - | -LL | 2i128.to_be_bytes(); - | ^^^^^^^^^^^^^^^^^^^ - -error: use of the method `to_be_bytes` - --> $DIR/endian_bytes.rs:145:5 - | -LL | 2usize.to_be_bytes(); - | ^^^^^^^^^^^^^^^^^^^^ - -error: use of the method `to_be_bytes` - --> $DIR/endian_bytes.rs:146:5 - | -LL | 2isize.to_be_bytes(); - | ^^^^^^^^^^^^^^^^^^^^ - -error: use of the method `to_be_bytes` - --> $DIR/endian_bytes.rs:147:5 - | -LL | 2.0f32.to_be_bytes(); - | ^^^^^^^^^^^^^^^^^^^^ - -error: use of the method `to_be_bytes` - --> $DIR/endian_bytes.rs:148:5 - | -LL | 2.0f64.to_be_bytes(); - | ^^^^^^^^^^^^^^^^^^^^ - -error: aborting due to 145 previous errors +error: aborting due to 86 previous errors From 48d36a7aa3d8281352ac70c240d98c18b0a9adfa Mon Sep 17 00:00:00 2001 From: Catherine <114838443+Centri3@users.noreply.github.com> Date: Thu, 25 May 2023 11:15:30 -0500 Subject: [PATCH 025/310] weird grammar --- clippy_lints/src/endian_bytes.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/clippy_lints/src/endian_bytes.rs b/clippy_lints/src/endian_bytes.rs index 6486430cf57..88e0d4dcd53 100644 --- a/clippy_lints/src/endian_bytes.rs +++ b/clippy_lints/src/endian_bytes.rs @@ -30,7 +30,7 @@ declare_clippy_lint! { /// Checks for the usage of the `to_le_bytes` method. /// /// ### Why is this bad? - /// It's not, but some may wish to lint usages of this method, either to suggest using the host + /// It's not, but some may wish to lint usage of this method, either to suggest using the host /// endianness or big endian. /// /// ### Example @@ -49,7 +49,7 @@ declare_clippy_lint! { /// Checks for the usage of the `to_be_bytes` method. /// /// ### Why is this bad? - /// It's not, but some may wish to lint usages of this method, either to suggest using the host + /// It's not, but some may wish to lint usage of this method, either to suggest using the host /// endianness or little endian. /// /// ### Example From 04b7cae37ec90237682aaff58e7773ad42d22259 Mon Sep 17 00:00:00 2001 From: Centri3 <114838443+Centri3@users.noreply.github.com> Date: Thu, 25 May 2023 11:29:43 -0500 Subject: [PATCH 026/310] refine output --- clippy_lints/src/endian_bytes.rs | 26 ++- tests/ui/endian_bytes.rs | 16 +- tests/ui/endian_bytes.stderr | 384 +++++++++++++++---------------- 3 files changed, 217 insertions(+), 209 deletions(-) diff --git a/clippy_lints/src/endian_bytes.rs b/clippy_lints/src/endian_bytes.rs index 88e0d4dcd53..434125932c4 100644 --- a/clippy_lints/src/endian_bytes.rs +++ b/clippy_lints/src/endian_bytes.rs @@ -2,7 +2,7 @@ use crate::Lint; use clippy_utils::{diagnostics::span_lint_and_then, is_lint_allowed}; use rustc_hir::{Expr, ExprKind}; use rustc_lint::{LateContext, LateLintPass, LintContext}; -use rustc_middle::lint::in_external_macro; +use rustc_middle::{lint::in_external_macro, ty::Ty}; use rustc_session::{declare_lint_pass, declare_tool_lint}; use rustc_span::Symbol; use std::borrow::Cow; @@ -102,11 +102,13 @@ impl LateLintPass<'_> for EndianBytes { if_chain! { if let ExprKind::MethodCall(method_name, receiver, args, ..) = expr.kind; - if let ExprKind::Lit(..) = receiver.kind; if args.is_empty(); - if try_lint_endian_bytes(cx, expr, "to", method_name.ident.name); + let ty = cx.typeck_results().expr_ty(receiver); + if ty.is_primitive_ty(); then { - return; + if try_lint_endian_bytes(cx, expr, "to", method_name.ident.name, ty) { + return; + } } } @@ -115,15 +117,16 @@ impl LateLintPass<'_> for EndianBytes { if let ExprKind::Path(qpath) = function.kind; if let Some(def_id) = cx.qpath_res(&qpath, function.hir_id).opt_def_id(); if let Some(function_name) = cx.get_def_path(def_id).last(); - if cx.typeck_results().expr_ty(expr).is_primitive_ty(); + let ty = cx.typeck_results().expr_ty(expr); + if ty.is_primitive_ty(); then { - try_lint_endian_bytes(cx, expr, "from", *function_name); + try_lint_endian_bytes(cx, expr, "from", *function_name, ty); } } } } -fn try_lint_endian_bytes(cx: &LateContext<'_>, expr: &Expr<'_>, prefix: &str, name: Symbol) -> bool { +fn try_lint_endian_bytes(cx: &LateContext<'_>, expr: &Expr<'_>, prefix: &str, name: Symbol, ty: Ty<'_>) -> bool { let ne = format!("{prefix}_ne_bytes"); let le = format!("{prefix}_le_bytes"); let be = format!("{prefix}_be_bytes"); @@ -171,7 +174,7 @@ fn try_lint_endian_bytes(cx: &LateContext<'_>, expr: &Expr<'_>, prefix: &str, na help_str.push_str("either of "); } - help_str.push_str(&format!("`{}` ", lint.to_name(prefix))); + help_str.push_str(&format!("`{ty}::{}` ", lint.to_name(prefix))); if i != len && !only_one { help_str.push_str("or "); @@ -185,7 +188,12 @@ fn try_lint_endian_bytes(cx: &LateContext<'_>, expr: &Expr<'_>, prefix: &str, na cx, lint.as_lint(), expr.span, - &format!("usage of the method `{}`", lint.to_name(prefix)), + &format!( + "usage of the {}`{ty}::{}`{}", + if prefix == "from" { "function " } else { "" }, + lint.to_name(prefix), + if prefix == "to" { " method" } else { "" }, + ), move |diag| { if let Some(help) = help { diag.help(help); diff --git a/tests/ui/endian_bytes.rs b/tests/ui/endian_bytes.rs index ccee8e20a3c..6bf014fc809 100644 --- a/tests/ui/endian_bytes.rs +++ b/tests/ui/endian_bytes.rs @@ -65,7 +65,7 @@ macro_rules! fn_body { } // bless breaks if I use fn_body too much (oops) -macro_rules! fn_body_small { +macro_rules! fn_body_smol { () => { 2u8.to_ne_bytes(); u8::from_ne_bytes(todo!()); @@ -93,35 +93,35 @@ fn big() { fn_body!(); } #[rustfmt::skip] #[warn(clippy::host_endian_bytes)] #[warn(clippy::big_endian_bytes)] -fn host_encourage_little() { fn_body_small!(); } +fn host_encourage_little() { fn_body_smol!(); } #[rustfmt::skip] #[warn(clippy::host_endian_bytes)] #[warn(clippy::little_endian_bytes)] -fn host_encourage_big() { fn_body_small!(); } +fn host_encourage_big() { fn_body_smol!(); } #[rustfmt::skip] #[warn(clippy::host_endian_bytes)] #[warn(clippy::little_endian_bytes)] #[warn(clippy::big_endian_bytes)] -fn no_help() { fn_body_small!(); } +fn no_help() { fn_body_smol!(); } #[rustfmt::skip] #[warn(clippy::little_endian_bytes)] #[warn(clippy::big_endian_bytes)] -fn little_encourage_host() { fn_body_small!(); } +fn little_encourage_host() { fn_body_smol!(); } #[rustfmt::skip] #[warn(clippy::host_endian_bytes)] #[warn(clippy::little_endian_bytes)] -fn little_encourage_big() { fn_body_small!(); } +fn little_encourage_big() { fn_body_smol!(); } #[rustfmt::skip] #[warn(clippy::big_endian_bytes)] #[warn(clippy::little_endian_bytes)] -fn big_encourage_host() { fn_body_small!(); } +fn big_encourage_host() { fn_body_smol!(); } #[rustfmt::skip] #[warn(clippy::host_endian_bytes)] #[warn(clippy::big_endian_bytes)] -fn big_encourage_little() { fn_body_small!(); } +fn big_encourage_little() { fn_body_smol!(); } diff --git a/tests/ui/endian_bytes.stderr b/tests/ui/endian_bytes.stderr index ff8d1a98f4f..5e64ea5b5ab 100644 --- a/tests/ui/endian_bytes.stderr +++ b/tests/ui/endian_bytes.stderr @@ -1,4 +1,4 @@ -error: usage of the method `to_ne_bytes` +error: usage of the `u8::to_ne_bytes` method --> $DIR/endian_bytes.rs:7:9 | LL | 2u8.to_ne_bytes(); @@ -11,7 +11,7 @@ LL | fn host() { fn_body!(); } = note: `-D clippy::host-endian-bytes` implied by `-D warnings` = note: this error originates in the macro `fn_body` (in Nightly builds, run with -Z macro-backtrace for more info) -error: usage of the method `to_ne_bytes` +error: usage of the `i8::to_ne_bytes` method --> $DIR/endian_bytes.rs:8:9 | LL | 2i8.to_ne_bytes(); @@ -23,7 +23,7 @@ LL | fn host() { fn_body!(); } = help: specify the desired endianness explicitly = note: this error originates in the macro `fn_body` (in Nightly builds, run with -Z macro-backtrace for more info) -error: usage of the method `to_ne_bytes` +error: usage of the `u16::to_ne_bytes` method --> $DIR/endian_bytes.rs:9:9 | LL | 2u16.to_ne_bytes(); @@ -35,7 +35,7 @@ LL | fn host() { fn_body!(); } = help: specify the desired endianness explicitly = note: this error originates in the macro `fn_body` (in Nightly builds, run with -Z macro-backtrace for more info) -error: usage of the method `to_ne_bytes` +error: usage of the `i16::to_ne_bytes` method --> $DIR/endian_bytes.rs:10:9 | LL | 2i16.to_ne_bytes(); @@ -47,7 +47,7 @@ LL | fn host() { fn_body!(); } = help: specify the desired endianness explicitly = note: this error originates in the macro `fn_body` (in Nightly builds, run with -Z macro-backtrace for more info) -error: usage of the method `to_ne_bytes` +error: usage of the `u32::to_ne_bytes` method --> $DIR/endian_bytes.rs:11:9 | LL | 2u32.to_ne_bytes(); @@ -59,7 +59,7 @@ LL | fn host() { fn_body!(); } = help: specify the desired endianness explicitly = note: this error originates in the macro `fn_body` (in Nightly builds, run with -Z macro-backtrace for more info) -error: usage of the method `to_ne_bytes` +error: usage of the `i32::to_ne_bytes` method --> $DIR/endian_bytes.rs:12:9 | LL | 2i32.to_ne_bytes(); @@ -71,7 +71,7 @@ LL | fn host() { fn_body!(); } = help: specify the desired endianness explicitly = note: this error originates in the macro `fn_body` (in Nightly builds, run with -Z macro-backtrace for more info) -error: usage of the method `to_ne_bytes` +error: usage of the `u64::to_ne_bytes` method --> $DIR/endian_bytes.rs:13:9 | LL | 2u64.to_ne_bytes(); @@ -83,7 +83,7 @@ LL | fn host() { fn_body!(); } = help: specify the desired endianness explicitly = note: this error originates in the macro `fn_body` (in Nightly builds, run with -Z macro-backtrace for more info) -error: usage of the method `to_ne_bytes` +error: usage of the `i64::to_ne_bytes` method --> $DIR/endian_bytes.rs:14:9 | LL | 2i64.to_ne_bytes(); @@ -95,7 +95,7 @@ LL | fn host() { fn_body!(); } = help: specify the desired endianness explicitly = note: this error originates in the macro `fn_body` (in Nightly builds, run with -Z macro-backtrace for more info) -error: usage of the method `to_ne_bytes` +error: usage of the `u128::to_ne_bytes` method --> $DIR/endian_bytes.rs:15:9 | LL | 2u128.to_ne_bytes(); @@ -107,7 +107,7 @@ LL | fn host() { fn_body!(); } = help: specify the desired endianness explicitly = note: this error originates in the macro `fn_body` (in Nightly builds, run with -Z macro-backtrace for more info) -error: usage of the method `to_ne_bytes` +error: usage of the `i128::to_ne_bytes` method --> $DIR/endian_bytes.rs:16:9 | LL | 2i128.to_ne_bytes(); @@ -119,7 +119,7 @@ LL | fn host() { fn_body!(); } = help: specify the desired endianness explicitly = note: this error originates in the macro `fn_body` (in Nightly builds, run with -Z macro-backtrace for more info) -error: usage of the method `to_ne_bytes` +error: usage of the `f32::to_ne_bytes` method --> $DIR/endian_bytes.rs:17:9 | LL | 2.0f32.to_ne_bytes(); @@ -131,7 +131,7 @@ LL | fn host() { fn_body!(); } = help: specify the desired endianness explicitly = note: this error originates in the macro `fn_body` (in Nightly builds, run with -Z macro-backtrace for more info) -error: usage of the method `to_ne_bytes` +error: usage of the `f64::to_ne_bytes` method --> $DIR/endian_bytes.rs:18:9 | LL | 2.0f64.to_ne_bytes(); @@ -143,7 +143,7 @@ LL | fn host() { fn_body!(); } = help: specify the desired endianness explicitly = note: this error originates in the macro `fn_body` (in Nightly builds, run with -Z macro-backtrace for more info) -error: usage of the method `to_ne_bytes` +error: usage of the `usize::to_ne_bytes` method --> $DIR/endian_bytes.rs:19:9 | LL | 2usize.to_ne_bytes(); @@ -155,7 +155,7 @@ LL | fn host() { fn_body!(); } = help: specify the desired endianness explicitly = note: this error originates in the macro `fn_body` (in Nightly builds, run with -Z macro-backtrace for more info) -error: usage of the method `to_ne_bytes` +error: usage of the `isize::to_ne_bytes` method --> $DIR/endian_bytes.rs:20:9 | LL | 2isize.to_ne_bytes(); @@ -167,7 +167,7 @@ LL | fn host() { fn_body!(); } = help: specify the desired endianness explicitly = note: this error originates in the macro `fn_body` (in Nightly builds, run with -Z macro-backtrace for more info) -error: usage of the method `from_ne_bytes` +error: usage of the function `u8::from_ne_bytes` --> $DIR/endian_bytes.rs:21:9 | LL | u8::from_ne_bytes(todo!()); @@ -179,7 +179,7 @@ LL | fn host() { fn_body!(); } = help: specify the desired endianness explicitly = note: this error originates in the macro `fn_body` (in Nightly builds, run with -Z macro-backtrace for more info) -error: usage of the method `from_ne_bytes` +error: usage of the function `i8::from_ne_bytes` --> $DIR/endian_bytes.rs:22:9 | LL | i8::from_ne_bytes(todo!()); @@ -191,7 +191,7 @@ LL | fn host() { fn_body!(); } = help: specify the desired endianness explicitly = note: this error originates in the macro `fn_body` (in Nightly builds, run with -Z macro-backtrace for more info) -error: usage of the method `from_ne_bytes` +error: usage of the function `u16::from_ne_bytes` --> $DIR/endian_bytes.rs:23:9 | LL | u16::from_ne_bytes(todo!()); @@ -203,7 +203,7 @@ LL | fn host() { fn_body!(); } = help: specify the desired endianness explicitly = note: this error originates in the macro `fn_body` (in Nightly builds, run with -Z macro-backtrace for more info) -error: usage of the method `from_ne_bytes` +error: usage of the function `i16::from_ne_bytes` --> $DIR/endian_bytes.rs:24:9 | LL | i16::from_ne_bytes(todo!()); @@ -215,7 +215,7 @@ LL | fn host() { fn_body!(); } = help: specify the desired endianness explicitly = note: this error originates in the macro `fn_body` (in Nightly builds, run with -Z macro-backtrace for more info) -error: usage of the method `from_ne_bytes` +error: usage of the function `u32::from_ne_bytes` --> $DIR/endian_bytes.rs:25:9 | LL | u32::from_ne_bytes(todo!()); @@ -227,7 +227,7 @@ LL | fn host() { fn_body!(); } = help: specify the desired endianness explicitly = note: this error originates in the macro `fn_body` (in Nightly builds, run with -Z macro-backtrace for more info) -error: usage of the method `from_ne_bytes` +error: usage of the function `i32::from_ne_bytes` --> $DIR/endian_bytes.rs:26:9 | LL | i32::from_ne_bytes(todo!()); @@ -239,7 +239,7 @@ LL | fn host() { fn_body!(); } = help: specify the desired endianness explicitly = note: this error originates in the macro `fn_body` (in Nightly builds, run with -Z macro-backtrace for more info) -error: usage of the method `from_ne_bytes` +error: usage of the function `u64::from_ne_bytes` --> $DIR/endian_bytes.rs:27:9 | LL | u64::from_ne_bytes(todo!()); @@ -251,7 +251,7 @@ LL | fn host() { fn_body!(); } = help: specify the desired endianness explicitly = note: this error originates in the macro `fn_body` (in Nightly builds, run with -Z macro-backtrace for more info) -error: usage of the method `from_ne_bytes` +error: usage of the function `i64::from_ne_bytes` --> $DIR/endian_bytes.rs:28:9 | LL | i64::from_ne_bytes(todo!()); @@ -263,7 +263,7 @@ LL | fn host() { fn_body!(); } = help: specify the desired endianness explicitly = note: this error originates in the macro `fn_body` (in Nightly builds, run with -Z macro-backtrace for more info) -error: usage of the method `from_ne_bytes` +error: usage of the function `u128::from_ne_bytes` --> $DIR/endian_bytes.rs:29:9 | LL | u128::from_ne_bytes(todo!()); @@ -275,7 +275,7 @@ LL | fn host() { fn_body!(); } = help: specify the desired endianness explicitly = note: this error originates in the macro `fn_body` (in Nightly builds, run with -Z macro-backtrace for more info) -error: usage of the method `from_ne_bytes` +error: usage of the function `i128::from_ne_bytes` --> $DIR/endian_bytes.rs:30:9 | LL | i128::from_ne_bytes(todo!()); @@ -287,7 +287,7 @@ LL | fn host() { fn_body!(); } = help: specify the desired endianness explicitly = note: this error originates in the macro `fn_body` (in Nightly builds, run with -Z macro-backtrace for more info) -error: usage of the method `from_ne_bytes` +error: usage of the function `usize::from_ne_bytes` --> $DIR/endian_bytes.rs:31:9 | LL | usize::from_ne_bytes(todo!()); @@ -299,7 +299,7 @@ LL | fn host() { fn_body!(); } = help: specify the desired endianness explicitly = note: this error originates in the macro `fn_body` (in Nightly builds, run with -Z macro-backtrace for more info) -error: usage of the method `from_ne_bytes` +error: usage of the function `isize::from_ne_bytes` --> $DIR/endian_bytes.rs:32:9 | LL | isize::from_ne_bytes(todo!()); @@ -311,7 +311,7 @@ LL | fn host() { fn_body!(); } = help: specify the desired endianness explicitly = note: this error originates in the macro `fn_body` (in Nightly builds, run with -Z macro-backtrace for more info) -error: usage of the method `from_ne_bytes` +error: usage of the function `f32::from_ne_bytes` --> $DIR/endian_bytes.rs:33:9 | LL | f32::from_ne_bytes(todo!()); @@ -323,7 +323,7 @@ LL | fn host() { fn_body!(); } = help: specify the desired endianness explicitly = note: this error originates in the macro `fn_body` (in Nightly builds, run with -Z macro-backtrace for more info) -error: usage of the method `from_ne_bytes` +error: usage of the function `f64::from_ne_bytes` --> $DIR/endian_bytes.rs:34:9 | LL | f64::from_ne_bytes(todo!()); @@ -335,7 +335,7 @@ LL | fn host() { fn_body!(); } = help: specify the desired endianness explicitly = note: this error originates in the macro `fn_body` (in Nightly builds, run with -Z macro-backtrace for more info) -error: usage of the method `to_le_bytes` +error: usage of the `u8::to_le_bytes` method --> $DIR/endian_bytes.rs:36:9 | LL | 2u8.to_le_bytes(); @@ -348,7 +348,7 @@ LL | fn little() { fn_body!(); } = note: `-D clippy::little-endian-bytes` implied by `-D warnings` = note: this error originates in the macro `fn_body` (in Nightly builds, run with -Z macro-backtrace for more info) -error: usage of the method `to_le_bytes` +error: usage of the `i8::to_le_bytes` method --> $DIR/endian_bytes.rs:37:9 | LL | 2i8.to_le_bytes(); @@ -360,7 +360,7 @@ LL | fn little() { fn_body!(); } = help: use the native endianness instead = note: this error originates in the macro `fn_body` (in Nightly builds, run with -Z macro-backtrace for more info) -error: usage of the method `to_le_bytes` +error: usage of the `u16::to_le_bytes` method --> $DIR/endian_bytes.rs:38:9 | LL | 2u16.to_le_bytes(); @@ -372,7 +372,7 @@ LL | fn little() { fn_body!(); } = help: use the native endianness instead = note: this error originates in the macro `fn_body` (in Nightly builds, run with -Z macro-backtrace for more info) -error: usage of the method `to_le_bytes` +error: usage of the `i16::to_le_bytes` method --> $DIR/endian_bytes.rs:39:9 | LL | 2i16.to_le_bytes(); @@ -384,7 +384,7 @@ LL | fn little() { fn_body!(); } = help: use the native endianness instead = note: this error originates in the macro `fn_body` (in Nightly builds, run with -Z macro-backtrace for more info) -error: usage of the method `to_le_bytes` +error: usage of the `u32::to_le_bytes` method --> $DIR/endian_bytes.rs:40:9 | LL | 2u32.to_le_bytes(); @@ -396,7 +396,7 @@ LL | fn little() { fn_body!(); } = help: use the native endianness instead = note: this error originates in the macro `fn_body` (in Nightly builds, run with -Z macro-backtrace for more info) -error: usage of the method `to_le_bytes` +error: usage of the `i32::to_le_bytes` method --> $DIR/endian_bytes.rs:41:9 | LL | 2i32.to_le_bytes(); @@ -408,7 +408,7 @@ LL | fn little() { fn_body!(); } = help: use the native endianness instead = note: this error originates in the macro `fn_body` (in Nightly builds, run with -Z macro-backtrace for more info) -error: usage of the method `to_le_bytes` +error: usage of the `u64::to_le_bytes` method --> $DIR/endian_bytes.rs:42:9 | LL | 2u64.to_le_bytes(); @@ -420,7 +420,7 @@ LL | fn little() { fn_body!(); } = help: use the native endianness instead = note: this error originates in the macro `fn_body` (in Nightly builds, run with -Z macro-backtrace for more info) -error: usage of the method `to_le_bytes` +error: usage of the `i64::to_le_bytes` method --> $DIR/endian_bytes.rs:43:9 | LL | 2i64.to_le_bytes(); @@ -432,7 +432,7 @@ LL | fn little() { fn_body!(); } = help: use the native endianness instead = note: this error originates in the macro `fn_body` (in Nightly builds, run with -Z macro-backtrace for more info) -error: usage of the method `to_le_bytes` +error: usage of the `u128::to_le_bytes` method --> $DIR/endian_bytes.rs:44:9 | LL | 2u128.to_le_bytes(); @@ -444,7 +444,7 @@ LL | fn little() { fn_body!(); } = help: use the native endianness instead = note: this error originates in the macro `fn_body` (in Nightly builds, run with -Z macro-backtrace for more info) -error: usage of the method `to_le_bytes` +error: usage of the `i128::to_le_bytes` method --> $DIR/endian_bytes.rs:45:9 | LL | 2i128.to_le_bytes(); @@ -456,7 +456,7 @@ LL | fn little() { fn_body!(); } = help: use the native endianness instead = note: this error originates in the macro `fn_body` (in Nightly builds, run with -Z macro-backtrace for more info) -error: usage of the method `to_le_bytes` +error: usage of the `f32::to_le_bytes` method --> $DIR/endian_bytes.rs:46:9 | LL | 2.0f32.to_le_bytes(); @@ -468,7 +468,7 @@ LL | fn little() { fn_body!(); } = help: use the native endianness instead = note: this error originates in the macro `fn_body` (in Nightly builds, run with -Z macro-backtrace for more info) -error: usage of the method `to_le_bytes` +error: usage of the `f64::to_le_bytes` method --> $DIR/endian_bytes.rs:47:9 | LL | 2.0f64.to_le_bytes(); @@ -480,7 +480,7 @@ LL | fn little() { fn_body!(); } = help: use the native endianness instead = note: this error originates in the macro `fn_body` (in Nightly builds, run with -Z macro-backtrace for more info) -error: usage of the method `to_le_bytes` +error: usage of the `usize::to_le_bytes` method --> $DIR/endian_bytes.rs:48:9 | LL | 2usize.to_le_bytes(); @@ -492,7 +492,7 @@ LL | fn little() { fn_body!(); } = help: use the native endianness instead = note: this error originates in the macro `fn_body` (in Nightly builds, run with -Z macro-backtrace for more info) -error: usage of the method `to_le_bytes` +error: usage of the `isize::to_le_bytes` method --> $DIR/endian_bytes.rs:49:9 | LL | 2isize.to_le_bytes(); @@ -504,7 +504,7 @@ LL | fn little() { fn_body!(); } = help: use the native endianness instead = note: this error originates in the macro `fn_body` (in Nightly builds, run with -Z macro-backtrace for more info) -error: usage of the method `from_le_bytes` +error: usage of the function `u8::from_le_bytes` --> $DIR/endian_bytes.rs:50:9 | LL | u8::from_le_bytes(todo!()); @@ -516,7 +516,7 @@ LL | fn little() { fn_body!(); } = help: use the native endianness instead = note: this error originates in the macro `fn_body` (in Nightly builds, run with -Z macro-backtrace for more info) -error: usage of the method `from_le_bytes` +error: usage of the function `i8::from_le_bytes` --> $DIR/endian_bytes.rs:51:9 | LL | i8::from_le_bytes(todo!()); @@ -528,7 +528,7 @@ LL | fn little() { fn_body!(); } = help: use the native endianness instead = note: this error originates in the macro `fn_body` (in Nightly builds, run with -Z macro-backtrace for more info) -error: usage of the method `from_le_bytes` +error: usage of the function `u16::from_le_bytes` --> $DIR/endian_bytes.rs:52:9 | LL | u16::from_le_bytes(todo!()); @@ -540,7 +540,7 @@ LL | fn little() { fn_body!(); } = help: use the native endianness instead = note: this error originates in the macro `fn_body` (in Nightly builds, run with -Z macro-backtrace for more info) -error: usage of the method `from_le_bytes` +error: usage of the function `i16::from_le_bytes` --> $DIR/endian_bytes.rs:53:9 | LL | i16::from_le_bytes(todo!()); @@ -552,7 +552,7 @@ LL | fn little() { fn_body!(); } = help: use the native endianness instead = note: this error originates in the macro `fn_body` (in Nightly builds, run with -Z macro-backtrace for more info) -error: usage of the method `from_le_bytes` +error: usage of the function `u32::from_le_bytes` --> $DIR/endian_bytes.rs:54:9 | LL | u32::from_le_bytes(todo!()); @@ -564,7 +564,7 @@ LL | fn little() { fn_body!(); } = help: use the native endianness instead = note: this error originates in the macro `fn_body` (in Nightly builds, run with -Z macro-backtrace for more info) -error: usage of the method `from_le_bytes` +error: usage of the function `i32::from_le_bytes` --> $DIR/endian_bytes.rs:55:9 | LL | i32::from_le_bytes(todo!()); @@ -576,7 +576,7 @@ LL | fn little() { fn_body!(); } = help: use the native endianness instead = note: this error originates in the macro `fn_body` (in Nightly builds, run with -Z macro-backtrace for more info) -error: usage of the method `from_le_bytes` +error: usage of the function `u64::from_le_bytes` --> $DIR/endian_bytes.rs:56:9 | LL | u64::from_le_bytes(todo!()); @@ -588,7 +588,7 @@ LL | fn little() { fn_body!(); } = help: use the native endianness instead = note: this error originates in the macro `fn_body` (in Nightly builds, run with -Z macro-backtrace for more info) -error: usage of the method `from_le_bytes` +error: usage of the function `i64::from_le_bytes` --> $DIR/endian_bytes.rs:57:9 | LL | i64::from_le_bytes(todo!()); @@ -600,7 +600,7 @@ LL | fn little() { fn_body!(); } = help: use the native endianness instead = note: this error originates in the macro `fn_body` (in Nightly builds, run with -Z macro-backtrace for more info) -error: usage of the method `from_le_bytes` +error: usage of the function `u128::from_le_bytes` --> $DIR/endian_bytes.rs:58:9 | LL | u128::from_le_bytes(todo!()); @@ -612,7 +612,7 @@ LL | fn little() { fn_body!(); } = help: use the native endianness instead = note: this error originates in the macro `fn_body` (in Nightly builds, run with -Z macro-backtrace for more info) -error: usage of the method `from_le_bytes` +error: usage of the function `i128::from_le_bytes` --> $DIR/endian_bytes.rs:59:9 | LL | i128::from_le_bytes(todo!()); @@ -624,7 +624,7 @@ LL | fn little() { fn_body!(); } = help: use the native endianness instead = note: this error originates in the macro `fn_body` (in Nightly builds, run with -Z macro-backtrace for more info) -error: usage of the method `from_le_bytes` +error: usage of the function `usize::from_le_bytes` --> $DIR/endian_bytes.rs:60:9 | LL | usize::from_le_bytes(todo!()); @@ -636,7 +636,7 @@ LL | fn little() { fn_body!(); } = help: use the native endianness instead = note: this error originates in the macro `fn_body` (in Nightly builds, run with -Z macro-backtrace for more info) -error: usage of the method `from_le_bytes` +error: usage of the function `isize::from_le_bytes` --> $DIR/endian_bytes.rs:61:9 | LL | isize::from_le_bytes(todo!()); @@ -648,7 +648,7 @@ LL | fn little() { fn_body!(); } = help: use the native endianness instead = note: this error originates in the macro `fn_body` (in Nightly builds, run with -Z macro-backtrace for more info) -error: usage of the method `from_le_bytes` +error: usage of the function `f32::from_le_bytes` --> $DIR/endian_bytes.rs:62:9 | LL | f32::from_le_bytes(todo!()); @@ -660,7 +660,7 @@ LL | fn little() { fn_body!(); } = help: use the native endianness instead = note: this error originates in the macro `fn_body` (in Nightly builds, run with -Z macro-backtrace for more info) -error: usage of the method `from_le_bytes` +error: usage of the function `f64::from_le_bytes` --> $DIR/endian_bytes.rs:63:9 | LL | f64::from_le_bytes(todo!()); @@ -672,360 +672,360 @@ LL | fn little() { fn_body!(); } = help: use the native endianness instead = note: this error originates in the macro `fn_body` (in Nightly builds, run with -Z macro-backtrace for more info) -error: usage of the method `to_ne_bytes` +error: usage of the `u8::to_ne_bytes` method --> $DIR/endian_bytes.rs:70:9 | LL | 2u8.to_ne_bytes(); | ^^^^^^^^^^^^^^^^^ ... -LL | fn host_encourage_little() { fn_body_small!(); } - | ---------------- in this macro invocation +LL | fn host_encourage_little() { fn_body_smol!(); } + | --------------- in this macro invocation | - = help: use `to_le_bytes` instead - = note: this error originates in the macro `fn_body_small` (in Nightly builds, run with -Z macro-backtrace for more info) + = help: use `u8::to_le_bytes` instead + = note: this error originates in the macro `fn_body_smol` (in Nightly builds, run with -Z macro-backtrace for more info) -error: usage of the method `from_ne_bytes` +error: usage of the function `u8::from_ne_bytes` --> $DIR/endian_bytes.rs:71:9 | LL | u8::from_ne_bytes(todo!()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ ... -LL | fn host_encourage_little() { fn_body_small!(); } - | ---------------- in this macro invocation +LL | fn host_encourage_little() { fn_body_smol!(); } + | --------------- in this macro invocation | - = help: use `from_le_bytes` instead - = note: this error originates in the macro `fn_body_small` (in Nightly builds, run with -Z macro-backtrace for more info) + = help: use `u8::from_le_bytes` instead + = note: this error originates in the macro `fn_body_smol` (in Nightly builds, run with -Z macro-backtrace for more info) -error: usage of the method `to_be_bytes` +error: usage of the `u8::to_be_bytes` method --> $DIR/endian_bytes.rs:76:9 | LL | 2u8.to_be_bytes(); | ^^^^^^^^^^^^^^^^^ ... -LL | fn host_encourage_little() { fn_body_small!(); } - | ---------------- in this macro invocation +LL | fn host_encourage_little() { fn_body_smol!(); } + | --------------- in this macro invocation | - = help: use `to_le_bytes` instead + = help: use `u8::to_le_bytes` instead = note: `-D clippy::big-endian-bytes` implied by `-D warnings` - = note: this error originates in the macro `fn_body_small` (in Nightly builds, run with -Z macro-backtrace for more info) + = note: this error originates in the macro `fn_body_smol` (in Nightly builds, run with -Z macro-backtrace for more info) -error: usage of the method `from_be_bytes` +error: usage of the function `u8::from_be_bytes` --> $DIR/endian_bytes.rs:77:9 | LL | u8::from_be_bytes(todo!()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ ... -LL | fn host_encourage_little() { fn_body_small!(); } - | ---------------- in this macro invocation +LL | fn host_encourage_little() { fn_body_smol!(); } + | --------------- in this macro invocation | - = help: use `from_le_bytes` instead - = note: this error originates in the macro `fn_body_small` (in Nightly builds, run with -Z macro-backtrace for more info) + = help: use `u8::from_le_bytes` instead + = note: this error originates in the macro `fn_body_smol` (in Nightly builds, run with -Z macro-backtrace for more info) -error: usage of the method `to_ne_bytes` +error: usage of the `u8::to_ne_bytes` method --> $DIR/endian_bytes.rs:70:9 | LL | 2u8.to_ne_bytes(); | ^^^^^^^^^^^^^^^^^ ... -LL | fn host_encourage_big() { fn_body_small!(); } - | ---------------- in this macro invocation +LL | fn host_encourage_big() { fn_body_smol!(); } + | --------------- in this macro invocation | - = help: use `to_be_bytes` instead - = note: this error originates in the macro `fn_body_small` (in Nightly builds, run with -Z macro-backtrace for more info) + = help: use `u8::to_be_bytes` instead + = note: this error originates in the macro `fn_body_smol` (in Nightly builds, run with -Z macro-backtrace for more info) -error: usage of the method `from_ne_bytes` +error: usage of the function `u8::from_ne_bytes` --> $DIR/endian_bytes.rs:71:9 | LL | u8::from_ne_bytes(todo!()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ ... -LL | fn host_encourage_big() { fn_body_small!(); } - | ---------------- in this macro invocation +LL | fn host_encourage_big() { fn_body_smol!(); } + | --------------- in this macro invocation | - = help: use `from_be_bytes` instead - = note: this error originates in the macro `fn_body_small` (in Nightly builds, run with -Z macro-backtrace for more info) + = help: use `u8::from_be_bytes` instead + = note: this error originates in the macro `fn_body_smol` (in Nightly builds, run with -Z macro-backtrace for more info) -error: usage of the method `to_le_bytes` +error: usage of the `u8::to_le_bytes` method --> $DIR/endian_bytes.rs:73:9 | LL | 2u8.to_le_bytes(); | ^^^^^^^^^^^^^^^^^ ... -LL | fn host_encourage_big() { fn_body_small!(); } - | ---------------- in this macro invocation +LL | fn host_encourage_big() { fn_body_smol!(); } + | --------------- in this macro invocation | - = help: use `to_be_bytes` instead - = note: this error originates in the macro `fn_body_small` (in Nightly builds, run with -Z macro-backtrace for more info) + = help: use `u8::to_be_bytes` instead + = note: this error originates in the macro `fn_body_smol` (in Nightly builds, run with -Z macro-backtrace for more info) -error: usage of the method `from_le_bytes` +error: usage of the function `u8::from_le_bytes` --> $DIR/endian_bytes.rs:74:9 | LL | u8::from_le_bytes(todo!()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ ... -LL | fn host_encourage_big() { fn_body_small!(); } - | ---------------- in this macro invocation +LL | fn host_encourage_big() { fn_body_smol!(); } + | --------------- in this macro invocation | - = help: use `from_be_bytes` instead - = note: this error originates in the macro `fn_body_small` (in Nightly builds, run with -Z macro-backtrace for more info) + = help: use `u8::from_be_bytes` instead + = note: this error originates in the macro `fn_body_smol` (in Nightly builds, run with -Z macro-backtrace for more info) -error: usage of the method `to_ne_bytes` +error: usage of the `u8::to_ne_bytes` method --> $DIR/endian_bytes.rs:70:9 | LL | 2u8.to_ne_bytes(); | ^^^^^^^^^^^^^^^^^ ... -LL | fn no_help() { fn_body_small!(); } - | ---------------- in this macro invocation +LL | fn no_help() { fn_body_smol!(); } + | --------------- in this macro invocation | - = note: this error originates in the macro `fn_body_small` (in Nightly builds, run with -Z macro-backtrace for more info) + = note: this error originates in the macro `fn_body_smol` (in Nightly builds, run with -Z macro-backtrace for more info) -error: usage of the method `from_ne_bytes` +error: usage of the function `u8::from_ne_bytes` --> $DIR/endian_bytes.rs:71:9 | LL | u8::from_ne_bytes(todo!()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ ... -LL | fn no_help() { fn_body_small!(); } - | ---------------- in this macro invocation +LL | fn no_help() { fn_body_smol!(); } + | --------------- in this macro invocation | - = note: this error originates in the macro `fn_body_small` (in Nightly builds, run with -Z macro-backtrace for more info) + = note: this error originates in the macro `fn_body_smol` (in Nightly builds, run with -Z macro-backtrace for more info) -error: usage of the method `to_le_bytes` +error: usage of the `u8::to_le_bytes` method --> $DIR/endian_bytes.rs:73:9 | LL | 2u8.to_le_bytes(); | ^^^^^^^^^^^^^^^^^ ... -LL | fn no_help() { fn_body_small!(); } - | ---------------- in this macro invocation +LL | fn no_help() { fn_body_smol!(); } + | --------------- in this macro invocation | - = note: this error originates in the macro `fn_body_small` (in Nightly builds, run with -Z macro-backtrace for more info) + = note: this error originates in the macro `fn_body_smol` (in Nightly builds, run with -Z macro-backtrace for more info) -error: usage of the method `from_le_bytes` +error: usage of the function `u8::from_le_bytes` --> $DIR/endian_bytes.rs:74:9 | LL | u8::from_le_bytes(todo!()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ ... -LL | fn no_help() { fn_body_small!(); } - | ---------------- in this macro invocation +LL | fn no_help() { fn_body_smol!(); } + | --------------- in this macro invocation | - = note: this error originates in the macro `fn_body_small` (in Nightly builds, run with -Z macro-backtrace for more info) + = note: this error originates in the macro `fn_body_smol` (in Nightly builds, run with -Z macro-backtrace for more info) -error: usage of the method `to_be_bytes` +error: usage of the `u8::to_be_bytes` method --> $DIR/endian_bytes.rs:76:9 | LL | 2u8.to_be_bytes(); | ^^^^^^^^^^^^^^^^^ ... -LL | fn no_help() { fn_body_small!(); } - | ---------------- in this macro invocation +LL | fn no_help() { fn_body_smol!(); } + | --------------- in this macro invocation | - = note: this error originates in the macro `fn_body_small` (in Nightly builds, run with -Z macro-backtrace for more info) + = note: this error originates in the macro `fn_body_smol` (in Nightly builds, run with -Z macro-backtrace for more info) -error: usage of the method `from_be_bytes` +error: usage of the function `u8::from_be_bytes` --> $DIR/endian_bytes.rs:77:9 | LL | u8::from_be_bytes(todo!()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ ... -LL | fn no_help() { fn_body_small!(); } - | ---------------- in this macro invocation +LL | fn no_help() { fn_body_smol!(); } + | --------------- in this macro invocation | - = note: this error originates in the macro `fn_body_small` (in Nightly builds, run with -Z macro-backtrace for more info) + = note: this error originates in the macro `fn_body_smol` (in Nightly builds, run with -Z macro-backtrace for more info) -error: usage of the method `to_le_bytes` +error: usage of the `u8::to_le_bytes` method --> $DIR/endian_bytes.rs:73:9 | LL | 2u8.to_le_bytes(); | ^^^^^^^^^^^^^^^^^ ... -LL | fn little_encourage_host() { fn_body_small!(); } - | ---------------- in this macro invocation +LL | fn little_encourage_host() { fn_body_smol!(); } + | --------------- in this macro invocation | = help: use the native endianness instead - = note: this error originates in the macro `fn_body_small` (in Nightly builds, run with -Z macro-backtrace for more info) + = note: this error originates in the macro `fn_body_smol` (in Nightly builds, run with -Z macro-backtrace for more info) -error: usage of the method `from_le_bytes` +error: usage of the function `u8::from_le_bytes` --> $DIR/endian_bytes.rs:74:9 | LL | u8::from_le_bytes(todo!()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ ... -LL | fn little_encourage_host() { fn_body_small!(); } - | ---------------- in this macro invocation +LL | fn little_encourage_host() { fn_body_smol!(); } + | --------------- in this macro invocation | = help: use the native endianness instead - = note: this error originates in the macro `fn_body_small` (in Nightly builds, run with -Z macro-backtrace for more info) + = note: this error originates in the macro `fn_body_smol` (in Nightly builds, run with -Z macro-backtrace for more info) -error: usage of the method `to_be_bytes` +error: usage of the `u8::to_be_bytes` method --> $DIR/endian_bytes.rs:76:9 | LL | 2u8.to_be_bytes(); | ^^^^^^^^^^^^^^^^^ ... -LL | fn little_encourage_host() { fn_body_small!(); } - | ---------------- in this macro invocation +LL | fn little_encourage_host() { fn_body_smol!(); } + | --------------- in this macro invocation | = help: use the native endianness instead - = note: this error originates in the macro `fn_body_small` (in Nightly builds, run with -Z macro-backtrace for more info) + = note: this error originates in the macro `fn_body_smol` (in Nightly builds, run with -Z macro-backtrace for more info) -error: usage of the method `from_be_bytes` +error: usage of the function `u8::from_be_bytes` --> $DIR/endian_bytes.rs:77:9 | LL | u8::from_be_bytes(todo!()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ ... -LL | fn little_encourage_host() { fn_body_small!(); } - | ---------------- in this macro invocation +LL | fn little_encourage_host() { fn_body_smol!(); } + | --------------- in this macro invocation | = help: use the native endianness instead - = note: this error originates in the macro `fn_body_small` (in Nightly builds, run with -Z macro-backtrace for more info) + = note: this error originates in the macro `fn_body_smol` (in Nightly builds, run with -Z macro-backtrace for more info) -error: usage of the method `to_ne_bytes` +error: usage of the `u8::to_ne_bytes` method --> $DIR/endian_bytes.rs:70:9 | LL | 2u8.to_ne_bytes(); | ^^^^^^^^^^^^^^^^^ ... -LL | fn little_encourage_big() { fn_body_small!(); } - | ---------------- in this macro invocation +LL | fn little_encourage_big() { fn_body_smol!(); } + | --------------- in this macro invocation | - = help: use `to_be_bytes` instead - = note: this error originates in the macro `fn_body_small` (in Nightly builds, run with -Z macro-backtrace for more info) + = help: use `u8::to_be_bytes` instead + = note: this error originates in the macro `fn_body_smol` (in Nightly builds, run with -Z macro-backtrace for more info) -error: usage of the method `from_ne_bytes` +error: usage of the function `u8::from_ne_bytes` --> $DIR/endian_bytes.rs:71:9 | LL | u8::from_ne_bytes(todo!()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ ... -LL | fn little_encourage_big() { fn_body_small!(); } - | ---------------- in this macro invocation +LL | fn little_encourage_big() { fn_body_smol!(); } + | --------------- in this macro invocation | - = help: use `from_be_bytes` instead - = note: this error originates in the macro `fn_body_small` (in Nightly builds, run with -Z macro-backtrace for more info) + = help: use `u8::from_be_bytes` instead + = note: this error originates in the macro `fn_body_smol` (in Nightly builds, run with -Z macro-backtrace for more info) -error: usage of the method `to_le_bytes` +error: usage of the `u8::to_le_bytes` method --> $DIR/endian_bytes.rs:73:9 | LL | 2u8.to_le_bytes(); | ^^^^^^^^^^^^^^^^^ ... -LL | fn little_encourage_big() { fn_body_small!(); } - | ---------------- in this macro invocation +LL | fn little_encourage_big() { fn_body_smol!(); } + | --------------- in this macro invocation | - = help: use `to_be_bytes` instead - = note: this error originates in the macro `fn_body_small` (in Nightly builds, run with -Z macro-backtrace for more info) + = help: use `u8::to_be_bytes` instead + = note: this error originates in the macro `fn_body_smol` (in Nightly builds, run with -Z macro-backtrace for more info) -error: usage of the method `from_le_bytes` +error: usage of the function `u8::from_le_bytes` --> $DIR/endian_bytes.rs:74:9 | LL | u8::from_le_bytes(todo!()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ ... -LL | fn little_encourage_big() { fn_body_small!(); } - | ---------------- in this macro invocation +LL | fn little_encourage_big() { fn_body_smol!(); } + | --------------- in this macro invocation | - = help: use `from_be_bytes` instead - = note: this error originates in the macro `fn_body_small` (in Nightly builds, run with -Z macro-backtrace for more info) + = help: use `u8::from_be_bytes` instead + = note: this error originates in the macro `fn_body_smol` (in Nightly builds, run with -Z macro-backtrace for more info) -error: usage of the method `to_le_bytes` +error: usage of the `u8::to_le_bytes` method --> $DIR/endian_bytes.rs:73:9 | LL | 2u8.to_le_bytes(); | ^^^^^^^^^^^^^^^^^ ... -LL | fn big_encourage_host() { fn_body_small!(); } - | ---------------- in this macro invocation +LL | fn big_encourage_host() { fn_body_smol!(); } + | --------------- in this macro invocation | = help: use the native endianness instead - = note: this error originates in the macro `fn_body_small` (in Nightly builds, run with -Z macro-backtrace for more info) + = note: this error originates in the macro `fn_body_smol` (in Nightly builds, run with -Z macro-backtrace for more info) -error: usage of the method `from_le_bytes` +error: usage of the function `u8::from_le_bytes` --> $DIR/endian_bytes.rs:74:9 | LL | u8::from_le_bytes(todo!()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ ... -LL | fn big_encourage_host() { fn_body_small!(); } - | ---------------- in this macro invocation +LL | fn big_encourage_host() { fn_body_smol!(); } + | --------------- in this macro invocation | = help: use the native endianness instead - = note: this error originates in the macro `fn_body_small` (in Nightly builds, run with -Z macro-backtrace for more info) + = note: this error originates in the macro `fn_body_smol` (in Nightly builds, run with -Z macro-backtrace for more info) -error: usage of the method `to_be_bytes` +error: usage of the `u8::to_be_bytes` method --> $DIR/endian_bytes.rs:76:9 | LL | 2u8.to_be_bytes(); | ^^^^^^^^^^^^^^^^^ ... -LL | fn big_encourage_host() { fn_body_small!(); } - | ---------------- in this macro invocation +LL | fn big_encourage_host() { fn_body_smol!(); } + | --------------- in this macro invocation | = help: use the native endianness instead - = note: this error originates in the macro `fn_body_small` (in Nightly builds, run with -Z macro-backtrace for more info) + = note: this error originates in the macro `fn_body_smol` (in Nightly builds, run with -Z macro-backtrace for more info) -error: usage of the method `from_be_bytes` +error: usage of the function `u8::from_be_bytes` --> $DIR/endian_bytes.rs:77:9 | LL | u8::from_be_bytes(todo!()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ ... -LL | fn big_encourage_host() { fn_body_small!(); } - | ---------------- in this macro invocation +LL | fn big_encourage_host() { fn_body_smol!(); } + | --------------- in this macro invocation | = help: use the native endianness instead - = note: this error originates in the macro `fn_body_small` (in Nightly builds, run with -Z macro-backtrace for more info) + = note: this error originates in the macro `fn_body_smol` (in Nightly builds, run with -Z macro-backtrace for more info) -error: usage of the method `to_ne_bytes` +error: usage of the `u8::to_ne_bytes` method --> $DIR/endian_bytes.rs:70:9 | LL | 2u8.to_ne_bytes(); | ^^^^^^^^^^^^^^^^^ ... -LL | fn big_encourage_little() { fn_body_small!(); } - | ---------------- in this macro invocation +LL | fn big_encourage_little() { fn_body_smol!(); } + | --------------- in this macro invocation | - = help: use `to_le_bytes` instead - = note: this error originates in the macro `fn_body_small` (in Nightly builds, run with -Z macro-backtrace for more info) + = help: use `u8::to_le_bytes` instead + = note: this error originates in the macro `fn_body_smol` (in Nightly builds, run with -Z macro-backtrace for more info) -error: usage of the method `from_ne_bytes` +error: usage of the function `u8::from_ne_bytes` --> $DIR/endian_bytes.rs:71:9 | LL | u8::from_ne_bytes(todo!()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ ... -LL | fn big_encourage_little() { fn_body_small!(); } - | ---------------- in this macro invocation +LL | fn big_encourage_little() { fn_body_smol!(); } + | --------------- in this macro invocation | - = help: use `from_le_bytes` instead - = note: this error originates in the macro `fn_body_small` (in Nightly builds, run with -Z macro-backtrace for more info) + = help: use `u8::from_le_bytes` instead + = note: this error originates in the macro `fn_body_smol` (in Nightly builds, run with -Z macro-backtrace for more info) -error: usage of the method `to_be_bytes` +error: usage of the `u8::to_be_bytes` method --> $DIR/endian_bytes.rs:76:9 | LL | 2u8.to_be_bytes(); | ^^^^^^^^^^^^^^^^^ ... -LL | fn big_encourage_little() { fn_body_small!(); } - | ---------------- in this macro invocation +LL | fn big_encourage_little() { fn_body_smol!(); } + | --------------- in this macro invocation | - = help: use `to_le_bytes` instead - = note: this error originates in the macro `fn_body_small` (in Nightly builds, run with -Z macro-backtrace for more info) + = help: use `u8::to_le_bytes` instead + = note: this error originates in the macro `fn_body_smol` (in Nightly builds, run with -Z macro-backtrace for more info) -error: usage of the method `from_be_bytes` +error: usage of the function `u8::from_be_bytes` --> $DIR/endian_bytes.rs:77:9 | LL | u8::from_be_bytes(todo!()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ ... -LL | fn big_encourage_little() { fn_body_small!(); } - | ---------------- in this macro invocation +LL | fn big_encourage_little() { fn_body_smol!(); } + | --------------- in this macro invocation | - = help: use `from_le_bytes` instead - = note: this error originates in the macro `fn_body_small` (in Nightly builds, run with -Z macro-backtrace for more info) + = help: use `u8::from_le_bytes` instead + = note: this error originates in the macro `fn_body_smol` (in Nightly builds, run with -Z macro-backtrace for more info) error: aborting due to 86 previous errors From 80ae1ec12d6aa7d5cec840387c14a196296b983c Mon Sep 17 00:00:00 2001 From: Centri3 <114838443+Centri3@users.noreply.github.com> Date: Thu, 25 May 2023 11:43:14 -0500 Subject: [PATCH 027/310] unidiomatic `if_chain!` --- clippy_lints/src/endian_bytes.rs | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/clippy_lints/src/endian_bytes.rs b/clippy_lints/src/endian_bytes.rs index 434125932c4..05005a791c2 100644 --- a/clippy_lints/src/endian_bytes.rs +++ b/clippy_lints/src/endian_bytes.rs @@ -105,10 +105,9 @@ impl LateLintPass<'_> for EndianBytes { if args.is_empty(); let ty = cx.typeck_results().expr_ty(receiver); if ty.is_primitive_ty(); + if try_lint_endian_bytes(cx, expr, "to", method_name.ident.name, ty); then { - if try_lint_endian_bytes(cx, expr, "to", method_name.ident.name, ty) { - return; - } + return; } } From 95e8c0b35a0963aa998aa68d9c74cdb2c5a5e6ab Mon Sep 17 00:00:00 2001 From: Centri3 <114838443+Centri3@users.noreply.github.com> Date: Wed, 31 May 2023 17:29:18 -0500 Subject: [PATCH 028/310] don't allocate the names --- clippy_lints/src/endian_bytes.rs | 48 +++++++++++++++++++++++--------- 1 file changed, 35 insertions(+), 13 deletions(-) diff --git a/clippy_lints/src/endian_bytes.rs b/clippy_lints/src/endian_bytes.rs index 05005a791c2..19fb74b9050 100644 --- a/clippy_lints/src/endian_bytes.rs +++ b/clippy_lints/src/endian_bytes.rs @@ -9,7 +9,7 @@ use std::borrow::Cow; declare_clippy_lint! { /// ### What it does - /// Checks for the usage of the `to_ne_bytes` method. + /// Checks for the usage of the `to_ne_bytes` method and/or the function `from_ne_bytes`. /// /// ### Why is this bad? /// It's not, but some may prefer to specify the target endianness explicitly. @@ -27,7 +27,7 @@ declare_clippy_lint! { declare_clippy_lint! { /// ### What it does - /// Checks for the usage of the `to_le_bytes` method. + /// Checks for the usage of the `to_le_bytes` method and/or the function `from_le_bytes`. /// /// ### Why is this bad? /// It's not, but some may wish to lint usage of this method, either to suggest using the host @@ -46,7 +46,7 @@ declare_clippy_lint! { declare_clippy_lint! { /// ### What it does - /// Checks for the usage of the `to_be_bytes` method. + /// Checks for the usage of the `to_be_bytes` method and/or the function `from_be_bytes`. /// /// ### Why is this bad? /// It's not, but some may wish to lint usage of this method, either to suggest using the host @@ -65,6 +65,10 @@ declare_clippy_lint! { declare_lint_pass!(EndianBytes => [HOST_ENDIAN_BYTES, LITTLE_ENDIAN_BYTES, BIG_ENDIAN_BYTES]); +const HOST_NAMES: [&str; 2] = ["from_ne_bytes", "to_ne_bytes"]; +const LITTLE_NAMES: [&str; 2] = ["from_le_bytes", "to_le_bytes"]; +const BIG_NAMES: [&str; 2] = ["from_be_bytes", "to_be_bytes"]; + #[derive(Clone, Debug)] enum LintKind { Host, @@ -85,11 +89,29 @@ impl LintKind { } } - fn to_name(&self, prefix: &str) -> String { + fn to_name(&self, prefix: &str) -> &str { match self { - LintKind::Host => format!("{prefix}_ne_bytes"), - LintKind::Little => format!("{prefix}_le_bytes"), - LintKind::Big => format!("{prefix}_be_bytes"), + LintKind::Host => { + if prefix == "from" { + HOST_NAMES[0] + } else { + HOST_NAMES[1] + } + }, + LintKind::Little => { + if prefix == "from" { + LITTLE_NAMES[0] + } else { + LITTLE_NAMES[1] + } + }, + LintKind::Big => { + if prefix == "from" { + BIG_NAMES[0] + } else { + BIG_NAMES[1] + } + }, } } } @@ -105,7 +127,7 @@ impl LateLintPass<'_> for EndianBytes { if args.is_empty(); let ty = cx.typeck_results().expr_ty(receiver); if ty.is_primitive_ty(); - if try_lint_endian_bytes(cx, expr, "to", method_name.ident.name, ty); + if maybe_lint_endian_bytes(cx, expr, "to", method_name.ident.name, ty); then { return; } @@ -119,16 +141,16 @@ impl LateLintPass<'_> for EndianBytes { let ty = cx.typeck_results().expr_ty(expr); if ty.is_primitive_ty(); then { - try_lint_endian_bytes(cx, expr, "from", *function_name, ty); + maybe_lint_endian_bytes(cx, expr, "from", *function_name, ty); } } } } -fn try_lint_endian_bytes(cx: &LateContext<'_>, expr: &Expr<'_>, prefix: &str, name: Symbol, ty: Ty<'_>) -> bool { - let ne = format!("{prefix}_ne_bytes"); - let le = format!("{prefix}_le_bytes"); - let be = format!("{prefix}_be_bytes"); +fn maybe_lint_endian_bytes(cx: &LateContext<'_>, expr: &Expr<'_>, prefix: &str, name: Symbol, ty: Ty<'_>) -> bool { + let ne = LintKind::Host.to_name(prefix); + let le = LintKind::Little.to_name(prefix); + let be = LintKind::Big.to_name(prefix); let (lint, other_lints) = match name.as_str() { name if name == ne => ((&LintKind::Host), [(&LintKind::Little), (&LintKind::Big)]), From 8188da3614959d2532deb69030f1ba64c8ac16bf Mon Sep 17 00:00:00 2001 From: Centri3 <114838443+Centri3@users.noreply.github.com> Date: Wed, 31 May 2023 23:33:30 -0500 Subject: [PATCH 029/310] Fix suggestion on fully qualified syntax --- clippy_lints/src/dereference.rs | 32 ++++++++++--- tests/ui/explicit_deref_methods.fixed | 29 +++++++++++- tests/ui/explicit_deref_methods.rs | 29 +++++++++++- tests/ui/explicit_deref_methods.stderr | 62 ++++++++++++++++++++------ 4 files changed, 132 insertions(+), 20 deletions(-) diff --git a/clippy_lints/src/dereference.rs b/clippy_lints/src/dereference.rs index b27ffe73ffd..96d1bcea6e5 100644 --- a/clippy_lints/src/dereference.rs +++ b/clippy_lints/src/dereference.rs @@ -155,7 +155,7 @@ impl_lint_pass!(Dereferencing<'_> => [ #[derive(Default)] pub struct Dereferencing<'tcx> { - state: Option<(State, StateData)>, + state: Option<(State<'tcx>, StateData)>, // While parsing a `deref` method call in ufcs form, the path to the function is itself an // expression. This is to store the id of that expression so it can be skipped when @@ -210,12 +210,13 @@ struct DerefedBorrow { } #[derive(Debug)] -enum State { +enum State<'tcx> { // Any number of deref method calls. DerefMethod { // The number of calls in a sequence which changed the referenced type ty_changed_count: usize, is_final_ufcs: bool, + call_args: Option<&'tcx [Expr<'tcx>]>, /// The required mutability target_mut: Mutability, }, @@ -312,10 +313,16 @@ impl<'tcx> LateLintPass<'tcx> for Dereferencing<'tcx> { && position.lint_explicit_deref() => { let ty_changed_count = usize::from(!deref_method_same_type(expr_ty, typeck.expr_ty(sub_expr))); + let (is_final_ufcs, call_args) = if let ExprKind::Call(_, args) = expr.kind { + (true, Some(args)) + } else { + (false, None) + }; self.state = Some(( State::DerefMethod { ty_changed_count, - is_final_ufcs: matches!(expr.kind, ExprKind::Call(..)), + is_final_ufcs, + call_args, target_mut, }, StateData { @@ -438,6 +445,7 @@ impl<'tcx> LateLintPass<'tcx> for Dereferencing<'tcx> { ty_changed_count + 1 }, is_final_ufcs: matches!(expr.kind, ExprKind::Call(..)), + call_args: None, target_mut, }, data, @@ -1472,11 +1480,12 @@ fn ty_contains_field(ty: Ty<'_>, name: Symbol) -> bool { } #[expect(clippy::needless_pass_by_value, clippy::too_many_lines)] -fn report<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>, state: State, data: StateData) { +fn report<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>, state: State<'_>, data: StateData) { match state { State::DerefMethod { ty_changed_count, is_final_ufcs, + call_args, target_mut, } => { let mut app = Applicability::MachineApplicable; @@ -1503,12 +1512,25 @@ fn report<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>, state: State, data "&" }; - let expr_str = if !expr_is_macro_call && is_final_ufcs && expr.precedence().order() < PREC_PREFIX { + let mut expr_str = if !expr_is_macro_call && is_final_ufcs && expr.precedence().order() < PREC_PREFIX { format!("({expr_str})") } else { expr_str.into_owned() }; + // Fix #10850, changes suggestion if it's `Foo::deref` instead of `foo.deref`. Since `Foo::deref` is + // a `Call` instead of a `MethodCall` this should catch all instances of this, even if it's fully + // qualified or whatnot. + if is_final_ufcs && let Some(args) = call_args { + // Remove ref if it's there + let arg = if let ExprKind::AddrOf(.., arg) = args[0].kind { + arg + } else { + &args[0] + }; + expr_str = snippet_with_applicability(cx, arg.span, "{ .. }", &mut app).to_string(); + } + span_lint_and_sugg( cx, EXPLICIT_DEREF_METHODS, diff --git a/tests/ui/explicit_deref_methods.fixed b/tests/ui/explicit_deref_methods.fixed index 60482c66da7..6cf7a28cafa 100644 --- a/tests/ui/explicit_deref_methods.fixed +++ b/tests/ui/explicit_deref_methods.fixed @@ -1,11 +1,12 @@ //@run-rustfix #![warn(clippy::explicit_deref_methods)] -#![allow(unused_variables)] +#![allow(unused_variables, unused_must_use)] #![allow( clippy::borrow_deref_ref, suspicious_double_ref_op, clippy::explicit_auto_deref, clippy::needless_borrow, + clippy::no_effect, clippy::uninlined_format_args )] @@ -28,6 +29,22 @@ impl Deref for CustomVec { } } +struct Aaa; + +impl Deref for Aaa { + type Target = (); + + fn deref(&self) -> &Self::Target { + todo!(); + } +} + +impl DerefMut for Aaa { + fn deref_mut(&mut self) -> &mut Self::Target { + todo!(); + } +} + fn main() { let a: &mut String = &mut String::from("foo"); @@ -58,6 +75,16 @@ fn main() { let opt_a = Some(a.clone()); let b = &*opt_a.unwrap(); + // make sure `Aaa::deref` instead of `aaa.deref()` works as well as fully qualified syntax + + &*Aaa; + &mut *Aaa; + &*Aaa; + &mut *Aaa; + let mut aaa = Aaa; + &*aaa; + &mut *aaa; + // following should not require linting let cv = CustomVec(vec![0, 42]); diff --git a/tests/ui/explicit_deref_methods.rs b/tests/ui/explicit_deref_methods.rs index e3613e216bb..77501fa6b6e 100644 --- a/tests/ui/explicit_deref_methods.rs +++ b/tests/ui/explicit_deref_methods.rs @@ -1,11 +1,12 @@ //@run-rustfix #![warn(clippy::explicit_deref_methods)] -#![allow(unused_variables)] +#![allow(unused_variables, unused_must_use)] #![allow( clippy::borrow_deref_ref, suspicious_double_ref_op, clippy::explicit_auto_deref, clippy::needless_borrow, + clippy::no_effect, clippy::uninlined_format_args )] @@ -28,6 +29,22 @@ impl Deref for CustomVec { } } +struct Aaa; + +impl Deref for Aaa { + type Target = (); + + fn deref(&self) -> &Self::Target { + todo!(); + } +} + +impl DerefMut for Aaa { + fn deref_mut(&mut self) -> &mut Self::Target { + todo!(); + } +} + fn main() { let a: &mut String = &mut String::from("foo"); @@ -58,6 +75,16 @@ fn main() { let opt_a = Some(a.clone()); let b = opt_a.unwrap().deref(); + // make sure `Aaa::deref` instead of `aaa.deref()` works as well as fully qualified syntax + + Aaa::deref(&Aaa); + Aaa::deref_mut(&mut Aaa); + ::deref(&Aaa); + ::deref_mut(&mut Aaa); + let mut aaa = Aaa; + Aaa::deref(&aaa); + Aaa::deref_mut(&mut aaa); + // following should not require linting let cv = CustomVec(vec![0, 42]); diff --git a/tests/ui/explicit_deref_methods.stderr b/tests/ui/explicit_deref_methods.stderr index 4b10ed1377b..30ebcd47b2b 100644 --- a/tests/ui/explicit_deref_methods.stderr +++ b/tests/ui/explicit_deref_methods.stderr @@ -1,5 +1,5 @@ error: explicit `deref` method call - --> $DIR/explicit_deref_methods.rs:36:19 + --> $DIR/explicit_deref_methods.rs:53:19 | LL | let b: &str = a.deref(); | ^^^^^^^^^ help: try this: `&*a` @@ -7,70 +7,106 @@ LL | let b: &str = a.deref(); = note: `-D clippy::explicit-deref-methods` implied by `-D warnings` error: explicit `deref_mut` method call - --> $DIR/explicit_deref_methods.rs:38:23 + --> $DIR/explicit_deref_methods.rs:55:23 | LL | let b: &mut str = a.deref_mut(); | ^^^^^^^^^^^^^ help: try this: `&mut **a` error: explicit `deref` method call - --> $DIR/explicit_deref_methods.rs:41:39 + --> $DIR/explicit_deref_methods.rs:58:39 | LL | let b: String = format!("{}, {}", a.deref(), a.deref()); | ^^^^^^^^^ help: try this: `&*a` error: explicit `deref` method call - --> $DIR/explicit_deref_methods.rs:41:50 + --> $DIR/explicit_deref_methods.rs:58:50 | LL | let b: String = format!("{}, {}", a.deref(), a.deref()); | ^^^^^^^^^ help: try this: `&*a` error: explicit `deref` method call - --> $DIR/explicit_deref_methods.rs:43:20 + --> $DIR/explicit_deref_methods.rs:60:20 | LL | println!("{}", a.deref()); | ^^^^^^^^^ help: try this: `&*a` error: explicit `deref` method call - --> $DIR/explicit_deref_methods.rs:46:11 + --> $DIR/explicit_deref_methods.rs:63:11 | LL | match a.deref() { | ^^^^^^^^^ help: try this: `&*a` error: explicit `deref` method call - --> $DIR/explicit_deref_methods.rs:50:28 + --> $DIR/explicit_deref_methods.rs:67:28 | LL | let b: String = concat(a.deref()); | ^^^^^^^^^ help: try this: `&*a` error: explicit `deref` method call - --> $DIR/explicit_deref_methods.rs:52:13 + --> $DIR/explicit_deref_methods.rs:69:13 | LL | let b = just_return(a).deref(); | ^^^^^^^^^^^^^^^^^^^^^^ help: try this: `just_return(a)` error: explicit `deref` method call - --> $DIR/explicit_deref_methods.rs:54:28 + --> $DIR/explicit_deref_methods.rs:71:28 | LL | let b: String = concat(just_return(a).deref()); | ^^^^^^^^^^^^^^^^^^^^^^ help: try this: `just_return(a)` error: explicit `deref` method call - --> $DIR/explicit_deref_methods.rs:56:19 + --> $DIR/explicit_deref_methods.rs:73:19 | LL | let b: &str = a.deref().deref(); | ^^^^^^^^^^^^^^^^^ help: try this: `&**a` error: explicit `deref` method call - --> $DIR/explicit_deref_methods.rs:59:13 + --> $DIR/explicit_deref_methods.rs:76:13 | LL | let b = opt_a.unwrap().deref(); | ^^^^^^^^^^^^^^^^^^^^^^ help: try this: `&*opt_a.unwrap()` error: explicit `deref` method call - --> $DIR/explicit_deref_methods.rs:85:31 + --> $DIR/explicit_deref_methods.rs:80:5 + | +LL | Aaa::deref(&Aaa); + | ^^^^^^^^^^^^^^^^ help: try this: `&*Aaa` + +error: explicit `deref_mut` method call + --> $DIR/explicit_deref_methods.rs:81:5 + | +LL | Aaa::deref_mut(&mut Aaa); + | ^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `&mut *Aaa` + +error: explicit `deref` method call + --> $DIR/explicit_deref_methods.rs:82:5 + | +LL | ::deref(&Aaa); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `&*Aaa` + +error: explicit `deref_mut` method call + --> $DIR/explicit_deref_methods.rs:83:5 + | +LL | ::deref_mut(&mut Aaa); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `&mut *Aaa` + +error: explicit `deref` method call + --> $DIR/explicit_deref_methods.rs:85:5 + | +LL | Aaa::deref(&aaa); + | ^^^^^^^^^^^^^^^^ help: try this: `&*aaa` + +error: explicit `deref_mut` method call + --> $DIR/explicit_deref_methods.rs:86:5 + | +LL | Aaa::deref_mut(&mut aaa); + | ^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `&mut *aaa` + +error: explicit `deref` method call + --> $DIR/explicit_deref_methods.rs:112:31 | LL | let b: &str = expr_deref!(a.deref()); | ^^^^^^^^^ help: try this: `&*a` -error: aborting due to 12 previous errors +error: aborting due to 18 previous errors From c11573d78c69459708967c28aec74a2e19947051 Mon Sep 17 00:00:00 2001 From: Deadbeef Date: Thu, 1 Jun 2023 06:14:06 +0000 Subject: [PATCH 030/310] Rename `impl_defaultness` to `defaultness` --- clippy_lints/src/missing_inline.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clippy_lints/src/missing_inline.rs b/clippy_lints/src/missing_inline.rs index 5a459548153..a41d5a9ce8d 100644 --- a/clippy_lints/src/missing_inline.rs +++ b/clippy_lints/src/missing_inline.rs @@ -105,7 +105,7 @@ impl<'tcx> LateLintPass<'tcx> for MissingInline { match tit_.kind { hir::TraitItemKind::Const(..) | hir::TraitItemKind::Type(..) => {}, hir::TraitItemKind::Fn(..) => { - if cx.tcx.impl_defaultness(tit.id.owner_id).has_value() { + if cx.tcx.defaultness(tit.id.owner_id).has_value() { // trait method with default body needs inline in case // an impl is not provided let desc = "a default trait method"; From 16f1cf8fd4e378d61bb240a8c5bbbeba2d000cb0 Mon Sep 17 00:00:00 2001 From: MarcusGrass Date: Thu, 1 Jun 2023 10:40:21 +0200 Subject: [PATCH 031/310] Ignore from_over_into if it contains Self --- clippy_lints/src/from_over_into.rs | 80 +++--------------------------- tests/ui/from_over_into.fixed | 6 +-- tests/ui/from_over_into.stderr | 15 +----- 3 files changed, 10 insertions(+), 91 deletions(-) diff --git a/clippy_lints/src/from_over_into.rs b/clippy_lints/src/from_over_into.rs index e725fb26c22..c4405feaa97 100644 --- a/clippy_lints/src/from_over_into.rs +++ b/clippy_lints/src/from_over_into.rs @@ -80,6 +80,11 @@ impl<'tcx> LateLintPass<'tcx> for FromOverInto { && cx.tcx.is_diagnostic_item(sym::Into, middle_trait_ref.def_id) && !matches!(middle_trait_ref.substs.type_at(1).kind(), ty::Alias(ty::Opaque, _)) { + if !target_ty.find_self_aliases().is_empty() { + // It's tricky to expand self-aliases correctly, we'll ignore it to not cause a + // bad suggestion/fix. + return; + } span_lint_and_then( cx, FROM_OVER_INTO, @@ -163,8 +168,7 @@ fn convert_to_from( let PatKind::Binding(.., self_ident, None) = input.pat.kind else { return None }; let from = snippet_opt(cx, self_ty.span)?; - // If Self is used, it refers to `self_ty`, which is now out `from` snippet - let into = replace_self(&snippet_opt(cx, target_ty.span)?, &from); + let into = snippet_opt(cx, target_ty.span)?; let mut suggestions = vec![ // impl Into for U -> impl From for U @@ -213,75 +217,3 @@ fn convert_to_from( Some(suggestions) } - -fn replace_self(input: &str, replace_with: &str) -> String { - const SELF: &str = "Self"; - let mut chunks = input.split(SELF).peekable(); - if let Some(first) = chunks.next() { - let mut last_ended_with_break = false; - // Heuristic, we're making a guess that the expansion probably doesn't exceed `input.len() * 2` - let mut output = String::with_capacity(input.len() * 2); - if first.is_empty() || first.ends_with(word_break) { - last_ended_with_break = true; - } - output.push_str(first); - while let Some(val) = chunks.next() { - let is_last = chunks.peek().is_none(); - if last_ended_with_break && is_last && val.is_empty() { - output.push_str(replace_with); - break; - } - let this_starts_with_break = val.starts_with(word_break); - let this_ends_with_break = val.ends_with(word_break); - if this_starts_with_break && last_ended_with_break { - output.push_str(replace_with); - } else { - output.push_str(SELF); - } - output.push_str(val); - last_ended_with_break = this_ends_with_break; - } - output - } else { - input.to_string() - } -} - -#[inline] -fn word_break(ch: char) -> bool { - !ch.is_alphanumeric() -} - -#[cfg(test)] -mod tests { - use crate::from_over_into::replace_self; - - #[test] - fn replace_doesnt_touch_coincidental_self() { - let input = "impl Into for String {"; - assert_eq!(input, &replace_self(input, "T")); - } - - #[test] - fn replace_replaces_self() { - let input = "impl Into for String {"; - assert_eq!("impl Into for String {", &replace_self(input, "String")); - } - #[test] - fn replace_replaces_self_many() { - let input = "impl Into>> for Self {"; - assert_eq!( - "impl Into>> for String {", - &replace_self(input, "String") - ); - } - - #[test] - fn replace_replaces_self_many_starts_ends_self() { - let input = "Self impl Into>> for Self"; - assert_eq!( - "String impl Into>> for String", - &replace_self(input, "String") - ); - } -} diff --git a/tests/ui/from_over_into.fixed b/tests/ui/from_over_into.fixed index f1333bb39a8..98310ac5c6c 100644 --- a/tests/ui/from_over_into.fixed +++ b/tests/ui/from_over_into.fixed @@ -92,9 +92,9 @@ pub struct Lval(T); pub struct Rval(T); -impl From> for Rval> { - fn from(val: Lval) -> Self { - Rval(val) +impl Into> for Lval { + fn into(self) -> Rval { + Rval(self) } } diff --git a/tests/ui/from_over_into.stderr b/tests/ui/from_over_into.stderr index c514bb6146c..6039f86fe67 100644 --- a/tests/ui/from_over_into.stderr +++ b/tests/ui/from_over_into.stderr @@ -71,18 +71,5 @@ LL ~ fn from(val: Vec) -> Self { LL ~ FromOverInto(val) | -error: an implementation of `From` is preferred since it gives you `Into<_>` for free where the reverse isn't true - --> $DIR/from_over_into.rs:95:1 - | -LL | impl Into> for Lval { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | -help: replace the `Into` implementation with `From>` - | -LL ~ impl From> for Rval> { -LL ~ fn from(val: Lval) -> Self { -LL ~ Rval(val) - | - -error: aborting due to 6 previous errors +error: aborting due to 5 previous errors From b2c85b31bbe9dfd841c5d4999ac79cd431489101 Mon Sep 17 00:00:00 2001 From: MarcusGrass Date: Thu, 1 Jun 2023 16:02:42 +0200 Subject: [PATCH 032/310] Move bail into lint to prevent no-linting, move to unfixable --- clippy_lints/src/from_over_into.rs | 10 +++++----- tests/ui/from_over_into.fixed | 10 ---------- tests/ui/from_over_into.rs | 10 ---------- tests/ui/from_over_into_unfixable.rs | 10 ++++++++++ tests/ui/from_over_into_unfixable.stderr | 10 +++++++++- 5 files changed, 24 insertions(+), 26 deletions(-) diff --git a/clippy_lints/src/from_over_into.rs b/clippy_lints/src/from_over_into.rs index c4405feaa97..e25b45eaa2e 100644 --- a/clippy_lints/src/from_over_into.rs +++ b/clippy_lints/src/from_over_into.rs @@ -80,11 +80,6 @@ impl<'tcx> LateLintPass<'tcx> for FromOverInto { && cx.tcx.is_diagnostic_item(sym::Into, middle_trait_ref.def_id) && !matches!(middle_trait_ref.substs.type_at(1).kind(), ty::Alias(ty::Opaque, _)) { - if !target_ty.find_self_aliases().is_empty() { - // It's tricky to expand self-aliases correctly, we'll ignore it to not cause a - // bad suggestion/fix. - return; - } span_lint_and_then( cx, FROM_OVER_INTO, @@ -161,6 +156,11 @@ fn convert_to_from( self_ty: &Ty<'_>, impl_item_ref: &ImplItemRef, ) -> Option> { + if !target_ty.find_self_aliases().is_empty() { + // It's tricky to expand self-aliases correctly, we'll ignore it to not cause a + // bad suggestion/fix. + return None; + } let impl_item = cx.tcx.hir().impl_item(impl_item_ref.id); let ImplItemKind::Fn(ref sig, body_id) = impl_item.kind else { return None }; let body = cx.tcx.hir().body(body_id); diff --git a/tests/ui/from_over_into.fixed b/tests/ui/from_over_into.fixed index 98310ac5c6c..d18f9387565 100644 --- a/tests/ui/from_over_into.fixed +++ b/tests/ui/from_over_into.fixed @@ -88,14 +88,4 @@ impl Into for IntoOpaque { fn into(self) -> Opaque {} } -pub struct Lval(T); - -pub struct Rval(T); - -impl Into> for Lval { - fn into(self) -> Rval { - Rval(self) - } -} - fn main() {} diff --git a/tests/ui/from_over_into.rs b/tests/ui/from_over_into.rs index 4fb91971db9..de8ff0b06bd 100644 --- a/tests/ui/from_over_into.rs +++ b/tests/ui/from_over_into.rs @@ -88,14 +88,4 @@ impl Into for IntoOpaque { fn into(self) -> Opaque {} } -pub struct Lval(T); - -pub struct Rval(T); - -impl Into> for Lval { - fn into(self) -> Rval { - Rval(self) - } -} - fn main() {} diff --git a/tests/ui/from_over_into_unfixable.rs b/tests/ui/from_over_into_unfixable.rs index 3b280b7488a..92d3504bc23 100644 --- a/tests/ui/from_over_into_unfixable.rs +++ b/tests/ui/from_over_into_unfixable.rs @@ -32,4 +32,14 @@ impl Into for ContainsVal { } } +pub struct Lval(T); + +pub struct Rval(T); + +impl Into> for Lval { + fn into(self) -> Rval { + Rval(self) + } +} + fn main() {} diff --git a/tests/ui/from_over_into_unfixable.stderr b/tests/ui/from_over_into_unfixable.stderr index 251f1d84e74..2ab9b9d6b17 100644 --- a/tests/ui/from_over_into_unfixable.stderr +++ b/tests/ui/from_over_into_unfixable.stderr @@ -25,5 +25,13 @@ LL | impl Into for ContainsVal { https://doc.rust-lang.org/reference/items/implementations.html#trait-implementation-coherence = help: replace the `Into` implementation with `From` -error: aborting due to 3 previous errors +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:39:1 + | +LL | impl Into> for Lval { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: replace the `Into` implementation with `From>` + +error: aborting due to 4 previous errors From 62eb4e7d7b5568bfcf9e82a61bf3a60aaa739548 Mon Sep 17 00:00:00 2001 From: MarcusGrass Date: Thu, 1 Jun 2023 15:53:20 +0200 Subject: [PATCH 033/310] Bring up Rust lang #37612 as a known problem for let_and_return --- clippy_lints/src/returns.rs | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/clippy_lints/src/returns.rs b/clippy_lints/src/returns.rs index 631ecf1428d..92913ddc4aa 100644 --- a/clippy_lints/src/returns.rs +++ b/clippy_lints/src/returns.rs @@ -25,6 +25,12 @@ declare_clippy_lint! { /// It is just extraneous code. Remove it to make your code /// more rusty. /// + /// ### Known problems + /// In the case of some temporaries, e.g. locks, eliding the variable binding could lead + /// to deadlocks. See [rust-lang issue 37612](https://github.com/rust-lang/rust/issues/37612). + /// This could become relevant if the code is later changed to use the code that would have been + /// bound without first assigning it to a let-binding. + /// /// ### Example /// ```rust /// fn foo() -> String { From ec2c6155aacbb92e2dba046e1560d9f28a61f077 Mon Sep 17 00:00:00 2001 From: Deadbeef Date: Wed, 17 May 2023 10:30:14 +0000 Subject: [PATCH 034/310] Use translatable diagnostics in `rustc_const_eval` --- tests/ui/modulo_one.stderr | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tests/ui/modulo_one.stderr b/tests/ui/modulo_one.stderr index 04ecdef5e99..83a76f81d4e 100644 --- a/tests/ui/modulo_one.stderr +++ b/tests/ui/modulo_one.stderr @@ -2,7 +2,7 @@ error: this operation will panic at runtime --> $DIR/modulo_one.rs:11:5 | LL | i32::MIN % (-1); // also caught by rustc - | ^^^^^^^^^^^^^^^ attempt to compute the remainder of `i32::MIN % -1_i32`, which would overflow + | ^^^^^^^^^^^^^^^ attempt to compute `i32::MIN % -1_i32`, which would overflow | = note: `#[deny(unconditional_panic)]` on by default @@ -10,13 +10,13 @@ error: this operation will panic at runtime --> $DIR/modulo_one.rs:21:5 | LL | INT_MIN % NEG_ONE; // also caught by rustc - | ^^^^^^^^^^^^^^^^^ attempt to compute the remainder of `i64::MIN % -1_i64`, which would overflow + | ^^^^^^^^^^^^^^^^^ attempt to compute `i64::MIN % -1_i64`, which would overflow error: this operation will panic at runtime --> $DIR/modulo_one.rs:22:5 | LL | INT_MIN % STATIC_NEG_ONE; // ONLY caught by rustc - | ^^^^^^^^^^^^^^^^^^^^^^^^ attempt to compute the remainder of `i64::MIN % -1_i64`, which would overflow + | ^^^^^^^^^^^^^^^^^^^^^^^^ attempt to compute `i64::MIN % -1_i64`, which would overflow error: any number modulo 1 will be 0 --> $DIR/modulo_one.rs:8:5 From 0a7366897d35c0dd2ea125fe79e43cb4862dc73b Mon Sep 17 00:00:00 2001 From: est31 Date: Thu, 1 Jun 2023 18:55:24 +0200 Subject: [PATCH 035/310] manual_let_else: only add () around PatKind::Or at the top level At the top level, () are required, but on the levels below they are not. --- clippy_lints/src/manual_let_else.rs | 13 +++++++++---- tests/ui/manual_let_else_match.rs | 5 +++++ tests/ui/manual_let_else_match.stderr | 13 +++++++++++-- 3 files changed, 25 insertions(+), 6 deletions(-) diff --git a/clippy_lints/src/manual_let_else.rs b/clippy_lints/src/manual_let_else.rs index 389b0a4a62d..d5e847e7183 100644 --- a/clippy_lints/src/manual_let_else.rs +++ b/clippy_lints/src/manual_let_else.rs @@ -159,7 +159,7 @@ fn emit_manual_let_else( } else { format!("{{ {sn_else} }}") }; - let sn_bl = replace_in_pattern(cx, span, local, pat, &mut app); + let sn_bl = replace_in_pattern(cx, span, local, pat, &mut app, true); let sugg = format!("let {sn_bl} = {sn_expr} else {else_bl};"); diag.span_suggestion(span, "consider writing", sugg, app); }, @@ -173,6 +173,7 @@ fn replace_in_pattern( local: &Pat<'_>, pat: &Pat<'_>, app: &mut Applicability, + top_level: bool, ) -> String { let mut bindings_count = 0; pat.each_binding_or_first(&mut |_, _, _, _| bindings_count += 1); @@ -191,16 +192,20 @@ fn replace_in_pattern( PatKind::Or(pats) => { let patterns = pats .iter() - .map(|pat| replace_in_pattern(cx, span, local, pat, app)) + .map(|pat| replace_in_pattern(cx, span, local, pat, app, false)) .collect::>(); let or_pat = patterns.join(" | "); - return format!("({or_pat})"); + if top_level { + return format!("({or_pat})"); + } else { + return or_pat; + } }, // Replace the variable name iff `TupleStruct` has one argument like `Variant(v)`. PatKind::TupleStruct(ref w, args, dot_dot_pos) => { let mut args = args .iter() - .map(|pat| replace_in_pattern(cx, span, local, pat, app)) + .map(|pat| replace_in_pattern(cx, span, local, pat, app, false)) .collect::>(); if let Some(pos) = dot_dot_pos.as_opt_usize() { args.insert(pos, "..".to_owned()); diff --git a/tests/ui/manual_let_else_match.rs b/tests/ui/manual_let_else_match.rs index dfca3b023cd..07cd5a53a7c 100644 --- a/tests/ui/manual_let_else_match.rs +++ b/tests/ui/manual_let_else_match.rs @@ -72,6 +72,11 @@ fn fire() { _ => return, }; + let _value = match Some(build_enum()) { + Some(Variant::Bar(v) | Variant::Baz(v)) => v, + _ => return, + }; + let data = [1_u8, 2, 3, 4, 0, 0, 0, 0]; let data = match data.as_slice() { [data @ .., 0, 0, 0, 0] | [data @ .., 0, 0] | [data @ .., 0] => data, diff --git a/tests/ui/manual_let_else_match.stderr b/tests/ui/manual_let_else_match.stderr index 13ed35bc1d5..ead2f28e609 100644 --- a/tests/ui/manual_let_else_match.stderr +++ b/tests/ui/manual_let_else_match.stderr @@ -64,7 +64,16 @@ LL | | }; | |______^ help: consider writing: `let (Variant::Bar(_value) | Variant::Baz(_value)) = f else { return };` error: this could be rewritten as `let...else` - --> $DIR/manual_let_else_match.rs:76:5 + --> $DIR/manual_let_else_match.rs:75:5 + | +LL | / let _value = match Some(build_enum()) { +LL | | Some(Variant::Bar(v) | Variant::Baz(v)) => v, +LL | | _ => return, +LL | | }; + | |______^ help: consider writing: `let Some(Variant::Bar(_value) | Variant::Baz(_value)) = Some(build_enum()) else { return };` + +error: this could be rewritten as `let...else` + --> $DIR/manual_let_else_match.rs:81:5 | LL | / let data = match data.as_slice() { LL | | [data @ .., 0, 0, 0, 0] | [data @ .., 0, 0] | [data @ .., 0] => data, @@ -72,5 +81,5 @@ LL | | _ => return, LL | | }; | |______^ help: consider writing: `let ([data @ .., 0, 0, 0, 0] | [data @ .., 0, 0] | [data @ .., 0]) = data.as_slice() else { return };` -error: aborting due to 8 previous errors +error: aborting due to 9 previous errors From b4f074c588ce7a72fb325648c8b7490c77ff9565 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Wed, 17 May 2023 04:05:46 +0000 Subject: [PATCH 036/310] Implement custom diagnostic for ConstParamTy --- tests/ui/same_functions_in_if_condition.rs | 4 +++- .../ui/same_functions_in_if_condition.stderr | 24 +++++++++---------- 2 files changed, 15 insertions(+), 13 deletions(-) diff --git a/tests/ui/same_functions_in_if_condition.rs b/tests/ui/same_functions_in_if_condition.rs index aea1507cc5b..08916398cbb 100644 --- a/tests/ui/same_functions_in_if_condition.rs +++ b/tests/ui/same_functions_in_if_condition.rs @@ -10,6 +10,8 @@ clippy::uninlined_format_args )] +use std::marker::ConstParamTy; + fn function() -> bool { true } @@ -96,7 +98,7 @@ fn main() { }; println!("{}", os); - #[derive(PartialEq, Eq)] + #[derive(PartialEq, Eq, ConstParamTy)] enum E { A, B, diff --git a/tests/ui/same_functions_in_if_condition.stderr b/tests/ui/same_functions_in_if_condition.stderr index aade3b1fa45..6aacc73b90d 100644 --- a/tests/ui/same_functions_in_if_condition.stderr +++ b/tests/ui/same_functions_in_if_condition.stderr @@ -1,11 +1,11 @@ error: this `if` has the same function call as a previous `if` - --> $DIR/same_functions_in_if_condition.rs:37:15 + --> $DIR/same_functions_in_if_condition.rs:39:15 | LL | } else if function() { | ^^^^^^^^^^ | note: same as this - --> $DIR/same_functions_in_if_condition.rs:36:8 + --> $DIR/same_functions_in_if_condition.rs:38:8 | LL | if function() { | ^^^^^^^^^^ @@ -16,61 +16,61 @@ 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 + --> $DIR/same_functions_in_if_condition.rs:44:15 | LL | } else if fn_arg(a) { | ^^^^^^^^^ | note: same as this - --> $DIR/same_functions_in_if_condition.rs:41:8 + --> $DIR/same_functions_in_if_condition.rs:43:8 | LL | if fn_arg(a) { | ^^^^^^^^^ error: this `if` has the same function call as a previous `if` - --> $DIR/same_functions_in_if_condition.rs:47:15 + --> $DIR/same_functions_in_if_condition.rs:49:15 | LL | } else if obj.method() { | ^^^^^^^^^^^^ | note: same as this - --> $DIR/same_functions_in_if_condition.rs:46:8 + --> $DIR/same_functions_in_if_condition.rs:48:8 | LL | if obj.method() { | ^^^^^^^^^^^^ error: this `if` has the same function call as a previous `if` - --> $DIR/same_functions_in_if_condition.rs:52:15 + --> $DIR/same_functions_in_if_condition.rs:54:15 | LL | } else if obj.method_arg(a) { | ^^^^^^^^^^^^^^^^^ | note: same as this - --> $DIR/same_functions_in_if_condition.rs:51:8 + --> $DIR/same_functions_in_if_condition.rs:53:8 | LL | if obj.method_arg(a) { | ^^^^^^^^^^^^^^^^^ error: this `if` has the same function call as a previous `if` - --> $DIR/same_functions_in_if_condition.rs:59:15 + --> $DIR/same_functions_in_if_condition.rs:61:15 | LL | } else if v.pop().is_none() { | ^^^^^^^^^^^^^^^^^ | note: same as this - --> $DIR/same_functions_in_if_condition.rs:57:8 + --> $DIR/same_functions_in_if_condition.rs:59:8 | LL | if v.pop().is_none() { | ^^^^^^^^^^^^^^^^^ error: this `if` has the same function call as a previous `if` - --> $DIR/same_functions_in_if_condition.rs:64:15 + --> $DIR/same_functions_in_if_condition.rs:66:15 | LL | } else if v.len() == 42 { | ^^^^^^^^^^^^^ | note: same as this - --> $DIR/same_functions_in_if_condition.rs:62:8 + --> $DIR/same_functions_in_if_condition.rs:64:8 | LL | if v.len() == 42 { | ^^^^^^^^^^^^^ From a28eb5995f57e63af09a4b55bf3f17d1db00fb39 Mon Sep 17 00:00:00 2001 From: xFrednet Date: Thu, 1 Jun 2023 21:14:07 +0200 Subject: [PATCH 037/310] Update *Current stable* text in `CHANGELOG.md` --- CHANGELOG.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 8b609b47d81..995f6d4562d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,7 +10,7 @@ document. ## Rust 1.70 -Current beta, released 2023-06-01 +Current stable, released 2023-06-01 [149392b0...83e42a23](https://github.com/rust-lang/rust-clippy/compare/149392b0...83e42a23) @@ -95,7 +95,7 @@ Current beta, released 2023-06-01 [#10375](https://github.com/rust-lang/rust-clippy/pull/10375) * [`mem_replace_option_with_none`]: No longer lints on field expressions [#10594](https://github.com/rust-lang/rust-clippy/pull/10594) -* [`items_after_statements`]: No longer lints on times from macros +* [`items_after_statements`]: No longer lints on items from macros [#10542](https://github.com/rust-lang/rust-clippy/pull/10542) * [`print_literal`], [`write_literal`]: No longer lint strings coming from the `file!()` macro [#10573](https://github.com/rust-lang/rust-clippy/pull/10573) @@ -135,7 +135,7 @@ Current beta, released 2023-06-01 ## Rust 1.69 -Current stable, released 2023-04-20 +Released 2023-04-20 [7f27e2e7...149392b0](https://github.com/rust-lang/rust-clippy/compare/7f27e2e7...149392b0) From eed466281c8d0e3a920a2cde01a5b4b5c0df5f0e Mon Sep 17 00:00:00 2001 From: Centri3 <114838443+Centri3@users.noreply.github.com> Date: Thu, 1 Jun 2023 14:29:56 -0500 Subject: [PATCH 038/310] ignore `Foo::deref` altogether --- clippy_lints/src/dereference.rs | 47 ++++++++++---------------- tests/ui/explicit_deref_methods.fixed | 15 ++++---- tests/ui/explicit_deref_methods.rs | 3 +- tests/ui/explicit_deref_methods.stderr | 40 ++-------------------- 4 files changed, 30 insertions(+), 75 deletions(-) diff --git a/clippy_lints/src/dereference.rs b/clippy_lints/src/dereference.rs index 96d1bcea6e5..93b6e2083b5 100644 --- a/clippy_lints/src/dereference.rs +++ b/clippy_lints/src/dereference.rs @@ -56,9 +56,11 @@ declare_clippy_lint! { /// let b = &*a; /// ``` /// - /// This lint excludes: + /// This lint excludes all of: /// ```rust,ignore /// let _ = d.unwrap().deref(); + /// let _ = Foo::deref(&foo); + /// let _ = ::deref(&foo); /// ``` #[clippy::version = "1.44.0"] pub EXPLICIT_DEREF_METHODS, @@ -155,7 +157,7 @@ impl_lint_pass!(Dereferencing<'_> => [ #[derive(Default)] pub struct Dereferencing<'tcx> { - state: Option<(State<'tcx>, StateData)>, + state: Option<(State, StateData)>, // While parsing a `deref` method call in ufcs form, the path to the function is itself an // expression. This is to store the id of that expression so it can be skipped when @@ -210,13 +212,12 @@ struct DerefedBorrow { } #[derive(Debug)] -enum State<'tcx> { +enum State { // Any number of deref method calls. DerefMethod { // The number of calls in a sequence which changed the referenced type ty_changed_count: usize, is_final_ufcs: bool, - call_args: Option<&'tcx [Expr<'tcx>]>, /// The required mutability target_mut: Mutability, }, @@ -313,16 +314,10 @@ impl<'tcx> LateLintPass<'tcx> for Dereferencing<'tcx> { && position.lint_explicit_deref() => { let ty_changed_count = usize::from(!deref_method_same_type(expr_ty, typeck.expr_ty(sub_expr))); - let (is_final_ufcs, call_args) = if let ExprKind::Call(_, args) = expr.kind { - (true, Some(args)) - } else { - (false, None) - }; self.state = Some(( State::DerefMethod { ty_changed_count, - is_final_ufcs, - call_args, + is_final_ufcs: matches!(expr.kind, ExprKind::Call(..)), target_mut, }, StateData { @@ -445,7 +440,6 @@ impl<'tcx> LateLintPass<'tcx> for Dereferencing<'tcx> { ty_changed_count + 1 }, is_final_ufcs: matches!(expr.kind, ExprKind::Call(..)), - call_args: None, target_mut, }, data, @@ -1480,16 +1474,15 @@ fn ty_contains_field(ty: Ty<'_>, name: Symbol) -> bool { } #[expect(clippy::needless_pass_by_value, clippy::too_many_lines)] -fn report<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>, state: State<'_>, data: StateData) { +fn report<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>, state: State, data: StateData) { match state { State::DerefMethod { ty_changed_count, is_final_ufcs, - call_args, target_mut, } => { let mut app = Applicability::MachineApplicable; - let (expr_str, expr_is_macro_call) = snippet_with_context(cx, expr.span, data.span.ctxt(), "..", &mut app); + let (expr_str, _expr_is_macro_call) = snippet_with_context(cx, expr.span, data.span.ctxt(), "..", &mut app); let ty = cx.typeck_results().expr_ty(expr); let (_, ref_count) = peel_mid_ty_refs(ty); let deref_str = if ty_changed_count >= ref_count && ref_count != 0 { @@ -1512,23 +1505,19 @@ fn report<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>, state: State<'_>, "&" }; - let mut expr_str = if !expr_is_macro_call && is_final_ufcs && expr.precedence().order() < PREC_PREFIX { - format!("({expr_str})") + // expr_str (the suggestion) is never shown if is_final_ufcs is true, since it's + // `expr.kind == ExprKind::Call`. Therefore, this is, afaik, always unnecessary. + /* + expr_str = if !expr_is_macro_call && is_final_ufcs && expr.precedence().order() < PREC_PREFIX { + Cow::Owned(format!("({expr_str})")) } else { - expr_str.into_owned() + expr_str }; + */ - // Fix #10850, changes suggestion if it's `Foo::deref` instead of `foo.deref`. Since `Foo::deref` is - // a `Call` instead of a `MethodCall` this should catch all instances of this, even if it's fully - // qualified or whatnot. - if is_final_ufcs && let Some(args) = call_args { - // Remove ref if it's there - let arg = if let ExprKind::AddrOf(.., arg) = args[0].kind { - arg - } else { - &args[0] - }; - expr_str = snippet_with_applicability(cx, arg.span, "{ .. }", &mut app).to_string(); + // Fix #10850, do not lint if it's `Foo::deref` instead of `foo.deref()`. + if is_final_ufcs { + return; } span_lint_and_sugg( diff --git a/tests/ui/explicit_deref_methods.fixed b/tests/ui/explicit_deref_methods.fixed index 6cf7a28cafa..1710b170fb8 100644 --- a/tests/ui/explicit_deref_methods.fixed +++ b/tests/ui/explicit_deref_methods.fixed @@ -75,15 +75,16 @@ fn main() { let opt_a = Some(a.clone()); let b = &*opt_a.unwrap(); - // make sure `Aaa::deref` instead of `aaa.deref()` works as well as fully qualified syntax + // make sure `Aaa::deref` instead of `aaa.deref()` is not linted, as well as fully qualified + // syntax - &*Aaa; - &mut *Aaa; - &*Aaa; - &mut *Aaa; + Aaa::deref(&Aaa); + Aaa::deref_mut(&mut Aaa); + ::deref(&Aaa); + ::deref_mut(&mut Aaa); let mut aaa = Aaa; - &*aaa; - &mut *aaa; + Aaa::deref(&aaa); + Aaa::deref_mut(&mut aaa); // following should not require linting diff --git a/tests/ui/explicit_deref_methods.rs b/tests/ui/explicit_deref_methods.rs index 77501fa6b6e..85147e1cb69 100644 --- a/tests/ui/explicit_deref_methods.rs +++ b/tests/ui/explicit_deref_methods.rs @@ -75,7 +75,8 @@ fn main() { let opt_a = Some(a.clone()); let b = opt_a.unwrap().deref(); - // make sure `Aaa::deref` instead of `aaa.deref()` works as well as fully qualified syntax + // make sure `Aaa::deref` instead of `aaa.deref()` is not linted, as well as fully qualified + // syntax Aaa::deref(&Aaa); Aaa::deref_mut(&mut Aaa); diff --git a/tests/ui/explicit_deref_methods.stderr b/tests/ui/explicit_deref_methods.stderr index 30ebcd47b2b..592563ffa8c 100644 --- a/tests/ui/explicit_deref_methods.stderr +++ b/tests/ui/explicit_deref_methods.stderr @@ -67,46 +67,10 @@ LL | let b = opt_a.unwrap().deref(); | ^^^^^^^^^^^^^^^^^^^^^^ help: try this: `&*opt_a.unwrap()` error: explicit `deref` method call - --> $DIR/explicit_deref_methods.rs:80:5 - | -LL | Aaa::deref(&Aaa); - | ^^^^^^^^^^^^^^^^ help: try this: `&*Aaa` - -error: explicit `deref_mut` method call - --> $DIR/explicit_deref_methods.rs:81:5 - | -LL | Aaa::deref_mut(&mut Aaa); - | ^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `&mut *Aaa` - -error: explicit `deref` method call - --> $DIR/explicit_deref_methods.rs:82:5 - | -LL | ::deref(&Aaa); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `&*Aaa` - -error: explicit `deref_mut` method call - --> $DIR/explicit_deref_methods.rs:83:5 - | -LL | ::deref_mut(&mut Aaa); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `&mut *Aaa` - -error: explicit `deref` method call - --> $DIR/explicit_deref_methods.rs:85:5 - | -LL | Aaa::deref(&aaa); - | ^^^^^^^^^^^^^^^^ help: try this: `&*aaa` - -error: explicit `deref_mut` method call - --> $DIR/explicit_deref_methods.rs:86:5 - | -LL | Aaa::deref_mut(&mut aaa); - | ^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `&mut *aaa` - -error: explicit `deref` method call - --> $DIR/explicit_deref_methods.rs:112:31 + --> $DIR/explicit_deref_methods.rs:113:31 | LL | let b: &str = expr_deref!(a.deref()); | ^^^^^^^^^ help: try this: `&*a` -error: aborting due to 18 previous errors +error: aborting due to 12 previous errors From a239c8b52be0c1eed1a07be6bef558d3e62f9e44 Mon Sep 17 00:00:00 2001 From: y21 <30553356+y21@users.noreply.github.com> Date: Fri, 2 Jun 2023 00:06:34 +0200 Subject: [PATCH 039/310] [`unnecessary_lazy_eval`]: don't lint on types with deref impl --- clippy_utils/src/eager_or_lazy.rs | 8 ++- tests/ui/unnecessary_lazy_eval.fixed | 20 +++++++ tests/ui/unnecessary_lazy_eval.rs | 20 +++++++ tests/ui/unnecessary_lazy_eval.stderr | 86 ++++++++++++++++----------- 4 files changed, 97 insertions(+), 37 deletions(-) diff --git a/clippy_utils/src/eager_or_lazy.rs b/clippy_utils/src/eager_or_lazy.rs index 3df40942e7b..e05b88e4cd0 100644 --- a/clippy_utils/src/eager_or_lazy.rs +++ b/clippy_utils/src/eager_or_lazy.rs @@ -173,11 +173,15 @@ fn expr_eagerness<'tcx>(cx: &LateContext<'tcx>, e: &'tcx Expr<'_>) -> EagernessS self.eagerness = Lazy; } }, - + // Custom `Deref` impl might have side effects + ExprKind::Unary(UnOp::Deref, e) + if self.cx.typeck_results().expr_ty(e).builtin_deref(true).is_none() => + { + self.eagerness |= NoChange; + }, // Dereferences should be cheap, but dereferencing a raw pointer earlier may not be safe. ExprKind::Unary(UnOp::Deref, e) if !self.cx.typeck_results().expr_ty(e).is_unsafe_ptr() => (), ExprKind::Unary(UnOp::Deref, _) => self.eagerness |= NoChange, - ExprKind::Unary(_, e) if matches!( self.cx.typeck_results().expr_ty(e).kind(), diff --git a/tests/ui/unnecessary_lazy_eval.fixed b/tests/ui/unnecessary_lazy_eval.fixed index c3728886ec9..f8d4c0bd912 100644 --- a/tests/ui/unnecessary_lazy_eval.fixed +++ b/tests/ui/unnecessary_lazy_eval.fixed @@ -5,6 +5,8 @@ #![allow(clippy::bind_instead_of_map)] #![allow(clippy::map_identity)] +use std::ops::Deref; + extern crate proc_macros; use proc_macros::with_span; @@ -41,6 +43,15 @@ impl Drop for Issue9427FollowUp { } } +struct Issue10437; +impl Deref for Issue10437 { + type Target = u32; + fn deref(&self) -> &Self::Target { + println!("side effect deref"); + &0 + } +} + fn main() { let astronomers_pi = 10; let ext_arr: [usize; 1] = [2]; @@ -65,6 +76,12 @@ fn main() { let _ = nested_tuple_opt.unwrap_or(Some((1, 2))); let _ = cond.then_some(astronomers_pi); + // Should lint - Builtin deref + let r = &1; + let _ = Some(1).unwrap_or(*r); + let b = Box::new(1); + let _ = Some(1).unwrap_or(*b); + // Cases when unwrap is not called on a simple variable let _ = Some(10).unwrap_or(2); let _ = Some(10).and(ext_opt); @@ -93,6 +110,9 @@ fn main() { let _ = deep.0.or_else(|| some_call()); let _ = opt.ok_or_else(|| ext_arr[0]); + let _ = Some(1).unwrap_or_else(|| *Issue10437); // Issue10437 has a deref impl + let _ = Some(1).unwrap_or(*Issue10437); + // Should not lint - bool let _ = (0 == 1).then(|| Issue9427(0)); // Issue9427 has a significant drop let _ = false.then(|| Issue9427FollowUp); // Issue9427FollowUp has a significant drop diff --git a/tests/ui/unnecessary_lazy_eval.rs b/tests/ui/unnecessary_lazy_eval.rs index 76e50fa5b03..b968894f870 100644 --- a/tests/ui/unnecessary_lazy_eval.rs +++ b/tests/ui/unnecessary_lazy_eval.rs @@ -5,6 +5,8 @@ #![allow(clippy::bind_instead_of_map)] #![allow(clippy::map_identity)] +use std::ops::Deref; + extern crate proc_macros; use proc_macros::with_span; @@ -41,6 +43,15 @@ impl Drop for Issue9427FollowUp { } } +struct Issue10437; +impl Deref for Issue10437 { + type Target = u32; + fn deref(&self) -> &Self::Target { + println!("side effect deref"); + &0 + } +} + fn main() { let astronomers_pi = 10; let ext_arr: [usize; 1] = [2]; @@ -65,6 +76,12 @@ fn main() { let _ = nested_tuple_opt.unwrap_or_else(|| Some((1, 2))); let _ = cond.then(|| astronomers_pi); + // Should lint - Builtin deref + let r = &1; + let _ = Some(1).unwrap_or_else(|| *r); + let b = Box::new(1); + let _ = Some(1).unwrap_or_else(|| *b); + // Cases when unwrap is not called on a simple variable let _ = Some(10).unwrap_or_else(|| 2); let _ = Some(10).and_then(|_| ext_opt); @@ -93,6 +110,9 @@ fn main() { let _ = deep.0.or_else(|| some_call()); let _ = opt.ok_or_else(|| ext_arr[0]); + let _ = Some(1).unwrap_or_else(|| *Issue10437); // Issue10437 has a deref impl + let _ = Some(1).unwrap_or(*Issue10437); + // Should not lint - bool let _ = (0 == 1).then(|| Issue9427(0)); // Issue9427 has a significant drop let _ = false.then(|| Issue9427FollowUp); // Issue9427FollowUp has a significant drop diff --git a/tests/ui/unnecessary_lazy_eval.stderr b/tests/ui/unnecessary_lazy_eval.stderr index 0339755442c..c3d106cd109 100644 --- a/tests/ui/unnecessary_lazy_eval.stderr +++ b/tests/ui/unnecessary_lazy_eval.stderr @@ -1,5 +1,5 @@ error: unnecessary closure used to substitute value for `Option::None` - --> $DIR/unnecessary_lazy_eval.rs:56:13 + --> $DIR/unnecessary_lazy_eval.rs:67:13 | LL | let _ = opt.unwrap_or_else(|| 2); | ^^^^-------------------- @@ -9,7 +9,7 @@ LL | let _ = opt.unwrap_or_else(|| 2); = note: `-D clippy::unnecessary-lazy-evaluations` implied by `-D warnings` error: unnecessary closure used to substitute value for `Option::None` - --> $DIR/unnecessary_lazy_eval.rs:57:13 + --> $DIR/unnecessary_lazy_eval.rs:68:13 | LL | let _ = opt.unwrap_or_else(|| astronomers_pi); | ^^^^--------------------------------- @@ -17,7 +17,7 @@ LL | let _ = opt.unwrap_or_else(|| astronomers_pi); | help: use `unwrap_or(..)` instead: `unwrap_or(astronomers_pi)` error: unnecessary closure used to substitute value for `Option::None` - --> $DIR/unnecessary_lazy_eval.rs:58:13 + --> $DIR/unnecessary_lazy_eval.rs:69:13 | LL | let _ = opt.unwrap_or_else(|| ext_str.some_field); | ^^^^------------------------------------- @@ -25,7 +25,7 @@ LL | let _ = opt.unwrap_or_else(|| ext_str.some_field); | help: use `unwrap_or(..)` instead: `unwrap_or(ext_str.some_field)` error: unnecessary closure used to substitute value for `Option::None` - --> $DIR/unnecessary_lazy_eval.rs:60:13 + --> $DIR/unnecessary_lazy_eval.rs:71:13 | LL | let _ = opt.and_then(|_| ext_opt); | ^^^^--------------------- @@ -33,7 +33,7 @@ LL | let _ = opt.and_then(|_| ext_opt); | help: use `and(..)` instead: `and(ext_opt)` error: unnecessary closure used to substitute value for `Option::None` - --> $DIR/unnecessary_lazy_eval.rs:61:13 + --> $DIR/unnecessary_lazy_eval.rs:72:13 | LL | let _ = opt.or_else(|| ext_opt); | ^^^^------------------- @@ -41,7 +41,7 @@ LL | let _ = opt.or_else(|| ext_opt); | help: use `or(..)` instead: `or(ext_opt)` error: unnecessary closure used to substitute value for `Option::None` - --> $DIR/unnecessary_lazy_eval.rs:62:13 + --> $DIR/unnecessary_lazy_eval.rs:73:13 | LL | let _ = opt.or_else(|| None); | ^^^^---------------- @@ -49,7 +49,7 @@ LL | let _ = opt.or_else(|| None); | help: use `or(..)` instead: `or(None)` error: unnecessary closure used to substitute value for `Option::None` - --> $DIR/unnecessary_lazy_eval.rs:63:13 + --> $DIR/unnecessary_lazy_eval.rs:74:13 | LL | let _ = opt.get_or_insert_with(|| 2); | ^^^^------------------------ @@ -57,7 +57,7 @@ LL | let _ = opt.get_or_insert_with(|| 2); | help: use `get_or_insert(..)` instead: `get_or_insert(2)` error: unnecessary closure used to substitute value for `Option::None` - --> $DIR/unnecessary_lazy_eval.rs:64:13 + --> $DIR/unnecessary_lazy_eval.rs:75:13 | LL | let _ = opt.ok_or_else(|| 2); | ^^^^---------------- @@ -65,7 +65,7 @@ LL | let _ = opt.ok_or_else(|| 2); | help: use `ok_or(..)` instead: `ok_or(2)` error: unnecessary closure used to substitute value for `Option::None` - --> $DIR/unnecessary_lazy_eval.rs:65:13 + --> $DIR/unnecessary_lazy_eval.rs:76:13 | LL | let _ = nested_tuple_opt.unwrap_or_else(|| Some((1, 2))); | ^^^^^^^^^^^^^^^^^------------------------------- @@ -73,7 +73,7 @@ LL | let _ = nested_tuple_opt.unwrap_or_else(|| Some((1, 2))); | help: use `unwrap_or(..)` instead: `unwrap_or(Some((1, 2)))` error: unnecessary closure used with `bool::then` - --> $DIR/unnecessary_lazy_eval.rs:66:13 + --> $DIR/unnecessary_lazy_eval.rs:77:13 | LL | let _ = cond.then(|| astronomers_pi); | ^^^^^----------------------- @@ -81,7 +81,23 @@ LL | let _ = cond.then(|| astronomers_pi); | help: use `then_some(..)` instead: `then_some(astronomers_pi)` error: unnecessary closure used to substitute value for `Option::None` - --> $DIR/unnecessary_lazy_eval.rs:69:13 + --> $DIR/unnecessary_lazy_eval.rs:81:13 + | +LL | let _ = Some(1).unwrap_or_else(|| *r); + | ^^^^^^^^--------------------- + | | + | help: use `unwrap_or(..)` instead: `unwrap_or(*r)` + +error: unnecessary closure used to substitute value for `Option::None` + --> $DIR/unnecessary_lazy_eval.rs:83:13 + | +LL | let _ = Some(1).unwrap_or_else(|| *b); + | ^^^^^^^^--------------------- + | | + | help: use `unwrap_or(..)` instead: `unwrap_or(*b)` + +error: unnecessary closure used to substitute value for `Option::None` + --> $DIR/unnecessary_lazy_eval.rs:86:13 | LL | let _ = Some(10).unwrap_or_else(|| 2); | ^^^^^^^^^-------------------- @@ -89,7 +105,7 @@ LL | let _ = Some(10).unwrap_or_else(|| 2); | help: use `unwrap_or(..)` instead: `unwrap_or(2)` error: unnecessary closure used to substitute value for `Option::None` - --> $DIR/unnecessary_lazy_eval.rs:70:13 + --> $DIR/unnecessary_lazy_eval.rs:87:13 | LL | let _ = Some(10).and_then(|_| ext_opt); | ^^^^^^^^^--------------------- @@ -97,7 +113,7 @@ LL | let _ = Some(10).and_then(|_| ext_opt); | help: use `and(..)` instead: `and(ext_opt)` error: unnecessary closure used to substitute value for `Option::None` - --> $DIR/unnecessary_lazy_eval.rs:71:28 + --> $DIR/unnecessary_lazy_eval.rs:88:28 | LL | let _: Option = None.or_else(|| ext_opt); | ^^^^^------------------- @@ -105,7 +121,7 @@ LL | let _: Option = None.or_else(|| ext_opt); | help: use `or(..)` instead: `or(ext_opt)` error: unnecessary closure used to substitute value for `Option::None` - --> $DIR/unnecessary_lazy_eval.rs:72:13 + --> $DIR/unnecessary_lazy_eval.rs:89:13 | LL | let _ = None.get_or_insert_with(|| 2); | ^^^^^------------------------ @@ -113,7 +129,7 @@ LL | let _ = None.get_or_insert_with(|| 2); | help: use `get_or_insert(..)` instead: `get_or_insert(2)` error: unnecessary closure used to substitute value for `Option::None` - --> $DIR/unnecessary_lazy_eval.rs:73:35 + --> $DIR/unnecessary_lazy_eval.rs:90:35 | LL | let _: Result = None.ok_or_else(|| 2); | ^^^^^---------------- @@ -121,7 +137,7 @@ LL | let _: Result = None.ok_or_else(|| 2); | help: use `ok_or(..)` instead: `ok_or(2)` error: unnecessary closure used to substitute value for `Option::None` - --> $DIR/unnecessary_lazy_eval.rs:74:28 + --> $DIR/unnecessary_lazy_eval.rs:91:28 | LL | let _: Option = None.or_else(|| None); | ^^^^^---------------- @@ -129,7 +145,7 @@ LL | let _: Option = None.or_else(|| None); | help: use `or(..)` instead: `or(None)` error: unnecessary closure used to substitute value for `Option::None` - --> $DIR/unnecessary_lazy_eval.rs:77:13 + --> $DIR/unnecessary_lazy_eval.rs:94:13 | LL | let _ = deep.0.unwrap_or_else(|| 2); | ^^^^^^^-------------------- @@ -137,7 +153,7 @@ LL | let _ = deep.0.unwrap_or_else(|| 2); | help: use `unwrap_or(..)` instead: `unwrap_or(2)` error: unnecessary closure used to substitute value for `Option::None` - --> $DIR/unnecessary_lazy_eval.rs:78:13 + --> $DIR/unnecessary_lazy_eval.rs:95:13 | LL | let _ = deep.0.and_then(|_| ext_opt); | ^^^^^^^--------------------- @@ -145,7 +161,7 @@ LL | let _ = deep.0.and_then(|_| ext_opt); | help: use `and(..)` instead: `and(ext_opt)` error: unnecessary closure used to substitute value for `Option::None` - --> $DIR/unnecessary_lazy_eval.rs:79:13 + --> $DIR/unnecessary_lazy_eval.rs:96:13 | LL | let _ = deep.0.or_else(|| None); | ^^^^^^^---------------- @@ -153,7 +169,7 @@ LL | let _ = deep.0.or_else(|| None); | help: use `or(..)` instead: `or(None)` error: unnecessary closure used to substitute value for `Option::None` - --> $DIR/unnecessary_lazy_eval.rs:80:13 + --> $DIR/unnecessary_lazy_eval.rs:97:13 | LL | let _ = deep.0.get_or_insert_with(|| 2); | ^^^^^^^------------------------ @@ -161,7 +177,7 @@ LL | let _ = deep.0.get_or_insert_with(|| 2); | help: use `get_or_insert(..)` instead: `get_or_insert(2)` error: unnecessary closure used to substitute value for `Option::None` - --> $DIR/unnecessary_lazy_eval.rs:81:13 + --> $DIR/unnecessary_lazy_eval.rs:98:13 | LL | let _ = deep.0.ok_or_else(|| 2); | ^^^^^^^---------------- @@ -169,7 +185,7 @@ LL | let _ = deep.0.ok_or_else(|| 2); | help: use `ok_or(..)` instead: `ok_or(2)` error: unnecessary closure used to substitute value for `Option::None` - --> $DIR/unnecessary_lazy_eval.rs:105:28 + --> $DIR/unnecessary_lazy_eval.rs:125:28 | LL | let _: Option = None.or_else(|| Some(3)); | ^^^^^------------------- @@ -177,7 +193,7 @@ LL | let _: Option = None.or_else(|| Some(3)); | help: use `or(..)` instead: `or(Some(3))` error: unnecessary closure used to substitute value for `Option::None` - --> $DIR/unnecessary_lazy_eval.rs:106:13 + --> $DIR/unnecessary_lazy_eval.rs:126:13 | LL | let _ = deep.0.or_else(|| Some(3)); | ^^^^^^^------------------- @@ -185,7 +201,7 @@ LL | let _ = deep.0.or_else(|| Some(3)); | help: use `or(..)` instead: `or(Some(3))` error: unnecessary closure used to substitute value for `Option::None` - --> $DIR/unnecessary_lazy_eval.rs:107:13 + --> $DIR/unnecessary_lazy_eval.rs:127:13 | LL | let _ = opt.or_else(|| Some(3)); | ^^^^------------------- @@ -193,7 +209,7 @@ LL | let _ = opt.or_else(|| Some(3)); | help: use `or(..)` instead: `or(Some(3))` error: unnecessary closure used to substitute value for `Result::Err` - --> $DIR/unnecessary_lazy_eval.rs:113:13 + --> $DIR/unnecessary_lazy_eval.rs:133:13 | LL | let _ = res2.unwrap_or_else(|_| 2); | ^^^^^--------------------- @@ -201,7 +217,7 @@ LL | let _ = res2.unwrap_or_else(|_| 2); | help: use `unwrap_or(..)` instead: `unwrap_or(2)` error: unnecessary closure used to substitute value for `Result::Err` - --> $DIR/unnecessary_lazy_eval.rs:114:13 + --> $DIR/unnecessary_lazy_eval.rs:134:13 | LL | let _ = res2.unwrap_or_else(|_| astronomers_pi); | ^^^^^---------------------------------- @@ -209,7 +225,7 @@ LL | let _ = res2.unwrap_or_else(|_| astronomers_pi); | help: use `unwrap_or(..)` instead: `unwrap_or(astronomers_pi)` error: unnecessary closure used to substitute value for `Result::Err` - --> $DIR/unnecessary_lazy_eval.rs:115:13 + --> $DIR/unnecessary_lazy_eval.rs:135:13 | LL | let _ = res2.unwrap_or_else(|_| ext_str.some_field); | ^^^^^-------------------------------------- @@ -217,7 +233,7 @@ LL | let _ = res2.unwrap_or_else(|_| ext_str.some_field); | help: use `unwrap_or(..)` instead: `unwrap_or(ext_str.some_field)` error: unnecessary closure used to substitute value for `Result::Err` - --> $DIR/unnecessary_lazy_eval.rs:137:35 + --> $DIR/unnecessary_lazy_eval.rs:157:35 | LL | let _: Result = res.and_then(|_| Err(2)); | ^^^^-------------------- @@ -225,7 +241,7 @@ LL | let _: Result = res.and_then(|_| Err(2)); | help: use `and(..)` instead: `and(Err(2))` error: unnecessary closure used to substitute value for `Result::Err` - --> $DIR/unnecessary_lazy_eval.rs:138:35 + --> $DIR/unnecessary_lazy_eval.rs:158:35 | LL | let _: Result = res.and_then(|_| Err(astronomers_pi)); | ^^^^--------------------------------- @@ -233,7 +249,7 @@ LL | let _: Result = res.and_then(|_| Err(astronomers_pi)); | help: use `and(..)` instead: `and(Err(astronomers_pi))` error: unnecessary closure used to substitute value for `Result::Err` - --> $DIR/unnecessary_lazy_eval.rs:139:35 + --> $DIR/unnecessary_lazy_eval.rs:159:35 | LL | let _: Result = res.and_then(|_| Err(ext_str.some_field)); | ^^^^------------------------------------- @@ -241,7 +257,7 @@ LL | let _: Result = res.and_then(|_| Err(ext_str.some_field)) | help: use `and(..)` instead: `and(Err(ext_str.some_field))` error: unnecessary closure used to substitute value for `Result::Err` - --> $DIR/unnecessary_lazy_eval.rs:141:35 + --> $DIR/unnecessary_lazy_eval.rs:161:35 | LL | let _: Result = res.or_else(|_| Ok(2)); | ^^^^------------------ @@ -249,7 +265,7 @@ LL | let _: Result = res.or_else(|_| Ok(2)); | help: use `or(..)` instead: `or(Ok(2))` error: unnecessary closure used to substitute value for `Result::Err` - --> $DIR/unnecessary_lazy_eval.rs:142:35 + --> $DIR/unnecessary_lazy_eval.rs:162:35 | LL | let _: Result = res.or_else(|_| Ok(astronomers_pi)); | ^^^^------------------------------- @@ -257,7 +273,7 @@ LL | let _: Result = res.or_else(|_| Ok(astronomers_pi)); | help: use `or(..)` instead: `or(Ok(astronomers_pi))` error: unnecessary closure used to substitute value for `Result::Err` - --> $DIR/unnecessary_lazy_eval.rs:143:35 + --> $DIR/unnecessary_lazy_eval.rs:163:35 | LL | let _: Result = res.or_else(|_| Ok(ext_str.some_field)); | ^^^^----------------------------------- @@ -265,7 +281,7 @@ LL | let _: Result = res.or_else(|_| Ok(ext_str.some_field)); | help: use `or(..)` instead: `or(Ok(ext_str.some_field))` error: unnecessary closure used to substitute value for `Result::Err` - --> $DIR/unnecessary_lazy_eval.rs:144:35 + --> $DIR/unnecessary_lazy_eval.rs:164:35 | LL | let _: Result = res. | ___________________________________^ @@ -279,5 +295,5 @@ LL | | or_else(|_| Ok(ext_str.some_field)); | | | help: use `or(..)` instead: `or(Ok(ext_str.some_field))` -error: aborting due to 34 previous errors +error: aborting due to 36 previous errors From 0cc1454db5d9b47ac247de31de8b545b9ae5be39 Mon Sep 17 00:00:00 2001 From: Centri3 <114838443+Centri3@users.noreply.github.com> Date: Thu, 1 Jun 2023 18:13:01 -0500 Subject: [PATCH 040/310] Fix #10498 --- clippy_lints/src/let_with_type_underscore.rs | 9 +++++++-- tests/ui/let_with_type_underscore.rs | 9 +++++++++ tests/ui/let_with_type_underscore.stderr | 12 ++++++------ 3 files changed, 22 insertions(+), 8 deletions(-) diff --git a/clippy_lints/src/let_with_type_underscore.rs b/clippy_lints/src/let_with_type_underscore.rs index 2f10e3d2581..8fcf42564d5 100644 --- a/clippy_lints/src/let_with_type_underscore.rs +++ b/clippy_lints/src/let_with_type_underscore.rs @@ -1,4 +1,4 @@ -use clippy_utils::diagnostics::span_lint_and_help; +use clippy_utils::{diagnostics::span_lint_and_help, is_from_proc_macro}; use rustc_hir::{Local, TyKind}; use rustc_lint::{LateContext, LateLintPass}; use rustc_middle::lint::in_external_macro; @@ -32,7 +32,12 @@ impl LateLintPass<'_> for UnderscoreTyped { if let TyKind::Infer = &ty.kind; // that type is '_' if local.span.ctxt() == ty.span.ctxt(); then { - span_lint_and_help(cx, + if let Some(init) = local.init && is_from_proc_macro(cx, init) { + return; + } + + span_lint_and_help( + cx, LET_WITH_TYPE_UNDERSCORE, local.span, "variable declared with type underscore", diff --git a/tests/ui/let_with_type_underscore.rs b/tests/ui/let_with_type_underscore.rs index 7c1835e8cd1..832d0304ffa 100644 --- a/tests/ui/let_with_type_underscore.rs +++ b/tests/ui/let_with_type_underscore.rs @@ -1,7 +1,10 @@ +//@aux-build: proc_macros.rs #![allow(unused)] #![warn(clippy::let_with_type_underscore)] #![allow(clippy::let_unit_value)] +extern crate proc_macros; + fn func() -> &'static str { "" } @@ -16,4 +19,10 @@ fn main() { let x = func(); let x: Vec<_> = Vec::::new(); let x: [_; 1] = [1]; + + // do not lint from procedural macros + proc_macros::with_span! { + span + let x: _ = (); + }; } diff --git a/tests/ui/let_with_type_underscore.stderr b/tests/ui/let_with_type_underscore.stderr index 16bf83c708f..26400363f5d 100644 --- a/tests/ui/let_with_type_underscore.stderr +++ b/tests/ui/let_with_type_underscore.stderr @@ -1,36 +1,36 @@ error: variable declared with type underscore - --> $DIR/let_with_type_underscore.rs:11:5 + --> $DIR/let_with_type_underscore.rs:14:5 | LL | let x: _ = 1; | ^^^^^^^^^^^^^ | help: remove the explicit type `_` declaration - --> $DIR/let_with_type_underscore.rs:11:10 + --> $DIR/let_with_type_underscore.rs:14:10 | LL | let x: _ = 1; | ^^^ = note: `-D clippy::let-with-type-underscore` implied by `-D warnings` error: variable declared with type underscore - --> $DIR/let_with_type_underscore.rs:12:5 + --> $DIR/let_with_type_underscore.rs:15:5 | LL | let _: _ = 2; | ^^^^^^^^^^^^^ | help: remove the explicit type `_` declaration - --> $DIR/let_with_type_underscore.rs:12:10 + --> $DIR/let_with_type_underscore.rs:15:10 | LL | let _: _ = 2; | ^^^ error: variable declared with type underscore - --> $DIR/let_with_type_underscore.rs:13:5 + --> $DIR/let_with_type_underscore.rs:16:5 | LL | let x: _ = func(); | ^^^^^^^^^^^^^^^^^^ | help: remove the explicit type `_` declaration - --> $DIR/let_with_type_underscore.rs:13:10 + --> $DIR/let_with_type_underscore.rs:16:10 | LL | let x: _ = func(); | ^^^ From 0086b6ab0a5a9a6a8e500f5742886097ed453a6d Mon Sep 17 00:00:00 2001 From: Centri3 <114838443+Centri3@users.noreply.github.com> Date: Thu, 1 Jun 2023 20:24:41 -0500 Subject: [PATCH 041/310] don't lint `allow_attributes` on attributes from proc macros --- clippy_lints/src/allow_attributes.rs | 3 +- clippy_lints/src/attrs.rs | 9 ++-- clippy_utils/src/check_proc_macro.rs | 44 ++++++++++++++++++- tests/ui/allow_attributes.fixed | 22 +++++++++- tests/ui/allow_attributes.rs | 20 ++++++++- tests/ui/allow_attributes.stderr | 10 +---- tests/ui/allow_attributes_false_positive.rs | 5 --- tests/ui/allow_attributes_without_reason.rs | 18 +++++++- .../ui/allow_attributes_without_reason.stderr | 28 +++++++++--- 9 files changed, 131 insertions(+), 28 deletions(-) delete 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 554efdc58e1..69ccbeb7b06 100644 --- a/clippy_lints/src/allow_attributes.rs +++ b/clippy_lints/src/allow_attributes.rs @@ -1,5 +1,5 @@ use ast::AttrStyle; -use clippy_utils::diagnostics::span_lint_and_sugg; +use clippy_utils::{diagnostics::span_lint_and_sugg, is_from_proc_macro}; use rustc_ast as ast; use rustc_errors::Applicability; use rustc_lint::{LateContext, LateLintPass, LintContext}; @@ -57,6 +57,7 @@ impl LateLintPass<'_> for AllowAttribute { if let AttrStyle::Outer = attr.style; if let Some(ident) = attr.ident(); if ident.name == rustc_span::symbol::sym::allow; + if !is_from_proc_macro(cx, &(attr, cx)); then { span_lint_and_sugg( cx, diff --git a/clippy_lints/src/attrs.rs b/clippy_lints/src/attrs.rs index 897495ba108..e989cde0f3c 100644 --- a/clippy_lints/src/attrs.rs +++ b/clippy_lints/src/attrs.rs @@ -1,9 +1,12 @@ //! checks for attributes -use clippy_utils::diagnostics::{span_lint, span_lint_and_help, span_lint_and_sugg, span_lint_and_then}; use clippy_utils::macros::{is_panic, macro_backtrace}; use clippy_utils::msrvs::{self, Msrv}; use clippy_utils::source::{first_line_of_span, is_present_in_source, snippet_opt, without_block_comments}; +use clippy_utils::{ + diagnostics::{span_lint, span_lint_and_help, span_lint_and_sugg, span_lint_and_then}, + is_from_proc_macro, +}; use if_chain::if_chain; use rustc_ast::{AttrKind, AttrStyle, Attribute, LitKind, MetaItemKind, MetaItemLit, NestedMetaItem}; use rustc_errors::Applicability; @@ -540,7 +543,7 @@ fn check_clippy_lint_names(cx: &LateContext<'_>, name: Symbol, items: &[NestedMe } } -fn check_lint_reason(cx: &LateContext<'_>, name: Symbol, items: &[NestedMetaItem], attr: &'_ Attribute) { +fn check_lint_reason(cx: &LateContext<'_>, name: Symbol, items: &[NestedMetaItem], attr: &Attribute) { // Check for the feature if !cx.tcx.features().lint_reasons { return; @@ -555,7 +558,7 @@ fn check_lint_reason(cx: &LateContext<'_>, name: Symbol, items: &[NestedMetaItem } // Check if the attribute is in an external macro and therefore out of the developer's control - if in_external_macro(cx.sess(), attr.span) { + if in_external_macro(cx.sess(), attr.span) || is_from_proc_macro(cx, &(attr, cx)) { return; } diff --git a/clippy_utils/src/check_proc_macro.rs b/clippy_utils/src/check_proc_macro.rs index 9edaae85373..8a8ccc30205 100644 --- a/clippy_utils/src/check_proc_macro.rs +++ b/clippy_utils/src/check_proc_macro.rs @@ -12,7 +12,11 @@ //! code was written, and check if the span contains that text. Note this will only work correctly //! if the span is not from a `macro_rules` based macro. -use rustc_ast::ast::{IntTy, LitIntType, LitKind, StrStyle, UintTy}; +use rustc_ast::{ + ast::{AttrKind, Attribute, IntTy, LitIntType, LitKind, StrStyle, UintTy}, + token::CommentKind, + AttrStyle, +}; use rustc_hir::{ intravisit::FnKind, Block, BlockCheckMode, Body, Closure, Destination, Expr, ExprKind, FieldDef, FnHeader, HirId, Impl, ImplItem, ImplItemKind, IsAuto, Item, ItemKind, LoopSource, MatchSource, Node, QPath, TraitItem, @@ -271,6 +275,32 @@ fn fn_kind_pat(tcx: TyCtxt<'_>, kind: &FnKind<'_>, body: &Body<'_>, hir_id: HirI (start_pat, end_pat) } +fn attr_search_pat(attr: &Attribute) -> (Pat, Pat) { + match attr.kind { + AttrKind::Normal(..) => { + if matches!(attr.style, AttrStyle::Outer) { + (Pat::Str("#["), Pat::Str("]")) + } else { + (Pat::Str("#!["), Pat::Str("]")) + } + }, + AttrKind::DocComment(_kind @ CommentKind::Line, ..) => { + if matches!(attr.style, AttrStyle::Outer) { + (Pat::Str("///"), Pat::Str("")) + } else { + (Pat::Str("//!"), Pat::Str("")) + } + }, + AttrKind::DocComment(_kind @ CommentKind::Block, ..) => { + if matches!(attr.style, AttrStyle::Outer) { + (Pat::Str("/**"), Pat::Str("*/")) + } else { + (Pat::Str("/*!"), Pat::Str("*/")) + } + }, + } +} + pub trait WithSearchPat { type Context: LintContext; fn search_pat(&self, cx: &Self::Context) -> (Pat, Pat); @@ -310,6 +340,18 @@ impl<'cx> WithSearchPat for (&FnKind<'cx>, &Body<'cx>, HirId, Span) { } } +impl<'cx> WithSearchPat for (&Attribute, &LateContext<'cx>) { + type Context = LateContext<'cx>; + + fn search_pat(&self, _cx: &Self::Context) -> (Pat, Pat) { + attr_search_pat(&self.0) + } + + fn span(&self) -> Span { + self.0.span + } +} + /// Checks if the item likely came from a proc-macro. /// /// This should be called after `in_external_macro` and the initial pattern matching of the ast as diff --git a/tests/ui/allow_attributes.fixed b/tests/ui/allow_attributes.fixed index f0936b2608e..be93c5bffe7 100644 --- a/tests/ui/allow_attributes.fixed +++ b/tests/ui/allow_attributes.fixed @@ -1,9 +1,12 @@ //@run-rustfix +//@aux-build:proc_macros.rs #![allow(unused)] #![warn(clippy::allow_attributes)] #![feature(lint_reasons)] +#![no_main] -fn main() {} +extern crate proc_macros; +use proc_macros::{external, with_span}; // Using clippy::needless_borrow just as a placeholder, it isn't relevant. @@ -17,9 +20,24 @@ struct T3; #[warn(clippy::needless_borrow)] // Should not lint struct T4; // `panic = "unwind"` should always be true -#[cfg_attr(panic = "unwind", expect(dead_code))] +#[cfg_attr(panic = "unwind", allow(dead_code))] struct CfgT; +fn ignore_external() { + external! { + #[allow(clippy::needless_borrow)] + fn a() {} + } +} + +fn ignore_proc_macro() { + with_span! { + span + #[allow(clippy::needless_borrow)] // Should not lint + fn a() {} + } +} + fn ignore_inner_attr() { #![allow(unused)] // Should not lint } diff --git a/tests/ui/allow_attributes.rs b/tests/ui/allow_attributes.rs index 2fb9e86126e..10d2ed1a8a9 100644 --- a/tests/ui/allow_attributes.rs +++ b/tests/ui/allow_attributes.rs @@ -1,9 +1,12 @@ //@run-rustfix +//@aux-build:proc_macros.rs #![allow(unused)] #![warn(clippy::allow_attributes)] #![feature(lint_reasons)] +#![no_main] -fn main() {} +extern crate proc_macros; +use proc_macros::{external, with_span}; // Using clippy::needless_borrow just as a placeholder, it isn't relevant. @@ -20,6 +23,21 @@ struct T4; #[cfg_attr(panic = "unwind", allow(dead_code))] struct CfgT; +fn ignore_external() { + external! { + #[allow(clippy::needless_borrow)] // Should not lint + fn a() {} + } +} + +fn ignore_proc_macro() { + with_span! { + span + #[allow(clippy::needless_borrow)] // Should not lint + fn a() {} + } +} + fn ignore_inner_attr() { #![allow(unused)] // Should not lint } diff --git a/tests/ui/allow_attributes.stderr b/tests/ui/allow_attributes.stderr index 681837e9ed7..37149104a47 100644 --- a/tests/ui/allow_attributes.stderr +++ b/tests/ui/allow_attributes.stderr @@ -1,16 +1,10 @@ error: #[allow] attribute found - --> $DIR/allow_attributes.rs:11:3 + --> $DIR/allow_attributes.rs:14:3 | LL | #[allow(dead_code)] | ^^^^^ help: replace it with: `expect` | = note: `-D clippy::allow-attributes` implied by `-D warnings` -error: #[allow] attribute found - --> $DIR/allow_attributes.rs:20:30 - | -LL | #[cfg_attr(panic = "unwind", allow(dead_code))] - | ^^^^^ help: replace it with: `expect` - -error: aborting due to 2 previous errors +error: aborting due to previous error diff --git a/tests/ui/allow_attributes_false_positive.rs b/tests/ui/allow_attributes_false_positive.rs deleted file mode 100644 index 5c3407628be..00000000000 --- a/tests/ui/allow_attributes_false_positive.rs +++ /dev/null @@ -1,5 +0,0 @@ -#![warn(clippy::allow_attributes)] -#![feature(lint_reasons)] -#![crate_type = "proc-macro"] - -fn main() {} diff --git a/tests/ui/allow_attributes_without_reason.rs b/tests/ui/allow_attributes_without_reason.rs index 1a0d4e88657..95a9fa2aa47 100644 --- a/tests/ui/allow_attributes_without_reason.rs +++ b/tests/ui/allow_attributes_without_reason.rs @@ -1,9 +1,15 @@ +//@aux-build:proc_macros.rs #![feature(lint_reasons)] #![deny(clippy::allow_attributes_without_reason)] +#![allow(unfulfilled_lint_expectations)] + +extern crate proc_macros; +use proc_macros::{external, with_span}; // These should trigger the lint #[allow(dead_code)] #[allow(dead_code, deprecated)] +#[expect(dead_code)] // These should be fine #[allow(dead_code, reason = "This should be allowed")] #[warn(dyn_drop, reason = "Warnings can also have reasons")] @@ -11,4 +17,14 @@ #[deny(deref_nullptr)] #[forbid(deref_nullptr)] -fn main() {} +fn main() { + external! { + #[allow(dead_code)] + fn a() {} + } + with_span! { + span + #[allow(dead_code)] + fn b() {} + } +} diff --git a/tests/ui/allow_attributes_without_reason.stderr b/tests/ui/allow_attributes_without_reason.stderr index 23f17e9a7af..96f747d0026 100644 --- a/tests/ui/allow_attributes_without_reason.stderr +++ b/tests/ui/allow_attributes_without_reason.stderr @@ -1,23 +1,39 @@ error: `allow` attribute without specifying a reason - --> $DIR/allow_attributes_without_reason.rs:5:1 + --> $DIR/allow_attributes_without_reason.rs:4:1 | -LL | #[allow(dead_code)] - | ^^^^^^^^^^^^^^^^^^^ +LL | #![allow(unfulfilled_lint_expectations)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = help: try adding a reason at the end with `, reason = ".."` note: the lint level is defined here - --> $DIR/allow_attributes_without_reason.rs:2:9 + --> $DIR/allow_attributes_without_reason.rs:3:9 | LL | #![deny(clippy::allow_attributes_without_reason)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: `allow` attribute without specifying a reason - --> $DIR/allow_attributes_without_reason.rs:6:1 + --> $DIR/allow_attributes_without_reason.rs:10:1 + | +LL | #[allow(dead_code)] + | ^^^^^^^^^^^^^^^^^^^ + | + = help: try adding a reason at the end with `, reason = ".."` + +error: `allow` attribute without specifying a reason + --> $DIR/allow_attributes_without_reason.rs:11:1 | LL | #[allow(dead_code, deprecated)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = help: try adding a reason at the end with `, reason = ".."` -error: aborting due to 2 previous errors +error: `expect` attribute without specifying a reason + --> $DIR/allow_attributes_without_reason.rs:12:1 + | +LL | #[expect(dead_code)] + | ^^^^^^^^^^^^^^^^^^^^ + | + = help: try adding a reason at the end with `, reason = ".."` + +error: aborting due to 4 previous errors From ab70553a387a5689170d2f075849ee345bc72a90 Mon Sep 17 00:00:00 2001 From: Centri3 <114838443+Centri3@users.noreply.github.com> Date: Thu, 1 Jun 2023 20:32:08 -0500 Subject: [PATCH 042/310] foiled again (forgot to run cargo test) --- clippy_utils/src/check_proc_macro.rs | 2 +- tests/ui/allow_attributes.fixed | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/clippy_utils/src/check_proc_macro.rs b/clippy_utils/src/check_proc_macro.rs index 8a8ccc30205..e0dbc1c9701 100644 --- a/clippy_utils/src/check_proc_macro.rs +++ b/clippy_utils/src/check_proc_macro.rs @@ -344,7 +344,7 @@ impl<'cx> WithSearchPat for (&Attribute, &LateContext<'cx>) { type Context = LateContext<'cx>; fn search_pat(&self, _cx: &Self::Context) -> (Pat, Pat) { - attr_search_pat(&self.0) + attr_search_pat(self.0) } fn span(&self) -> Span { diff --git a/tests/ui/allow_attributes.fixed b/tests/ui/allow_attributes.fixed index be93c5bffe7..5c30a9d2941 100644 --- a/tests/ui/allow_attributes.fixed +++ b/tests/ui/allow_attributes.fixed @@ -25,7 +25,7 @@ struct CfgT; fn ignore_external() { external! { - #[allow(clippy::needless_borrow)] + #[allow(clippy::needless_borrow)] // Should not lint fn a() {} } } From 497f37793e54a689d24983c2fbbc40d1255c4755 Mon Sep 17 00:00:00 2001 From: Centri3 <114838443+Centri3@users.noreply.github.com> Date: Thu, 1 Jun 2023 21:26:41 -0500 Subject: [PATCH 043/310] Fix `attr_search_pat` for `#[cfg_attr]` --- clippy_utils/src/check_proc_macro.rs | 22 ++++++++++++++++++++-- tests/ui/allow_attributes.fixed | 2 +- tests/ui/allow_attributes.stderr | 8 +++++++- 3 files changed, 28 insertions(+), 4 deletions(-) diff --git a/clippy_utils/src/check_proc_macro.rs b/clippy_utils/src/check_proc_macro.rs index e0dbc1c9701..fd04f2ddf7c 100644 --- a/clippy_utils/src/check_proc_macro.rs +++ b/clippy_utils/src/check_proc_macro.rs @@ -29,12 +29,16 @@ use rustc_span::{Span, Symbol}; use rustc_target::spec::abi::Abi; /// The search pattern to look for. Used by `span_matches_pat` -#[derive(Clone, Copy)] +#[derive(Clone)] pub enum Pat { /// A single string. Str(&'static str), + /// A single string. + OwnedStr(String), /// Any of the given strings. MultiStr(&'static [&'static str]), + /// Any of the given strings. + OwnedMultiStr(Vec), /// The string representation of the symbol. Sym(Symbol), /// Any decimal or hexadecimal digit depending on the location. @@ -55,12 +59,16 @@ fn span_matches_pat(sess: &Session, span: Span, start_pat: Pat, end_pat: Pat) -> let end_str = s.trim_end_matches(|c: char| c.is_whitespace() || c == ')' || c == ','); (match start_pat { Pat::Str(text) => start_str.starts_with(text), + Pat::OwnedStr(text) => start_str.starts_with(&text), Pat::MultiStr(texts) => texts.iter().any(|s| start_str.starts_with(s)), + Pat::OwnedMultiStr(texts) => texts.iter().any(|s| start_str.starts_with(s)), Pat::Sym(sym) => start_str.starts_with(sym.as_str()), Pat::Num => start_str.as_bytes().first().map_or(false, u8::is_ascii_digit), } && match end_pat { Pat::Str(text) => end_str.ends_with(text), + Pat::OwnedStr(text) => end_str.starts_with(&text), Pat::MultiStr(texts) => texts.iter().any(|s| start_str.ends_with(s)), + Pat::OwnedMultiStr(texts) => texts.iter().any(|s| start_str.starts_with(s)), Pat::Sym(sym) => end_str.ends_with(sym.as_str()), Pat::Num => end_str.as_bytes().last().map_or(false, u8::is_ascii_hexdigit), }) @@ -278,11 +286,21 @@ fn fn_kind_pat(tcx: TyCtxt<'_>, kind: &FnKind<'_>, body: &Body<'_>, hir_id: HirI fn attr_search_pat(attr: &Attribute) -> (Pat, Pat) { match attr.kind { AttrKind::Normal(..) => { - if matches!(attr.style, AttrStyle::Outer) { + let mut pat = if matches!(attr.style, AttrStyle::Outer) { (Pat::Str("#["), Pat::Str("]")) } else { (Pat::Str("#!["), Pat::Str("]")) + }; + + if let Some(ident) = attr.ident() && let Pat::Str(old_pat) = pat.0 { + // TODO: I feel like it's likely we can use `Cow` instead but this will require quite a bit of + // refactoring + // NOTE: This will likely have false positives, like `allow = 1` + pat.0 = Pat::OwnedMultiStr(vec![ident.to_string(), old_pat.to_owned()]); + pat.1 = Pat::Str(""); } + + pat }, AttrKind::DocComment(_kind @ CommentKind::Line, ..) => { if matches!(attr.style, AttrStyle::Outer) { diff --git a/tests/ui/allow_attributes.fixed b/tests/ui/allow_attributes.fixed index 5c30a9d2941..fa04f53ca91 100644 --- a/tests/ui/allow_attributes.fixed +++ b/tests/ui/allow_attributes.fixed @@ -20,7 +20,7 @@ struct T3; #[warn(clippy::needless_borrow)] // Should not lint struct T4; // `panic = "unwind"` should always be true -#[cfg_attr(panic = "unwind", allow(dead_code))] +#[cfg_attr(panic = "unwind", expect(dead_code))] struct CfgT; fn ignore_external() { diff --git a/tests/ui/allow_attributes.stderr b/tests/ui/allow_attributes.stderr index 37149104a47..d17fd86cb86 100644 --- a/tests/ui/allow_attributes.stderr +++ b/tests/ui/allow_attributes.stderr @@ -6,5 +6,11 @@ LL | #[allow(dead_code)] | = note: `-D clippy::allow-attributes` implied by `-D warnings` -error: aborting due to previous error +error: #[allow] attribute found + --> $DIR/allow_attributes.rs:23:30 + | +LL | #[cfg_attr(panic = "unwind", allow(dead_code))] + | ^^^^^ help: replace it with: `expect` + +error: aborting due to 2 previous errors From 143ff2dfc307b34f2d277c02b3415f384ad3d950 Mon Sep 17 00:00:00 2001 From: Centri3 <114838443+Centri3@users.noreply.github.com> Date: Thu, 1 Jun 2023 22:29:06 -0500 Subject: [PATCH 044/310] Use type snippet instead of init expr for proc macro check --- clippy_lints/src/let_with_type_underscore.rs | 12 +++++-- tests/ui/let_with_type_underscore.rs | 18 ++++++++-- tests/ui/let_with_type_underscore.stderr | 38 ++++++++++++++++---- 3 files changed, 56 insertions(+), 12 deletions(-) diff --git a/clippy_lints/src/let_with_type_underscore.rs b/clippy_lints/src/let_with_type_underscore.rs index 8fcf42564d5..4f8c5ff58b5 100644 --- a/clippy_lints/src/let_with_type_underscore.rs +++ b/clippy_lints/src/let_with_type_underscore.rs @@ -1,4 +1,5 @@ -use clippy_utils::{diagnostics::span_lint_and_help, is_from_proc_macro}; +use clippy_utils::diagnostics::span_lint_and_help; +use clippy_utils::source::snippet; use rustc_hir::{Local, TyKind}; use rustc_lint::{LateContext, LateLintPass}; use rustc_middle::lint::in_external_macro; @@ -32,7 +33,12 @@ impl LateLintPass<'_> for UnderscoreTyped { if let TyKind::Infer = &ty.kind; // that type is '_' if local.span.ctxt() == ty.span.ctxt(); then { - if let Some(init) = local.init && is_from_proc_macro(cx, init) { + let underscore_span = ty.span.with_lo(local.pat.span.hi()); + let snippet = snippet(cx, underscore_span, ": _"); + + // NOTE: Using `is_from_proc_macro` on `init` will require that it's initialized, + // this doesn't. Alternatively, `WithSearchPat` can be implemented for `Ty` + if !snippet.trim().starts_with(':') && !snippet.trim().ends_with('_') { return; } @@ -41,7 +47,7 @@ impl LateLintPass<'_> for UnderscoreTyped { LET_WITH_TYPE_UNDERSCORE, local.span, "variable declared with type underscore", - Some(ty.span.with_lo(local.pat.span.hi())), + Some(underscore_span), "remove the explicit type `_` declaration" ) } diff --git a/tests/ui/let_with_type_underscore.rs b/tests/ui/let_with_type_underscore.rs index 832d0304ffa..ae1a480bcfc 100644 --- a/tests/ui/let_with_type_underscore.rs +++ b/tests/ui/let_with_type_underscore.rs @@ -1,7 +1,7 @@ //@aux-build: proc_macros.rs #![allow(unused)] #![warn(clippy::let_with_type_underscore)] -#![allow(clippy::let_unit_value)] +#![allow(clippy::let_unit_value, clippy::needless_late_init)] extern crate proc_macros; @@ -9,20 +9,34 @@ fn func() -> &'static str { "" } +#[rustfmt::skip] fn main() { // Will lint let x: _ = 1; let _: _ = 2; let x: _ = func(); + let x: _; + x = (); 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]; + let x : _ = 1; - // do not lint from procedural macros + // Do not lint from procedural macros proc_macros::with_span! { span let x: _ = (); + // Late initialization + let x: _; + x = (); + // Ensure weird formatting will not break it (hopefully) + let x : _ = 1; + let x +: _ = 1; + let x : + _; + x = (); }; } diff --git a/tests/ui/let_with_type_underscore.stderr b/tests/ui/let_with_type_underscore.stderr index 26400363f5d..a749552c7fa 100644 --- a/tests/ui/let_with_type_underscore.stderr +++ b/tests/ui/let_with_type_underscore.stderr @@ -1,39 +1,63 @@ error: variable declared with type underscore - --> $DIR/let_with_type_underscore.rs:14:5 + --> $DIR/let_with_type_underscore.rs:15:5 | LL | let x: _ = 1; | ^^^^^^^^^^^^^ | help: remove the explicit type `_` declaration - --> $DIR/let_with_type_underscore.rs:14:10 + --> $DIR/let_with_type_underscore.rs:15:10 | LL | let x: _ = 1; | ^^^ = note: `-D clippy::let-with-type-underscore` implied by `-D warnings` error: variable declared with type underscore - --> $DIR/let_with_type_underscore.rs:15:5 + --> $DIR/let_with_type_underscore.rs:16:5 | LL | let _: _ = 2; | ^^^^^^^^^^^^^ | help: remove the explicit type `_` declaration - --> $DIR/let_with_type_underscore.rs:15:10 + --> $DIR/let_with_type_underscore.rs:16:10 | LL | let _: _ = 2; | ^^^ error: variable declared with type underscore - --> $DIR/let_with_type_underscore.rs:16:5 + --> $DIR/let_with_type_underscore.rs:17:5 | LL | let x: _ = func(); | ^^^^^^^^^^^^^^^^^^ | help: remove the explicit type `_` declaration - --> $DIR/let_with_type_underscore.rs:16:10 + --> $DIR/let_with_type_underscore.rs:17:10 | LL | let x: _ = func(); | ^^^ -error: aborting due to 3 previous errors +error: variable declared with type underscore + --> $DIR/let_with_type_underscore.rs:18:5 + | +LL | let x: _; + | ^^^^^^^^^ + | +help: remove the explicit type `_` declaration + --> $DIR/let_with_type_underscore.rs:18:10 + | +LL | let x: _; + | ^^^ + +error: variable declared with type underscore + --> $DIR/let_with_type_underscore.rs:25:5 + | +LL | let x : _ = 1; + | ^^^^^^^^^^^^^^ + | +help: remove the explicit type `_` declaration + --> $DIR/let_with_type_underscore.rs:25:10 + | +LL | let x : _ = 1; + | ^^^^ + +error: aborting due to 5 previous errors From ad76687b2f2cf041190ca44f7a53d89f84ac552b Mon Sep 17 00:00:00 2001 From: ihciah Date: Thu, 1 Jun 2023 14:11:28 +0000 Subject: [PATCH 045/310] add checking for cfg(features = ...) --- CHANGELOG.md | 1 + clippy_lints/src/attrs.rs | 57 ++++++++++++++++++++++++++++++ clippy_lints/src/declared_lints.rs | 1 + tests/ui/cfg_features.rs | 12 +++++++ tests/ui/cfg_features.stderr | 28 +++++++++++++++ 5 files changed, 99 insertions(+) create mode 100644 tests/ui/cfg_features.rs create mode 100644 tests/ui/cfg_features.stderr diff --git a/CHANGELOG.md b/CHANGELOG.md index 8b609b47d81..fd619368e8f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4947,6 +4947,7 @@ Released 2018-09-13 [`match_wild_err_arm`]: https://rust-lang.github.io/rust-clippy/master/index.html#match_wild_err_arm [`match_wildcard_for_single_variants`]: https://rust-lang.github.io/rust-clippy/master/index.html#match_wildcard_for_single_variants [`maybe_infinite_iter`]: https://rust-lang.github.io/rust-clippy/master/index.html#maybe_infinite_iter +[`maybe_misused_cfg`]: https://rust-lang.github.io/rust-clippy/master/index.html#maybe_misused_cfg [`mem_discriminant_non_enum`]: https://rust-lang.github.io/rust-clippy/master/index.html#mem_discriminant_non_enum [`mem_forget`]: https://rust-lang.github.io/rust-clippy/master/index.html#mem_forget [`mem_replace_option_with_none`]: https://rust-lang.github.io/rust-clippy/master/index.html#mem_replace_option_with_none diff --git a/clippy_lints/src/attrs.rs b/clippy_lints/src/attrs.rs index 897495ba108..891ee8af82b 100644 --- a/clippy_lints/src/attrs.rs +++ b/clippy_lints/src/attrs.rs @@ -362,6 +362,32 @@ declare_clippy_lint! { "ensure that all `cfg(any())` and `cfg(all())` have more than one condition" } +declare_clippy_lint! { + /// ### What it does + /// Checks for `#[cfg(features = "...")]` and suggests to replace it with + /// `#[cfg(feature = "...")]`. + /// + /// ### Why is this bad? + /// Misspelling `feature` as `features` can be sometimes hard to spot. It + /// may cause conditional compilation not work quitely. + /// + /// ### Example + /// ```rust + /// #[cfg(features = "some-feature")] + /// fn conditional() { } + /// ``` + /// + /// Use instead: + /// ```rust + /// #[cfg(feature = "some-feature")] + /// fn conditional() { } + /// ``` + #[clippy::version = "1.69.0"] + pub MAYBE_MISUSED_CFG, + suspicious, + "prevent from misusing the wrong attr name" +} + declare_lint_pass!(Attributes => [ ALLOW_ATTRIBUTES_WITHOUT_REASON, INLINE_ALWAYS, @@ -676,6 +702,7 @@ impl_lint_pass!(EarlyAttributes => [ EMPTY_LINE_AFTER_OUTER_ATTR, EMPTY_LINE_AFTER_DOC_COMMENTS, NON_MINIMAL_CFG, + MAYBE_MISUSED_CFG, ]); impl EarlyLintPass for EarlyAttributes { @@ -687,6 +714,7 @@ impl EarlyLintPass for EarlyAttributes { check_deprecated_cfg_attr(cx, attr, &self.msrv); check_mismatched_target_os(cx, attr); check_minimal_cfg_condition(cx, attr); + check_misused_cfg(cx, attr); } extract_msrv_attr!(EarlyContext); @@ -810,6 +838,27 @@ fn check_nested_cfg(cx: &EarlyContext<'_>, items: &[NestedMetaItem]) { } } +fn check_nested_misused_cfg(cx: &EarlyContext<'_>, items: &[NestedMetaItem]) { + for item in items.iter() { + if let NestedMetaItem::MetaItem(meta) = item { + if meta.has_name(sym!(features)) && let Some(val) = meta.value_str() { + span_lint_and_sugg( + cx, + MAYBE_MISUSED_CFG, + meta.span, + "feature may misspelled as features", + "use", + format!("feature = \"{val}\""), + Applicability::MaybeIncorrect, + ); + } + if let MetaItemKind::List(list) = &meta.kind { + check_nested_misused_cfg(cx, list); + } + } + } +} + fn check_minimal_cfg_condition(cx: &EarlyContext<'_>, attr: &Attribute) { if attr.has_name(sym::cfg) && let Some(items) = attr.meta_item_list() @@ -818,6 +867,14 @@ fn check_minimal_cfg_condition(cx: &EarlyContext<'_>, attr: &Attribute) { } } +fn check_misused_cfg(cx: &EarlyContext<'_>, attr: &Attribute) { + if attr.has_name(sym::cfg) && + let Some(items) = attr.meta_item_list() + { + check_nested_misused_cfg(cx, &items); + } +} + fn check_mismatched_target_os(cx: &EarlyContext<'_>, attr: &Attribute) { fn find_os(name: &str) -> Option<&'static str> { UNIX_SYSTEMS diff --git a/clippy_lints/src/declared_lints.rs b/clippy_lints/src/declared_lints.rs index a7067d8b86a..d867ab39294 100644 --- a/clippy_lints/src/declared_lints.rs +++ b/clippy_lints/src/declared_lints.rs @@ -51,6 +51,7 @@ pub(crate) static LINTS: &[&crate::LintInfo] = &[ crate::attrs::EMPTY_LINE_AFTER_DOC_COMMENTS_INFO, crate::attrs::EMPTY_LINE_AFTER_OUTER_ATTR_INFO, crate::attrs::INLINE_ALWAYS_INFO, + crate::attrs::MAYBE_MISUSED_CFG_INFO, crate::attrs::MISMATCHED_TARGET_OS_INFO, crate::attrs::NON_MINIMAL_CFG_INFO, crate::attrs::USELESS_ATTRIBUTE_INFO, diff --git a/tests/ui/cfg_features.rs b/tests/ui/cfg_features.rs new file mode 100644 index 00000000000..bc4109c2c89 --- /dev/null +++ b/tests/ui/cfg_features.rs @@ -0,0 +1,12 @@ +#![warn(clippy::maybe_misused_cfg)] + +fn main() { + #[cfg(features = "not-really-a-feature")] + let _ = 1 + 2; + + #[cfg(all(feature = "right", features = "wrong"))] + let _ = 1 + 2; + + #[cfg(all(features = "wrong1", any(feature = "right", features = "wrong2", feature, features)))] + let _ = 1 + 2; +} diff --git a/tests/ui/cfg_features.stderr b/tests/ui/cfg_features.stderr new file mode 100644 index 00000000000..00405985d48 --- /dev/null +++ b/tests/ui/cfg_features.stderr @@ -0,0 +1,28 @@ +error: feature may misspelled as features + --> $DIR/cfg_features.rs:4:11 + | +LL | #[cfg(features = "not-really-a-feature")] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use: `feature = "not-really-a-feature"` + | + = note: `-D clippy::maybe-misused-cfg` implied by `-D warnings` + +error: feature may misspelled as features + --> $DIR/cfg_features.rs:7:34 + | +LL | #[cfg(all(feature = "right", features = "wrong"))] + | ^^^^^^^^^^^^^^^^^^ help: use: `feature = "wrong"` + +error: feature may misspelled as features + --> $DIR/cfg_features.rs:10:15 + | +LL | #[cfg(all(features = "wrong1", any(feature = "right", features = "wrong2", feature, features)))] + | ^^^^^^^^^^^^^^^^^^^ help: use: `feature = "wrong1"` + +error: feature may misspelled as features + --> $DIR/cfg_features.rs:10:59 + | +LL | #[cfg(all(features = "wrong1", any(feature = "right", features = "wrong2", feature, features)))] + | ^^^^^^^^^^^^^^^^^^^ help: use: `feature = "wrong2"` + +error: aborting due to 4 previous errors + From e6dc0efc0076690c0dcae05541fec771795ca84c Mon Sep 17 00:00:00 2001 From: Philipp Krones Date: Fri, 2 Jun 2023 11:41:57 +0200 Subject: [PATCH 046/310] Merge commit '30448e8cf98d4754350db0c959644564f317bc0f' into clippyup --- .github/ISSUE_TEMPLATE/new_lint.yml | 23 - CHANGELOG.md | 130 +++++- Cargo.toml | 9 +- book/src/configuration.md | 10 +- book/src/development/adding_lints.md | 10 +- clippy_dev/src/main.rs | 4 +- clippy_lints/Cargo.toml | 10 +- clippy_lints/src/allow_attributes.rs | 2 +- clippy_lints/src/booleans.rs | 5 +- clippy_lints/src/casts/mod.rs | 33 +- clippy_lints/src/casts/ptr_cast_constness.rs | 44 ++ clippy_lints/src/collection_is_never_read.rs | 2 +- clippy_lints/src/declared_lints.rs | 3 + .../src/default_constructed_unit_structs.rs | 15 +- clippy_lints/src/large_futures.rs | 2 +- clippy_lints/src/large_stack_arrays.rs | 2 +- clippy_lints/src/let_with_type_underscore.rs | 2 +- clippy_lints/src/lib.rs | 43 +- clippy_lints/src/manual_let_else.rs | 164 ++++--- .../src/matches/match_wild_err_arm.rs | 7 +- clippy_lints/src/matches/mod.rs | 8 +- .../src/matches/redundant_pattern_match.rs | 21 +- clippy_lints/src/methods/mod.rs | 2 +- clippy_lints/src/missing_assert_message.rs | 2 +- clippy_lints/src/missing_fields_in_debug.rs | 234 ++++++++++ clippy_lints/src/needless_else.rs | 61 +++ clippy_lints/src/nonstandard_macro_braces.rs | 2 +- clippy_lints/src/redundant_async_block.rs | 2 +- clippy_lints/src/regex.rs | 2 +- clippy_lints/src/returns.rs | 28 +- clippy_lints/src/strings.rs | 5 +- clippy_lints/src/unused_async.rs | 50 +- clippy_lints/src/utils/conf.rs | 207 +++++---- clippy_lints/src/wildcard_imports.rs | 9 +- clippy_utils/Cargo.toml | 2 +- clippy_utils/src/lib.rs | 2 +- clippy_utils/src/msrvs.rs | 2 +- clippy_utils/src/paths.rs | 4 +- clippy_utils/src/source.rs | 13 +- declare_clippy_lint/Cargo.toml | 2 +- lintcheck/Cargo.toml | 2 +- rust-toolchain | 2 +- src/driver.rs | 15 +- .../multiple_crate_versions/fail/Cargo.lock | 67 +-- .../multiple_crate_versions/fail/Cargo.toml | 2 +- tests/ui-internal/custom_ice_message.rs | 2 +- tests/ui-internal/custom_ice_message.stderr | 7 +- tests/ui-toml/bad_toml/conf_bad_toml.stderr | 6 +- .../bad_toml_type/conf_bad_type.stderr | 6 +- .../conf_deprecated_key.stderr | 12 +- tests/ui-toml/duplicated_keys/clippy.toml | 3 - .../duplicated_keys/duplicated_keys.stderr | 12 +- .../duplicated_keys_deprecated/clippy.toml | 3 + .../duplicated_keys.rs | 1 + .../duplicated_keys.stderr | 14 + .../duplicated_keys_deprecated_2/clippy.toml | 4 + .../duplicated_keys.rs | 1 + .../duplicated_keys.stderr | 14 + tests/ui-toml/ifs_same_cond/ifs_same_cond.rs | 2 +- tests/ui-toml/toml_unknown_key/clippy.toml | 4 +- .../toml_unknown_key/conf_unknown_key.stderr | 70 ++- tests/ui/auxiliary/wildcard_imports_helper.rs | 6 + .../branches_sharing_code/valid_if_blocks.rs | 6 +- .../valid_if_blocks.stderr | 20 +- tests/ui/crashes/ice-7410.rs | 1 + .../ui/default_constructed_unit_structs.fixed | 22 + tests/ui/default_constructed_unit_structs.rs | 22 + .../default_constructed_unit_structs.stderr | 8 +- tests/ui/ifs_same_cond.rs | 2 +- tests/ui/large_stack_arrays.rs | 13 + tests/ui/large_stack_arrays.stderr | 30 +- tests/ui/manual_let_else.rs | 16 +- tests/ui/manual_let_else.stderr | 35 +- tests/ui/manual_let_else_match.rs | 2 +- tests/ui/manual_let_else_match.stderr | 4 +- tests/ui/match_wild_err_arm.rs | 15 +- tests/ui/match_wild_err_arm.stderr | 8 +- tests/ui/missing_fields_in_debug.rs | 191 ++++++++ tests/ui/missing_fields_in_debug.stderr | 73 +++ tests/ui/needless_else.fixed | 57 +++ tests/ui/needless_else.rs | 58 +++ tests/ui/needless_else.stderr | 12 + tests/ui/needless_return.fixed | 3 +- tests/ui/needless_return.rs | 3 +- tests/ui/needless_return.stderr | 426 +++++++++++++----- tests/ui/nonminimal_bool.rs | 14 + tests/ui/ptr_cast_constness.fixed | 55 +++ tests/ui/ptr_cast_constness.rs | 55 +++ tests/ui/ptr_cast_constness.stderr | 34 ++ ...edundant_pattern_matching_drop_order.fixed | 2 +- .../redundant_pattern_matching_drop_order.rs | 2 +- .../redundant_pattern_matching_option.fixed | 12 + tests/ui/redundant_pattern_matching_option.rs | 12 + .../redundant_pattern_matching_option.stderr | 44 +- .../redundant_pattern_matching_result.fixed | 15 + tests/ui/redundant_pattern_matching_result.rs | 15 + .../redundant_pattern_matching_result.stderr | 46 +- tests/ui/regex.rs | 7 + tests/ui/regex.stderr | 30 +- tests/ui/rename.fixed | 1 + tests/ui/rename.rs | 1 + tests/ui/rename.stderr | 100 ++-- tests/ui/single_match.fixed | 209 +++++++++ tests/ui/single_match.rs | 25 +- tests/ui/single_match.stderr | 44 +- tests/ui/single_match_else.fixed | 173 +++++++ tests/ui/single_match_else.rs | 88 +++- tests/ui/single_match_else.stderr | 98 +++- tests/ui/suspicious_else_formatting.rs | 2 +- tests/ui/unused_async.rs | 20 + tests/ui/unused_async.stderr | 25 +- tests/ui/wildcard_imports.fixed | 2 + tests/ui/wildcard_imports.rs | 2 + tests/ui/wildcard_imports.stderr | 30 +- 114 files changed, 2970 insertions(+), 653 deletions(-) create mode 100644 clippy_lints/src/casts/ptr_cast_constness.rs create mode 100644 clippy_lints/src/missing_fields_in_debug.rs create mode 100644 clippy_lints/src/needless_else.rs create mode 100644 tests/ui-toml/duplicated_keys_deprecated/clippy.toml create mode 100644 tests/ui-toml/duplicated_keys_deprecated/duplicated_keys.rs create mode 100644 tests/ui-toml/duplicated_keys_deprecated/duplicated_keys.stderr create mode 100644 tests/ui-toml/duplicated_keys_deprecated_2/clippy.toml create mode 100644 tests/ui-toml/duplicated_keys_deprecated_2/duplicated_keys.rs create mode 100644 tests/ui-toml/duplicated_keys_deprecated_2/duplicated_keys.stderr create mode 100644 tests/ui/missing_fields_in_debug.rs create mode 100644 tests/ui/missing_fields_in_debug.stderr create mode 100644 tests/ui/needless_else.fixed create mode 100644 tests/ui/needless_else.rs create mode 100644 tests/ui/needless_else.stderr create mode 100644 tests/ui/ptr_cast_constness.fixed create mode 100644 tests/ui/ptr_cast_constness.rs create mode 100644 tests/ui/ptr_cast_constness.stderr create mode 100644 tests/ui/single_match.fixed create mode 100644 tests/ui/single_match_else.fixed diff --git a/.github/ISSUE_TEMPLATE/new_lint.yml b/.github/ISSUE_TEMPLATE/new_lint.yml index 0b43d8d70c0..b49493edce1 100644 --- a/.github/ISSUE_TEMPLATE/new_lint.yml +++ b/.github/ISSUE_TEMPLATE/new_lint.yml @@ -12,29 +12,6 @@ body: description: What does this lint do? validations: required: true - - type: input - id: lint-name - attributes: - label: Lint Name - description: Please provide the lint name. - - type: dropdown - id: category - attributes: - label: Category - description: > - What category should this lint go into? If you're unsure you can select - multiple categories. You can find a category description in the - `README`. - multiple: true - options: - - correctness - - suspicious - - style - - complexity - - perf - - pedantic - - restriction - - cargo - type: textarea id: advantage attributes: diff --git a/CHANGELOG.md b/CHANGELOG.md index 79f2a47110b..8b609b47d81 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,7 +6,132 @@ document. ## Unreleased / Beta / In Rust Nightly -[149392b0...master](https://github.com/rust-lang/rust-clippy/compare/149392b0...master) +[83e42a23...master](https://github.com/rust-lang/rust-clippy/compare/83e42a23...master) + +## Rust 1.70 + +Current beta, released 2023-06-01 + +[149392b0...83e42a23](https://github.com/rust-lang/rust-clippy/compare/149392b0...83e42a23) + +### New Lints + +* [`large_futures`] + [#10414](https://github.com/rust-lang/rust-clippy/pull/10414) +* [`missing_assert_message`] + [#10362](https://github.com/rust-lang/rust-clippy/pull/10362) +* [`clear_with_drain`] + [#10528](https://github.com/rust-lang/rust-clippy/pull/10528) +* [`redundant_async_block`] + [#10448](https://github.com/rust-lang/rust-clippy/pull/10448) +* [`collection_is_never_read`] + [#10415](https://github.com/rust-lang/rust-clippy/pull/10415) +* [`let_with_type_underscore`] + [#10467](https://github.com/rust-lang/rust-clippy/pull/10467) +* [`tests_outside_test_module`] + [#10543](https://github.com/rust-lang/rust-clippy/pull/10543) +* [`allow_attributes`] + [#10481](https://github.com/rust-lang/rust-clippy/pull/10481) +* [`suspicious_doc_comments`] + [#10497](https://github.com/rust-lang/rust-clippy/pull/10497) +* [`unnecessary_box_returns`] + [#9102](https://github.com/rust-lang/rust-clippy/pull/9102) +* [`manual_main_separator_str`] + [#10483](https://github.com/rust-lang/rust-clippy/pull/10483) +* [`unnecessary_struct_initialization`] + [#10489](https://github.com/rust-lang/rust-clippy/pull/10489) +* [`manual_slice_size_calculation`] + [#10601](https://github.com/rust-lang/rust-clippy/pull/10601) +* [`lines_filter_map_ok`] + [#10534](https://github.com/rust-lang/rust-clippy/pull/10534) + +### Moves and Deprecations + +* Moved [`let_underscore_untyped`] to `restriction` + [#10442](https://github.com/rust-lang/rust-clippy/pull/10442) + +### Enhancements + +* [`extra_unused_type_parameters`]: No longer lints on public items if `avoid-breaking-exported-api` is set + [#10536](https://github.com/rust-lang/rust-clippy/pull/10536) +* [`len_without_is_empty`]: Now also detects `async` functions + [#10359](https://github.com/rust-lang/rust-clippy/pull/10359) +* [`arithmetic_side_effects`]: Now correctly handles divisions and modulo expressions if the right-hand-side + is unknown + [#10585](https://github.com/rust-lang/rust-clippy/pull/10585) +* [`nonminimal_bool`]: No longer ignores `#[allow]` attributes + [#10588](https://github.com/rust-lang/rust-clippy/pull/10588) +* [`uninit_vec`], [`uninit_assumed_init`]: Now uses a better heuristic + [#10520](https://github.com/rust-lang/rust-clippy/pull/10520) +* [`ifs_same_cond`]: Now also detects immutable method calls. + [#10350](https://github.com/rust-lang/rust-clippy/pull/10350) +* [`arithmetic_side_effects`]: No longer lints on right or left shifts with constant integers, as the + compiler warns about them + [#10309](https://github.com/rust-lang/rust-clippy/pull/10309) +* [`items_after_statements`]: `#[allow(items_after_statements)]` now works on items + [#10542](https://github.com/rust-lang/rust-clippy/pull/10542) +* [`significant_drop_tightening`]: Was optimized + [#10533](https://github.com/rust-lang/rust-clippy/pull/10533) + +### False Positive Fixes + +* [`single_component_path_imports`]: No longer lints if the import is used relative to `self` + [#10566](https://github.com/rust-lang/rust-clippy/pull/10566) +* [`derivable_impls`]: No longer suggests deriving `Default` on generics with implicit arguments + [#10399](https://github.com/rust-lang/rust-clippy/pull/10399) +* [`let_unit_value`]: No longer lints if the expression contains an `await` + [#10439](https://github.com/rust-lang/rust-clippy/pull/10439) +* [`double_must_use`]: Now ignores `async` functions + [#10589](https://github.com/rust-lang/rust-clippy/pull/10589) +* [`manual_clamp`]: No longer lints in constant context + [#10479](https://github.com/rust-lang/rust-clippy/pull/10479) +* [`almost_swapped`]: Now ignores external macros + [#10502](https://github.com/rust-lang/rust-clippy/pull/10502) +* [`nonminimal_bool`]: Now ignores macros + [#10527](https://github.com/rust-lang/rust-clippy/pull/10527) +* [`needless_return`]: No longer lints match statements with incompatible branches + [#10593](https://github.com/rust-lang/rust-clippy/pull/10593) +* [`use_self`]: Do not suggest using `Self` in const generic parameters + [#10375](https://github.com/rust-lang/rust-clippy/pull/10375) +* [`mem_replace_option_with_none`]: No longer lints on field expressions + [#10594](https://github.com/rust-lang/rust-clippy/pull/10594) +* [`items_after_statements`]: No longer lints on times from macros + [#10542](https://github.com/rust-lang/rust-clippy/pull/10542) +* [`print_literal`], [`write_literal`]: No longer lint strings coming from the `file!()` macro + [#10573](https://github.com/rust-lang/rust-clippy/pull/10573) +* [`uninit_vec`], [`uninit_assumed_init`]: Now check the types inside arrays and tuples + [#10553](https://github.com/rust-lang/rust-clippy/pull/10553) +* [`almost_swapped`]: No longer lints if a variable is assigned to itself + [#10499](https://github.com/rust-lang/rust-clippy/pull/10499) +* [`missing_docs_in_private_items`]: No longer lints on public items + [#10324](https://github.com/rust-lang/rust-clippy/pull/10324) + +### Suggestion Fixes/Improvements + +* [`extra_unused_type_parameters`]: The suggestion is now machine applicable + [#10536](https://github.com/rust-lang/rust-clippy/pull/10536) +* [`match_single_binding`]: Now adds a semicolon after the suggestion + [#10470](https://github.com/rust-lang/rust-clippy/pull/10470) +* [`missing_const_for_fn`]: Now includes a note if the change could break compatibility + [#10618](https://github.com/rust-lang/rust-clippy/pull/10618) +* [`cast_possible_truncation`]: Corrected suggestion for float and wildcard casts + [#10496](https://github.com/rust-lang/rust-clippy/pull/10496) +* [`transmutes_expressible_as_ptr_casts`]: The suggestion now includes parentheses when they are required + [#10454](https://github.com/rust-lang/rust-clippy/pull/10454) + +### ICE Fixes + +* [`needless_borrow`]: No longer panics on ambiguous projections + [#10403](https://github.com/rust-lang/rust-clippy/pull/10403) +* [`multiple_unsafe_ops_per_block`]: Fix ICE when calling a function-like object in an unsafe block + [#10405](https://github.com/rust-lang/rust-clippy/pull/10405) + +### Others + +* `clippy-driver` now searches parent directories for `clippy.toml` files + [#10592](https://github.com/rust-lang/rust-clippy/pull/10592) +* Fixed a deserialization error for the `array-size-threshold` config value + [#10423](https://github.com/rust-lang/rust-clippy/pull/10423) ## Rust 1.69 @@ -4838,6 +4963,7 @@ Released 2018-09-13 [`missing_docs_in_private_items`]: https://rust-lang.github.io/rust-clippy/master/index.html#missing_docs_in_private_items [`missing_enforced_import_renames`]: https://rust-lang.github.io/rust-clippy/master/index.html#missing_enforced_import_renames [`missing_errors_doc`]: https://rust-lang.github.io/rust-clippy/master/index.html#missing_errors_doc +[`missing_fields_in_debug`]: https://rust-lang.github.io/rust-clippy/master/index.html#missing_fields_in_debug [`missing_inline_in_public_items`]: https://rust-lang.github.io/rust-clippy/master/index.html#missing_inline_in_public_items [`missing_panics_doc`]: https://rust-lang.github.io/rust-clippy/master/index.html#missing_panics_doc [`missing_safety_doc`]: https://rust-lang.github.io/rust-clippy/master/index.html#missing_safety_doc @@ -4874,6 +5000,7 @@ Released 2018-09-13 [`needless_collect`]: https://rust-lang.github.io/rust-clippy/master/index.html#needless_collect [`needless_continue`]: https://rust-lang.github.io/rust-clippy/master/index.html#needless_continue [`needless_doctest_main`]: https://rust-lang.github.io/rust-clippy/master/index.html#needless_doctest_main +[`needless_else`]: https://rust-lang.github.io/rust-clippy/master/index.html#needless_else [`needless_for_each`]: https://rust-lang.github.io/rust-clippy/master/index.html#needless_for_each [`needless_late_init`]: https://rust-lang.github.io/rust-clippy/master/index.html#needless_late_init [`needless_lifetimes`]: https://rust-lang.github.io/rust-clippy/master/index.html#needless_lifetimes @@ -4949,6 +5076,7 @@ Released 2018-09-13 [`println_empty_string`]: https://rust-lang.github.io/rust-clippy/master/index.html#println_empty_string [`ptr_arg`]: https://rust-lang.github.io/rust-clippy/master/index.html#ptr_arg [`ptr_as_ptr`]: https://rust-lang.github.io/rust-clippy/master/index.html#ptr_as_ptr +[`ptr_cast_constness`]: https://rust-lang.github.io/rust-clippy/master/index.html#ptr_cast_constness [`ptr_eq`]: https://rust-lang.github.io/rust-clippy/master/index.html#ptr_eq [`ptr_offset_with_cast`]: https://rust-lang.github.io/rust-clippy/master/index.html#ptr_offset_with_cast [`pub_enum_variant_names`]: https://rust-lang.github.io/rust-clippy/master/index.html#pub_enum_variant_names diff --git a/Cargo.toml b/Cargo.toml index 3c72bb62ed1..ca8bf9fac91 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "clippy" -version = "0.1.71" +version = "0.1.72" description = "A bunch of helpful lints to avoid common pitfalls in Rust" repository = "https://github.com/rust-lang/rust-clippy" readme = "README.md" @@ -30,16 +30,11 @@ termize = "0.1" compiletest_rs = { version = "0.10", features = ["tmp"] } tester = "0.9" regex = "1.5" -toml = "0.5" +toml = "0.7.3" walkdir = "2.3" # This is used by the `collect-metadata` alias. filetime = "0.2" -# A noop dependency that changes in the Rust repository, it's a bit of a hack. -# See the `src/tools/rustc-workspace-hack/README.md` file in `rust-lang/rust` -# for more information. -rustc-workspace-hack = "1.0" - # UI test dependencies clap = { version = "4.1.4", features = ["derive"] } clippy_utils = { path = "clippy_utils" } diff --git a/book/src/configuration.md b/book/src/configuration.md index 1304f6a8c2f..e8274bc4575 100644 --- a/book/src/configuration.md +++ b/book/src/configuration.md @@ -2,8 +2,14 @@ > **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 e.g. +Some lints can be configured in a TOML file named `clippy.toml` or `.clippy.toml`, which is searched for in: + +1. The directory specified by the `CLIPPY_CONF_DIR` environment variable, or +2. The directory specified by the +[CARGO_MANIFEST_DIR](https://doc.rust-lang.org/cargo/reference/environment-variables.html) environment variable, or +3. The current directory. + +It contains a basic `variable = value` mapping e.g. ```toml avoid-breaking-exported-api = false diff --git a/book/src/development/adding_lints.md b/book/src/development/adding_lints.md index ccae8d37420..c26aa883eba 100644 --- a/book/src/development/adding_lints.md +++ b/book/src/development/adding_lints.md @@ -630,8 +630,14 @@ Before submitting your PR make sure you followed all the basic requirements: ## Adding configuration to a lint -Clippy supports the configuration of lints values using a `clippy.toml` file in -the workspace directory. Adding a configuration to a lint can be useful for +Clippy supports the configuration of lints values using a `clippy.toml` file which is searched for in: + +1. The directory specified by the `CLIPPY_CONF_DIR` environment variable, or +2. The directory specified by the +[CARGO_MANIFEST_DIR](https://doc.rust-lang.org/cargo/reference/environment-variables.html) environment variable, or +3. The current directory. + +Adding a configuration to a lint can be useful for thresholds or to constrain some behavior that can be seen as a false positive for some users. Adding a configuration is done in the following steps: diff --git a/clippy_dev/src/main.rs b/clippy_dev/src/main.rs index e2457e5a8a5..c03fbe9d275 100644 --- a/clippy_dev/src/main.rs +++ b/clippy_dev/src/main.rs @@ -5,6 +5,7 @@ use clap::{Arg, ArgAction, ArgMatches, Command}; use clippy_dev::{bless, dogfood, fmt, lint, new_lint, serve, setup, update_lints}; use indoc::indoc; +use std::convert::Infallible; fn main() { let matches = get_clap_config(); @@ -180,7 +181,8 @@ fn get_clap_config() -> ArgMatches { .short('n') .long("name") .help("Name of the new lint in snake case, ex: fn_too_long") - .required(true), + .required(true) + .value_parser(|name: &str| Ok::<_, Infallible>(name.replace('-', "_"))), Arg::new("category") .short('c') .long("category") diff --git a/clippy_lints/Cargo.toml b/clippy_lints/Cargo.toml index 98e69c7fd26..be9261a4704 100644 --- a/clippy_lints/Cargo.toml +++ b/clippy_lints/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "clippy_lints" -version = "0.1.71" +version = "0.1.72" description = "A bunch of helpful lints to avoid common pitfalls in Rust" repository = "https://github.com/rust-lang/rust-clippy" readme = "README.md" @@ -20,15 +20,13 @@ quine-mc_cluskey = "0.2" regex-syntax = "0.7" serde = { version = "1.0", features = ["derive"] } serde_json = { version = "1.0", optional = true } -tempfile = { version = "3.2", optional = true } -toml = "0.5" +tempfile = { version = "3.3.0", optional = true } +toml = "0.7.3" unicode-normalization = "0.1" unicode-script = { version = "0.5", default-features = false } semver = "1.0" rustc-semver = "1.1" -# NOTE: cargo requires serde feat in its url dep -# see -url = { version = "2.2", features = ["serde"] } +url = "2.2" [features] deny-warnings = ["clippy_utils/deny-warnings"] diff --git a/clippy_lints/src/allow_attributes.rs b/clippy_lints/src/allow_attributes.rs index add73d0aeee..554efdc58e1 100644 --- a/clippy_lints/src/allow_attributes.rs +++ b/clippy_lints/src/allow_attributes.rs @@ -40,7 +40,7 @@ declare_clippy_lint! { /// a.len() /// } /// ``` - #[clippy::version = "1.69.0"] + #[clippy::version = "1.70.0"] pub ALLOW_ATTRIBUTES, restriction, "`#[allow]` will not trigger if a warning isn't found. `#[expect]` triggers if there are no warnings." diff --git a/clippy_lints/src/booleans.rs b/clippy_lints/src/booleans.rs index 455f0df7cd0..ff0102255a0 100644 --- a/clippy_lints/src/booleans.rs +++ b/clippy_lints/src/booleans.rs @@ -88,7 +88,6 @@ impl<'tcx> LateLintPass<'tcx> for NonminimalBool { NonminimalBoolVisitor { cx }.visit_body(body); } } - struct NonminimalBoolVisitor<'a, 'tcx> { cx: &'a LateContext<'tcx>, } @@ -473,6 +472,10 @@ impl<'a, 'tcx> Visitor<'tcx> for NonminimalBoolVisitor<'a, 'tcx> { self.bool_expr(e); }, ExprKind::Unary(UnOp::Not, inner) => { + if let ExprKind::Unary(UnOp::Not, ex) = inner.kind && + !self.cx.typeck_results().node_types()[ex.hir_id].is_bool() { + return; + } if self.cx.typeck_results().node_types()[inner.hir_id].is_bool() { self.bool_expr(e); } diff --git a/clippy_lints/src/casts/mod.rs b/clippy_lints/src/casts/mod.rs index 0c175372aab..b90dab07a27 100644 --- a/clippy_lints/src/casts/mod.rs +++ b/clippy_lints/src/casts/mod.rs @@ -17,6 +17,7 @@ mod fn_to_numeric_cast; mod fn_to_numeric_cast_any; mod fn_to_numeric_cast_with_truncation; mod ptr_as_ptr; +mod ptr_cast_constness; mod unnecessary_cast; mod utils; @@ -363,7 +364,7 @@ declare_clippy_lint! { /// namely `*const T` to `*const U` and `*mut T` to `*mut U`. /// /// ### Why is this bad? - /// Though `as` casts between raw pointers is not terrible, `pointer::cast` is safer because + /// Though `as` casts between raw pointers are not terrible, `pointer::cast` is safer because /// it cannot accidentally change the pointer's mutability nor cast the pointer to other types like `usize`. /// /// ### Example @@ -386,6 +387,34 @@ declare_clippy_lint! { "casting using `as` from and to raw pointers that doesn't change its mutability, where `pointer::cast` could take the place of `as`" } +declare_clippy_lint! { + /// ### What it does + /// Checks for `as` casts between raw pointers which change its constness, namely `*const T` to + /// `*mut T` and `*mut T` to `*const T`. + /// + /// ### Why is this bad? + /// Though `as` casts between raw pointers are not terrible, `pointer::cast_mut` and + /// `pointer::cast_const` are safer because they cannot accidentally cast the pointer to another + /// type. + /// + /// ### Example + /// ```rust + /// let ptr: *const u32 = &42_u32; + /// let mut_ptr = ptr as *mut u32; + /// let ptr = mut_ptr as *const u32; + /// ``` + /// Use instead: + /// ```rust + /// let ptr: *const u32 = &42_u32; + /// let mut_ptr = ptr.cast_mut(); + /// let ptr = mut_ptr.cast_const(); + /// ``` + #[clippy::version = "1.71.0"] + pub PTR_CAST_CONSTNESS, + pedantic, + "casting using `as` from and to raw pointers to change constness when specialized methods apply" +} + declare_clippy_lint! { /// ### What it does /// Checks for casts from an enum type to an integral type which will definitely truncate the @@ -652,6 +681,7 @@ impl_lint_pass!(Casts => [ FN_TO_NUMERIC_CAST_WITH_TRUNCATION, CHAR_LIT_AS_U8, PTR_AS_PTR, + PTR_CAST_CONSTNESS, CAST_ENUM_TRUNCATION, CAST_ENUM_CONSTRUCTOR, CAST_ABS_TO_UNSIGNED, @@ -685,6 +715,7 @@ impl<'tcx> LateLintPass<'tcx> for Casts { return; } cast_slice_from_raw_parts::check(cx, expr, cast_expr, cast_to, &self.msrv); + ptr_cast_constness::check(cx, expr, cast_expr, cast_from, cast_to, &self.msrv); as_ptr_cast_mut::check(cx, expr, cast_expr, cast_to); fn_to_numeric_cast_any::check(cx, expr, cast_expr, cast_from, cast_to); fn_to_numeric_cast::check(cx, expr, cast_expr, cast_from, cast_to); diff --git a/clippy_lints/src/casts/ptr_cast_constness.rs b/clippy_lints/src/casts/ptr_cast_constness.rs new file mode 100644 index 00000000000..ab015f8822e --- /dev/null +++ b/clippy_lints/src/casts/ptr_cast_constness.rs @@ -0,0 +1,44 @@ +use clippy_utils::msrvs::POINTER_CAST_CONSTNESS; +use clippy_utils::sugg::Sugg; +use clippy_utils::{diagnostics::span_lint_and_sugg, msrvs::Msrv}; +use if_chain::if_chain; +use rustc_errors::Applicability; +use rustc_hir::{Expr, Mutability}; +use rustc_lint::LateContext; +use rustc_middle::ty::{self, Ty, TypeAndMut}; + +use super::PTR_CAST_CONSTNESS; + +pub(super) fn check( + cx: &LateContext<'_>, + expr: &Expr<'_>, + cast_expr: &Expr<'_>, + cast_from: Ty<'_>, + cast_to: Ty<'_>, + msrv: &Msrv, +) { + if_chain! { + if msrv.meets(POINTER_CAST_CONSTNESS); + if let ty::RawPtr(TypeAndMut { mutbl: from_mutbl, .. }) = cast_from.kind(); + if let ty::RawPtr(TypeAndMut { mutbl: to_mutbl, .. }) = cast_to.kind(); + if matches!((from_mutbl, to_mutbl), + (Mutability::Not, Mutability::Mut) | (Mutability::Mut, Mutability::Not)); + then { + let sugg = Sugg::hir(cx, cast_expr, "_"); + let constness = match *to_mutbl { + Mutability::Not => "const", + Mutability::Mut => "mut", + }; + + span_lint_and_sugg( + cx, + PTR_CAST_CONSTNESS, + expr.span, + "`as` casting between raw pointers while changing its constness", + &format!("try `pointer::cast_{constness}`, a safer alternative"), + format!("{}.cast_{constness}()", sugg.maybe_par()), + Applicability::MachineApplicable, + ); + } + } +} diff --git a/clippy_lints/src/collection_is_never_read.rs b/clippy_lints/src/collection_is_never_read.rs index 5e2eb5789f6..ac5ac542cf9 100644 --- a/clippy_lints/src/collection_is_never_read.rs +++ b/clippy_lints/src/collection_is_never_read.rs @@ -37,7 +37,7 @@ declare_clippy_lint! { /// println!("{sample}"); /// } /// ``` - #[clippy::version = "1.69.0"] + #[clippy::version = "1.70.0"] pub COLLECTION_IS_NEVER_READ, nursery, "a collection is never queried" diff --git a/clippy_lints/src/declared_lints.rs b/clippy_lints/src/declared_lints.rs index 212e809d4c5..15ff8be0fd9 100644 --- a/clippy_lints/src/declared_lints.rs +++ b/clippy_lints/src/declared_lints.rs @@ -89,6 +89,7 @@ pub(crate) static LINTS: &[&crate::LintInfo] = &[ crate::casts::FN_TO_NUMERIC_CAST_ANY_INFO, crate::casts::FN_TO_NUMERIC_CAST_WITH_TRUNCATION_INFO, crate::casts::PTR_AS_PTR_INFO, + crate::casts::PTR_CAST_CONSTNESS_INFO, crate::casts::UNNECESSARY_CAST_INFO, crate::checked_conversions::CHECKED_CONVERSIONS_INFO, crate::cognitive_complexity::COGNITIVE_COMPLEXITY_INFO, @@ -427,6 +428,7 @@ pub(crate) static LINTS: &[&crate::LintInfo] = &[ crate::missing_const_for_fn::MISSING_CONST_FOR_FN_INFO, crate::missing_doc::MISSING_DOCS_IN_PRIVATE_ITEMS_INFO, crate::missing_enforced_import_rename::MISSING_ENFORCED_IMPORT_RENAMES_INFO, + crate::missing_fields_in_debug::MISSING_FIELDS_IN_DEBUG_INFO, crate::missing_inline::MISSING_INLINE_IN_PUBLIC_ITEMS_INFO, crate::missing_trait_methods::MISSING_TRAIT_METHODS_INFO, crate::mixed_read_write_in_expression::DIVERGING_SUB_EXPRESSION_INFO, @@ -447,6 +449,7 @@ pub(crate) static LINTS: &[&crate::LintInfo] = &[ crate::needless_bool::NEEDLESS_BOOL_ASSIGN_INFO, crate::needless_borrowed_ref::NEEDLESS_BORROWED_REFERENCE_INFO, crate::needless_continue::NEEDLESS_CONTINUE_INFO, + crate::needless_else::NEEDLESS_ELSE_INFO, crate::needless_for_each::NEEDLESS_FOR_EACH_INFO, crate::needless_late_init::NEEDLESS_LATE_INIT_INFO, crate::needless_parens_on_range_literals::NEEDLESS_PARENS_ON_RANGE_LITERALS_INFO, diff --git a/clippy_lints/src/default_constructed_unit_structs.rs b/clippy_lints/src/default_constructed_unit_structs.rs index 9bd7a0dc0f3..fb037bbcbf3 100644 --- a/clippy_lints/src/default_constructed_unit_structs.rs +++ b/clippy_lints/src/default_constructed_unit_structs.rs @@ -1,4 +1,4 @@ -use clippy_utils::{diagnostics::span_lint_and_sugg, match_def_path, paths}; +use clippy_utils::{diagnostics::span_lint_and_sugg, is_ty_alias, match_def_path, paths}; use hir::{def::Res, ExprKind}; use rustc_errors::Applicability; use rustc_hir as hir; @@ -43,12 +43,23 @@ declare_clippy_lint! { } declare_lint_pass!(DefaultConstructedUnitStructs => [DEFAULT_CONSTRUCTED_UNIT_STRUCTS]); +fn is_alias(ty: hir::Ty<'_>) -> bool { + if let hir::TyKind::Path(ref qpath) = ty.kind { + is_ty_alias(qpath) + } else { + false + } +} + 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@ hir::QPath::TypeRelative(_,_)) = fn_expr.kind; + if let ExprKind::Path(ref qpath @ hir::QPath::TypeRelative(base, _)) = fn_expr.kind; + // make sure this isn't a type alias: + // `::Assoc` cannot be used as a constructor + if !is_alias(*base); 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) diff --git a/clippy_lints/src/large_futures.rs b/clippy_lints/src/large_futures.rs index 0ca31033b16..087c4a65250 100644 --- a/clippy_lints/src/large_futures.rs +++ b/clippy_lints/src/large_futures.rs @@ -38,7 +38,7 @@ declare_clippy_lint! { /// wait(fut).await; /// } /// ``` - #[clippy::version = "1.68.0"] + #[clippy::version = "1.70.0"] pub LARGE_FUTURES, pedantic, "large future may lead to unexpected stack overflows" diff --git a/clippy_lints/src/large_stack_arrays.rs b/clippy_lints/src/large_stack_arrays.rs index 32c6312e069..0a5901bce04 100644 --- a/clippy_lints/src/large_stack_arrays.rs +++ b/clippy_lints/src/large_stack_arrays.rs @@ -38,7 +38,7 @@ impl_lint_pass!(LargeStackArrays => [LARGE_STACK_ARRAYS]); impl<'tcx> LateLintPass<'tcx> for LargeStackArrays { fn check_expr(&mut self, cx: &LateContext<'_>, expr: &Expr<'_>) { - if let ExprKind::Repeat(_, _) = expr.kind + if let ExprKind::Repeat(_, _) | ExprKind::Array(_) = expr.kind && let ty::Array(element_type, cst) = cx.typeck_results().expr_ty(expr).kind() && let ConstKind::Value(ty::ValTree::Leaf(element_count)) = cst.kind() && let Ok(element_count) = element_count.try_to_target_usize(cx.tcx) diff --git a/clippy_lints/src/let_with_type_underscore.rs b/clippy_lints/src/let_with_type_underscore.rs index c01e3882d52..2f10e3d2581 100644 --- a/clippy_lints/src/let_with_type_underscore.rs +++ b/clippy_lints/src/let_with_type_underscore.rs @@ -17,7 +17,7 @@ declare_clippy_lint! { /// ```rust,ignore /// let my_number = 1; /// ``` - #[clippy::version = "1.69.0"] + #[clippy::version = "1.70.0"] pub LET_WITH_TYPE_UNDERSCORE, complexity, "unneeded underscore type (`_`) in a variable declaration" diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index fcca595c2bc..4a23edb58aa 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -202,6 +202,7 @@ mod missing_assert_message; mod missing_const_for_fn; mod missing_doc; mod missing_enforced_import_rename; +mod missing_fields_in_debug; mod missing_inline; mod missing_trait_methods; mod mixed_read_write_in_expression; @@ -217,6 +218,7 @@ mod needless_arbitrary_self_type; mod needless_bool; mod needless_borrowed_ref; mod needless_continue; +mod needless_else; mod needless_for_each; mod needless_late_init; mod needless_parens_on_range_literals; @@ -333,7 +335,7 @@ mod zero_sized_map_values; pub use crate::utils::conf::{lookup_conf_file, Conf}; use crate::utils::{ - conf::{format_error, metadata::get_configuration_metadata, TryConf}, + conf::{metadata::get_configuration_metadata, TryConf}, FindAll, }; @@ -369,23 +371,36 @@ pub fn read_conf(sess: &Session, path: &io::Result<(Option, Vec }, }; - let TryConf { conf, errors, warnings } = utils::conf::read(file_name); + let TryConf { conf, errors, warnings } = utils::conf::read(sess, file_name); // all conf errors are non-fatal, we just use the default conf in case of error for error in errors { - sess.err(format!( - "error reading Clippy's configuration file `{}`: {}", - file_name.display(), - format_error(error) - )); + if let Some(span) = error.span { + sess.span_err( + span, + format!("error reading Clippy's configuration file: {}", error.message), + ); + } else { + sess.err(format!( + "error reading Clippy's configuration file `{}`: {}", + file_name.display(), + error.message + )); + } } for warning in warnings { - sess.struct_warn(format!( - "error reading Clippy's configuration file `{}`: {}", - file_name.display(), - format_error(warning) - )) - .emit(); + if let Some(span) = warning.span { + sess.span_warn( + span, + format!("error reading Clippy's configuration file: {}", warning.message), + ); + } else { + sess.warn(format!( + "error reading Clippy's configuration file `{}`: {}", + file_name.display(), + warning.message + )); + } } conf @@ -990,6 +1005,8 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: store.register_late_pass(|_| Box::new(items_after_test_module::ItemsAfterTestModule)); store.register_early_pass(|| Box::new(ref_patterns::RefPatterns)); store.register_late_pass(|_| Box::new(default_constructed_unit_structs::DefaultConstructedUnitStructs)); + store.register_early_pass(|| Box::new(needless_else::NeedlessElse)); + store.register_late_pass(|_| Box::new(missing_fields_in_debug::MissingFieldsInDebug)); // add lints here, do not remove this comment, it's used in `new_lint` } diff --git a/clippy_lints/src/manual_let_else.rs b/clippy_lints/src/manual_let_else.rs index 3f8b42ffe80..389b0a4a62d 100644 --- a/clippy_lints/src/manual_let_else.rs +++ b/clippy_lints/src/manual_let_else.rs @@ -77,53 +77,54 @@ impl<'tcx> LateLintPass<'tcx> for ManualLetElse { local.els.is_none() && local.ty.is_none() && init.span.ctxt() == stmt.span.ctxt() && - let Some(if_let_or_match) = IfLetOrMatch::parse(cx, init) { - match if_let_or_match { - IfLetOrMatch::IfLet(if_let_expr, let_pat, if_then, if_else) => if_chain! { - if expr_is_simple_identity(let_pat, if_then); - if let Some(if_else) = if_else; - if expr_diverges(cx, if_else); - then { - emit_manual_let_else(cx, stmt.span, if_let_expr, local.pat, let_pat, if_else); - } - }, - IfLetOrMatch::Match(match_expr, arms, source) => { - if self.matches_behaviour == MatchLintBehaviour::Never { - return; - } - if source != MatchSource::Normal { - return; - } - // Any other number than two arms doesn't (necessarily) - // have a trivial mapping to let else. - if arms.len() != 2 { - return; - } - // Guards don't give us an easy mapping either - if arms.iter().any(|arm| arm.guard.is_some()) { - return; - } - let check_types = self.matches_behaviour == MatchLintBehaviour::WellKnownTypes; - let diverging_arm_opt = arms - .iter() - .enumerate() - .find(|(_, arm)| expr_diverges(cx, arm.body) && pat_allowed_for_else(cx, arm.pat, check_types)); - let Some((idx, diverging_arm)) = diverging_arm_opt else { return; }; - // If the non-diverging arm is the first one, its pattern can be reused in a let/else statement. - // However, if it arrives in second position, its pattern may cover some cases already covered - // by the diverging one. - // TODO: accept the non-diverging arm as a second position if patterns are disjointed. - if idx == 0 { - return; - } - let pat_arm = &arms[1 - idx]; - if !expr_is_simple_identity(pat_arm.pat, pat_arm.body) { - return; - } + let Some(if_let_or_match) = IfLetOrMatch::parse(cx, init) + { + match if_let_or_match { + IfLetOrMatch::IfLet(if_let_expr, let_pat, if_then, if_else) => if_chain! { + if expr_is_simple_identity(let_pat, if_then); + if let Some(if_else) = if_else; + if expr_diverges(cx, if_else); + then { + emit_manual_let_else(cx, stmt.span, if_let_expr, local.pat, let_pat, if_else); + } + }, + IfLetOrMatch::Match(match_expr, arms, source) => { + if self.matches_behaviour == MatchLintBehaviour::Never { + return; + } + if source != MatchSource::Normal { + return; + } + // Any other number than two arms doesn't (necessarily) + // have a trivial mapping to let else. + if arms.len() != 2 { + return; + } + // Guards don't give us an easy mapping either + if arms.iter().any(|arm| arm.guard.is_some()) { + return; + } + let check_types = self.matches_behaviour == MatchLintBehaviour::WellKnownTypes; + let diverging_arm_opt = arms + .iter() + .enumerate() + .find(|(_, arm)| expr_diverges(cx, arm.body) && pat_allowed_for_else(cx, arm.pat, check_types)); + let Some((idx, diverging_arm)) = diverging_arm_opt else { return; }; + // If the non-diverging arm is the first one, its pattern can be reused in a let/else statement. + // However, if it arrives in second position, its pattern may cover some cases already covered + // by the diverging one. + // TODO: accept the non-diverging arm as a second position if patterns are disjointed. + if idx == 0 { + return; + } + let pat_arm = &arms[1 - idx]; + if !expr_is_simple_identity(pat_arm.pat, pat_arm.body) { + return; + } - emit_manual_let_else(cx, stmt.span, match_expr, local.pat, pat_arm.pat, diverging_arm.body); - }, - } + emit_manual_let_else(cx, stmt.span, match_expr, local.pat, pat_arm.pat, diverging_arm.body); + }, + } }; } @@ -145,10 +146,9 @@ fn emit_manual_let_else( "this could be rewritten as `let...else`", |diag| { // This is far from perfect, for example there needs to be: - // * mut additions for the bindings - // * renamings of the bindings for `PatKind::Or` + // * tracking for multi-binding cases: let (foo, bar) = if let (Some(foo), Ok(bar)) = ... + // * renamings of the bindings for many `PatKind`s like structs, slices, etc. // * unused binding collision detection with existing ones - // * putting patterns with at the top level | inside () // for this to be machine applicable. let mut app = Applicability::HasPlaceholders; let (sn_expr, _) = snippet_with_context(cx, expr.span, span.ctxt(), "", &mut app); @@ -159,28 +159,62 @@ fn emit_manual_let_else( } else { format!("{{ {sn_else} }}") }; - let sn_bl = match pat.kind { - PatKind::Or(..) => { - let (sn_pat, _) = snippet_with_context(cx, pat.span, span.ctxt(), "", &mut app); - format!("({sn_pat})") - }, - // Replace the variable name iff `TupleStruct` has one argument like `Variant(v)`. - PatKind::TupleStruct(ref w, args, ..) if args.len() == 1 => { - let sn_wrapper = cx.sess().source_map().span_to_snippet(w.span()).unwrap_or_default(); - let (sn_inner, _) = snippet_with_context(cx, local.span, span.ctxt(), "", &mut app); - format!("{sn_wrapper}({sn_inner})") - }, - _ => { - let (sn_pat, _) = snippet_with_context(cx, pat.span, span.ctxt(), "", &mut app); - sn_pat.into_owned() - }, - }; + let sn_bl = replace_in_pattern(cx, span, local, pat, &mut app); let sugg = format!("let {sn_bl} = {sn_expr} else {else_bl};"); diag.span_suggestion(span, "consider writing", sugg, app); }, ); } +// replaces the locals in the pattern +fn replace_in_pattern( + cx: &LateContext<'_>, + span: Span, + local: &Pat<'_>, + pat: &Pat<'_>, + app: &mut Applicability, +) -> String { + let mut bindings_count = 0; + pat.each_binding_or_first(&mut |_, _, _, _| bindings_count += 1); + // If the pattern creates multiple bindings, exit early, + // as otherwise we might paste the pattern to the positions of multiple bindings. + if bindings_count > 1 { + let (sn_pat, _) = snippet_with_context(cx, pat.span, span.ctxt(), "", app); + return sn_pat.into_owned(); + } + + match pat.kind { + PatKind::Binding(..) => { + let (sn_bdg, _) = snippet_with_context(cx, local.span, span.ctxt(), "", app); + return sn_bdg.to_string(); + }, + PatKind::Or(pats) => { + let patterns = pats + .iter() + .map(|pat| replace_in_pattern(cx, span, local, pat, app)) + .collect::>(); + let or_pat = patterns.join(" | "); + return format!("({or_pat})"); + }, + // Replace the variable name iff `TupleStruct` has one argument like `Variant(v)`. + PatKind::TupleStruct(ref w, args, dot_dot_pos) => { + let mut args = args + .iter() + .map(|pat| replace_in_pattern(cx, span, local, pat, app)) + .collect::>(); + if let Some(pos) = dot_dot_pos.as_opt_usize() { + args.insert(pos, "..".to_owned()); + } + let args = args.join(", "); + let sn_wrapper = cx.sess().source_map().span_to_snippet(w.span()).unwrap_or_default(); + return format!("{sn_wrapper}({args})"); + }, + _ => {}, + } + let (sn_pat, _) = snippet_with_context(cx, pat.span, span.ctxt(), "", app); + sn_pat.into_owned() +} + /// Check whether an expression is divergent. May give false negatives. fn expr_diverges(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool { struct V<'cx, 'tcx> { diff --git a/clippy_lints/src/matches/match_wild_err_arm.rs b/clippy_lints/src/matches/match_wild_err_arm.rs index 42f1e2629d4..6424ac31d9f 100644 --- a/clippy_lints/src/matches/match_wild_err_arm.rs +++ b/clippy_lints/src/matches/match_wild_err_arm.rs @@ -2,7 +2,7 @@ use clippy_utils::diagnostics::span_lint_and_note; use clippy_utils::macros::{is_panic, root_macro_call}; use clippy_utils::ty::is_type_diagnostic_item; use clippy_utils::visitors::is_local_used; -use clippy_utils::{is_wild, peel_blocks_with_stmt}; +use clippy_utils::{in_constant, is_wild, peel_blocks_with_stmt}; use rustc_hir::{Arm, Expr, PatKind}; use rustc_lint::LateContext; use rustc_span::symbol::{kw, sym}; @@ -10,6 +10,11 @@ use rustc_span::symbol::{kw, sym}; use super::MATCH_WILD_ERR_ARM; pub(crate) fn check<'tcx>(cx: &LateContext<'tcx>, ex: &Expr<'tcx>, arms: &[Arm<'tcx>]) { + // `unwrap`/`expect` is not (yet) const, so we want to allow this in const contexts for now + if in_constant(cx, ex.hir_id) { + return; + } + let ex_ty = cx.typeck_results().expr_ty(ex).peel_refs(); if is_type_diagnostic_item(cx, ex_ty, sym::Result) { for arm in arms { diff --git a/clippy_lints/src/matches/mod.rs b/clippy_lints/src/matches/mod.rs index 55ec9d4474f..0d91051632a 100644 --- a/clippy_lints/src/matches/mod.rs +++ b/clippy_lints/src/matches/mod.rs @@ -25,7 +25,7 @@ mod wild_in_or_pats; use clippy_utils::msrvs::{self, Msrv}; use clippy_utils::source::{snippet_opt, walk_span_to_context}; -use clippy_utils::{higher, in_constant, is_span_match, tokenize_with_text}; +use clippy_utils::{higher, in_constant, is_direct_expn_of, is_span_match, tokenize_with_text}; use rustc_hir::{Arm, Expr, ExprKind, Local, MatchSource, Pat}; use rustc_lexer::TokenKind; use rustc_lint::{LateContext, LateLintPass, LintContext}; @@ -974,12 +974,16 @@ impl_lint_pass!(Matches => [ impl<'tcx> LateLintPass<'tcx> for Matches { fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) { - if in_external_macro(cx.sess(), expr.span) { + if is_direct_expn_of(expr.span, "matches").is_none() && in_external_macro(cx.sess(), expr.span) { return; } let from_expansion = expr.span.from_expansion(); if let ExprKind::Match(ex, arms, source) = expr.kind { + if is_direct_expn_of(expr.span, "matches").is_some() { + redundant_pattern_match::check_match(cx, expr, ex, arms); + } + if source == MatchSource::Normal && !is_span_match(cx, expr.span) { return; } diff --git a/clippy_lints/src/matches/redundant_pattern_match.rs b/clippy_lints/src/matches/redundant_pattern_match.rs index e81e09da425..479cfd83512 100644 --- a/clippy_lints/src/matches/redundant_pattern_match.rs +++ b/clippy_lints/src/matches/redundant_pattern_match.rs @@ -1,10 +1,10 @@ use super::REDUNDANT_PATTERN_MATCHING; -use clippy_utils::diagnostics::span_lint_and_then; +use clippy_utils::diagnostics::{span_lint_and_sugg, span_lint_and_then}; use clippy_utils::source::{snippet, walk_span_to_context}; use clippy_utils::sugg::Sugg; use clippy_utils::ty::{is_type_diagnostic_item, needs_ordered_drop}; use clippy_utils::visitors::any_temporaries_need_ordered_drop; -use clippy_utils::{higher, is_trait_method}; +use clippy_utils::{higher, is_expn_of, is_trait_method}; use if_chain::if_chain; use rustc_ast::ast::LitKind; use rustc_errors::Applicability; @@ -190,24 +190,19 @@ pub(super) fn check_match<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>, op let node_pair = (&arms[0].pat.kind, &arms[1].pat.kind); if let Some(good_method) = found_good_method(cx, arms, node_pair) { - let span = expr.span.to(op.span); + let span = is_expn_of(expr.span, "matches").unwrap_or(expr.span.to(op.span)); let result_expr = match &op.kind { ExprKind::AddrOf(_, _, borrowed) => borrowed, _ => op, }; - span_lint_and_then( + span_lint_and_sugg( cx, REDUNDANT_PATTERN_MATCHING, - expr.span, + span, &format!("redundant pattern matching, consider using `{good_method}`"), - |diag| { - diag.span_suggestion( - span, - "try this", - format!("{}.{good_method}", snippet(cx, result_expr.span, "_")), - Applicability::MaybeIncorrect, // snippet - ); - }, + "try this", + format!("{}.{good_method}", snippet(cx, result_expr.span, "_")), + Applicability::MachineApplicable, ); } } diff --git a/clippy_lints/src/methods/mod.rs b/clippy_lints/src/methods/mod.rs index 9a594d964ab..88cbefbb5d3 100644 --- a/clippy_lints/src/methods/mod.rs +++ b/clippy_lints/src/methods/mod.rs @@ -3191,7 +3191,7 @@ declare_clippy_lint! { /// let mut v = vec![1, 2, 3]; /// v.clear(); /// ``` - #[clippy::version = "1.69.0"] + #[clippy::version = "1.70.0"] pub CLEAR_WITH_DRAIN, nursery, "calling `drain` in order to `clear` a container" diff --git a/clippy_lints/src/missing_assert_message.rs b/clippy_lints/src/missing_assert_message.rs index 2214a568d9c..4dbb79334ca 100644 --- a/clippy_lints/src/missing_assert_message.rs +++ b/clippy_lints/src/missing_assert_message.rs @@ -36,7 +36,7 @@ declare_clippy_lint! { /// assert!(service.ready, "`service.poll_ready()` must be called first to ensure that service is ready to receive requests"); /// } /// ``` - #[clippy::version = "1.69.0"] + #[clippy::version = "1.70.0"] pub MISSING_ASSERT_MESSAGE, restriction, "checks assertions without a custom panic message" diff --git a/clippy_lints/src/missing_fields_in_debug.rs b/clippy_lints/src/missing_fields_in_debug.rs new file mode 100644 index 00000000000..b6f0de7e504 --- /dev/null +++ b/clippy_lints/src/missing_fields_in_debug.rs @@ -0,0 +1,234 @@ +use std::ops::ControlFlow; + +use clippy_utils::{ + diagnostics::span_lint_and_then, + is_path_lang_item, paths, + ty::match_type, + visitors::{for_each_expr, Visitable}, +}; +use rustc_ast::LitKind; +use rustc_data_structures::fx::FxHashSet; +use rustc_hir::Block; +use rustc_hir::{ + def::{DefKind, Res}, + Expr, ImplItemKind, LangItem, Node, +}; +use rustc_hir::{ExprKind, Impl, ItemKind, QPath, TyKind}; +use rustc_hir::{ImplItem, Item, VariantData}; +use rustc_lint::{LateContext, LateLintPass}; +use rustc_middle::ty::Ty; +use rustc_middle::ty::TypeckResults; +use rustc_session::{declare_lint_pass, declare_tool_lint}; +use rustc_span::{sym, Span, Symbol}; + +declare_clippy_lint! { + /// ### What it does + /// Checks for manual [`core::fmt::Debug`](https://doc.rust-lang.org/core/fmt/trait.Debug.html) implementations that do not use all fields. + /// + /// ### Why is this bad? + /// A common mistake is to forget to update manual `Debug` implementations when adding a new field + /// to a struct or a new variant to an enum. + /// + /// At the same time, it also acts as a style lint to suggest using [`core::fmt::DebugStruct::finish_non_exhaustive`](https://doc.rust-lang.org/core/fmt/struct.DebugStruct.html#method.finish_non_exhaustive) + /// for the times when the user intentionally wants to leave out certain fields (e.g. to hide implementation details). + /// + /// ### Known problems + /// This lint works based on the `DebugStruct` helper types provided by the `Formatter`, + /// so this won't detect `Debug` impls that use the `write!` macro. + /// Oftentimes there is more logic to a `Debug` impl if it uses `write!` macro, so it tries + /// to be on the conservative side and not lint in those cases in an attempt to prevent false positives. + /// + /// This lint also does not look through function calls, so calling a function does not consider fields + /// used inside of that function as used by the `Debug` impl. + /// + /// Lastly, it also ignores tuple structs as their `DebugTuple` formatter does not have a `finish_non_exhaustive` + /// method, as well as enums because their exhaustiveness is already checked by the compiler when matching on the enum, + /// making it much less likely to accidentally forget to update the `Debug` impl when adding a new variant. + /// + /// ### Example + /// ```rust + /// use std::fmt; + /// struct Foo { + /// data: String, + /// // implementation detail + /// hidden_data: i32 + /// } + /// impl fmt::Debug for Foo { + /// fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result { + /// formatter + /// .debug_struct("Foo") + /// .field("data", &self.data) + /// .finish() + /// } + /// } + /// ``` + /// Use instead: + /// ```rust + /// use std::fmt; + /// struct Foo { + /// data: String, + /// // implementation detail + /// hidden_data: i32 + /// } + /// impl fmt::Debug for Foo { + /// fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result { + /// formatter + /// .debug_struct("Foo") + /// .field("data", &self.data) + /// .finish_non_exhaustive() + /// } + /// } + /// ``` + #[clippy::version = "1.70.0"] + pub MISSING_FIELDS_IN_DEBUG, + pedantic, + "missing fields in manual `Debug` implementation" +} +declare_lint_pass!(MissingFieldsInDebug => [MISSING_FIELDS_IN_DEBUG]); + +fn report_lints(cx: &LateContext<'_>, span: Span, span_notes: Vec<(Span, &'static str)>) { + span_lint_and_then( + cx, + MISSING_FIELDS_IN_DEBUG, + span, + "manual `Debug` impl does not include all fields", + |diag| { + for (span, note) in span_notes { + diag.span_note(span, note); + } + diag.help("consider including all fields in this `Debug` impl") + .help("consider calling `.finish_non_exhaustive()` if you intend to ignore fields"); + }, + ); +} + +/// Checks if we should lint in a block of code +/// +/// The way we check for this condition is by checking if there is +/// a call to `Formatter::debug_struct` but no call to `.finish_non_exhaustive()`. +fn should_lint<'tcx>( + cx: &LateContext<'tcx>, + typeck_results: &TypeckResults<'tcx>, + block: impl Visitable<'tcx>, +) -> bool { + // Is there a call to `DebugStruct::finish_non_exhaustive`? Don't lint if there is. + let mut has_finish_non_exhaustive = false; + // Is there a call to `DebugStruct::debug_struct`? Do lint if there is. + let mut has_debug_struct = false; + + for_each_expr(block, |expr| { + if let ExprKind::MethodCall(path, recv, ..) = &expr.kind { + let recv_ty = typeck_results.expr_ty(recv).peel_refs(); + + if path.ident.name == sym::debug_struct && match_type(cx, recv_ty, &paths::FORMATTER) { + has_debug_struct = true; + } else if path.ident.name == sym!(finish_non_exhaustive) && match_type(cx, recv_ty, &paths::DEBUG_STRUCT) { + has_finish_non_exhaustive = true; + } + } + ControlFlow::::Continue(()) + }); + + !has_finish_non_exhaustive && has_debug_struct +} + +/// Checks if the given expression is a call to `DebugStruct::field` +/// and the first argument to it is a string literal and if so, returns it +/// +/// Example: `.field("foo", ....)` returns `Some("foo")` +fn as_field_call<'tcx>( + cx: &LateContext<'tcx>, + typeck_results: &TypeckResults<'tcx>, + expr: &Expr<'_>, +) -> Option { + if let ExprKind::MethodCall(path, recv, [debug_field, _], _) = &expr.kind + && let recv_ty = typeck_results.expr_ty(recv).peel_refs() + && match_type(cx, recv_ty, &paths::DEBUG_STRUCT) + && path.ident.name == sym::field + && let ExprKind::Lit(lit) = &debug_field.kind + && let LitKind::Str(sym, ..) = lit.node + { + Some(sym) + } else { + None + } +} + +/// Attempts to find unused fields assuming that the item is a struct +fn check_struct<'tcx>( + cx: &LateContext<'tcx>, + typeck_results: &TypeckResults<'tcx>, + block: &'tcx Block<'tcx>, + self_ty: Ty<'tcx>, + item: &'tcx Item<'tcx>, + data: &VariantData<'_>, +) { + // Is there a "direct" field access anywhere (i.e. self.foo)? + // We don't want to lint if there is not, because the user might have + // a newtype struct and use fields from the wrapped type only. + let mut has_direct_field_access = false; + let mut field_accesses = FxHashSet::default(); + + for_each_expr(block, |expr| { + if let ExprKind::Field(target, ident) = expr.kind + && let target_ty = typeck_results.expr_ty_adjusted(target).peel_refs() + && target_ty == self_ty + { + field_accesses.insert(ident.name); + has_direct_field_access = true; + } else if let Some(sym) = as_field_call(cx, typeck_results, expr) { + field_accesses.insert(sym); + } + ControlFlow::::Continue(()) + }); + + let span_notes = data + .fields() + .iter() + .filter_map(|field| { + if field_accesses.contains(&field.ident.name) || is_path_lang_item(cx, field.ty, LangItem::PhantomData) { + None + } else { + Some((field.span, "this field is unused")) + } + }) + .collect::>(); + + // only lint if there's also at least one direct field access to allow patterns + // where one might have a newtype struct and uses fields from the wrapped type + if !span_notes.is_empty() && has_direct_field_access { + report_lints(cx, item.span, span_notes); + } +} + +impl<'tcx> LateLintPass<'tcx> for MissingFieldsInDebug { + fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx rustc_hir::Item<'tcx>) { + // is this an `impl Debug for X` block? + if let ItemKind::Impl(Impl { of_trait: Some(trait_ref), self_ty, items, .. }) = item.kind + && let Res::Def(DefKind::Trait, trait_def_id) = trait_ref.path.res + && let TyKind::Path(QPath::Resolved(_, self_path)) = &self_ty.kind + && cx.match_def_path(trait_def_id, &[sym::core, sym::fmt, sym::Debug]) + // don't trigger if this impl was derived + && !cx.tcx.has_attr(item.owner_id, sym::automatically_derived) + && !item.span.from_expansion() + // find `Debug::fmt` function + && let Some(fmt_item) = items.iter().find(|i| i.ident.name == sym::fmt) + && let ImplItem { kind: ImplItemKind::Fn(_, body_id), .. } = cx.tcx.hir().impl_item(fmt_item.id) + && let body = cx.tcx.hir().body(*body_id) + && let ExprKind::Block(block, _) = body.value.kind + // inspect `self` + && let self_ty = cx.tcx.type_of(self_path.res.def_id()).skip_binder().peel_refs() + && let Some(self_adt) = self_ty.ty_adt_def() + && let Some(self_def_id) = self_adt.did().as_local() + && let Some(Node::Item(self_item)) = cx.tcx.hir().find_by_def_id(self_def_id) + // NB: can't call cx.typeck_results() as we are not in a body + && let typeck_results = cx.tcx.typeck_body(*body_id) + && should_lint(cx, typeck_results, block) + { + // we intentionally only lint structs, see lint description + if let ItemKind::Struct(data, _) = &self_item.kind { + check_struct(cx, typeck_results, block, self_ty, item, data); + } + } + } +} diff --git a/clippy_lints/src/needless_else.rs b/clippy_lints/src/needless_else.rs new file mode 100644 index 00000000000..4ff1bf7ffc0 --- /dev/null +++ b/clippy_lints/src/needless_else.rs @@ -0,0 +1,61 @@ +use clippy_utils::source::snippet_opt; +use clippy_utils::{diagnostics::span_lint_and_sugg, source::trim_span}; +use rustc_ast::ast::{Expr, ExprKind}; +use rustc_errors::Applicability; +use rustc_lint::{EarlyContext, EarlyLintPass, LintContext}; +use rustc_session::{declare_lint_pass, declare_tool_lint}; + +declare_clippy_lint! { + /// ### What it does + /// Checks for empty `else` branches. + /// + /// ### Why is this bad? + /// An empty else branch does nothing and can be removed. + /// + /// ### Example + /// ```rust + ///# fn check() -> bool { true } + /// if check() { + /// println!("Check successful!"); + /// } else { + /// } + /// ``` + /// Use instead: + /// ```rust + ///# fn check() -> bool { true } + /// if check() { + /// println!("Check successful!"); + /// } + /// ``` + #[clippy::version = "1.71.0"] + pub NEEDLESS_ELSE, + style, + "empty else branch" +} +declare_lint_pass!(NeedlessElse => [NEEDLESS_ELSE]); + +impl EarlyLintPass for NeedlessElse { + fn check_expr(&mut self, cx: &EarlyContext<'_>, expr: &Expr) { + if let ExprKind::If(_, then_block, Some(else_clause)) = &expr.kind + && let ExprKind::Block(block, _) = &else_clause.kind + && !expr.span.from_expansion() + && !else_clause.span.from_expansion() + && block.stmts.is_empty() + && let Some(trimmed) = expr.span.trim_start(then_block.span) + && let span = trim_span(cx.sess().source_map(), trimmed) + && let Some(else_snippet) = snippet_opt(cx, span) + // Ignore else blocks that contain comments or #[cfg]s + && !else_snippet.contains(['/', '#']) + { + span_lint_and_sugg( + cx, + NEEDLESS_ELSE, + span, + "this else branch is empty", + "you can remove it", + String::new(), + Applicability::MachineApplicable, + ); + } + } +} diff --git a/clippy_lints/src/nonstandard_macro_braces.rs b/clippy_lints/src/nonstandard_macro_braces.rs index 6c909e5ed73..2d79a5c9008 100644 --- a/clippy_lints/src/nonstandard_macro_braces.rs +++ b/clippy_lints/src/nonstandard_macro_braces.rs @@ -241,7 +241,7 @@ impl<'de> Deserialize<'de> for MacroMatcher { V: de::MapAccess<'de>, { let mut name = None; - let mut brace: Option<&str> = None; + let mut brace: Option = None; while let Some(key) = map.next_key()? { match key { Field::Name => { diff --git a/clippy_lints/src/redundant_async_block.rs b/clippy_lints/src/redundant_async_block.rs index a0f831764d0..05e52e6b38b 100644 --- a/clippy_lints/src/redundant_async_block.rs +++ b/clippy_lints/src/redundant_async_block.rs @@ -35,7 +35,7 @@ declare_clippy_lint! { /// }; /// let fut = f; /// ``` - #[clippy::version = "1.69.0"] + #[clippy::version = "1.70.0"] pub REDUNDANT_ASYNC_BLOCK, complexity, "`async { future.await }` can be replaced by `future`" diff --git a/clippy_lints/src/regex.rs b/clippy_lints/src/regex.rs index ef19c6f4617..674f8bf4c0f 100644 --- a/clippy_lints/src/regex.rs +++ b/clippy_lints/src/regex.rs @@ -177,7 +177,7 @@ fn check_set<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>, utf8: bool) { } fn check_regex<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>, utf8: bool) { - let mut parser = regex_syntax::ParserBuilder::new().unicode(true).utf8(!utf8).build(); + let mut parser = regex_syntax::ParserBuilder::new().unicode(true).utf8(utf8).build(); if let ExprKind::Lit(lit) = expr.kind { if let LitKind::Str(ref r, style) = lit.node { diff --git a/clippy_lints/src/returns.rs b/clippy_lints/src/returns.rs index df126d7617e..631ecf1428d 100644 --- a/clippy_lints/src/returns.rs +++ b/clippy_lints/src/returns.rs @@ -70,7 +70,7 @@ declare_clippy_lint! { "using a return statement like `return expr;` where an expression would suffice" } -#[derive(PartialEq, Eq, Clone)] +#[derive(PartialEq, Eq)] enum RetReplacement<'tcx> { Empty, Block, @@ -80,7 +80,7 @@ enum RetReplacement<'tcx> { } impl<'tcx> RetReplacement<'tcx> { - fn sugg_help(self) -> &'static str { + fn sugg_help(&self) -> &'static str { match self { Self::Empty | Self::Expr(..) => "remove `return`", Self::Block => "replace `return` with an empty block", @@ -88,10 +88,11 @@ impl<'tcx> RetReplacement<'tcx> { Self::IfSequence(..) => "remove `return` and wrap the sequence with parentheses", } } - fn applicability(&self) -> Option { + + fn applicability(&self) -> Applicability { match self { - Self::Expr(_, ap) | Self::IfSequence(_, ap) => Some(*ap), - _ => None, + Self::Expr(_, ap) | Self::IfSequence(_, ap) => *ap, + _ => Applicability::MachineApplicable, } } } @@ -271,7 +272,7 @@ fn check_final_expr<'tcx>( return; } - emit_return_lint(cx, ret_span, semi_spans, replacement); + emit_return_lint(cx, ret_span, semi_spans, &replacement); }, ExprKind::If(_, then, else_clause_opt) => { check_block_return(cx, &then.kind, peeled_drop_expr.span, semi_spans.clone()); @@ -306,20 +307,17 @@ fn expr_contains_conjunctive_ifs<'tcx>(expr: &'tcx Expr<'tcx>) -> bool { contains_if(expr, false) } -fn emit_return_lint(cx: &LateContext<'_>, ret_span: Span, semi_spans: Vec, replacement: RetReplacement<'_>) { +fn emit_return_lint(cx: &LateContext<'_>, ret_span: Span, semi_spans: Vec, replacement: &RetReplacement<'_>) { 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(); span_lint_and_then(cx, NEEDLESS_RETURN, ret_span, "unneeded `return` statement", |diag| { - diag.span_suggestion_hidden(ret_span, sugg_help, return_replacement, applicability); - // for each parent statement, we need to remove the semicolon - for semi_stmt_span in semi_spans { - diag.tool_only_span_suggestion(semi_stmt_span, "remove this semicolon", "", applicability); - } + let suggestions = std::iter::once((ret_span, replacement.to_string())) + .chain(semi_spans.into_iter().map(|span| (span, String::new()))) + .collect(); + + diag.multipart_suggestion_verbose(replacement.sugg_help(), suggestions, replacement.applicability()); }); } diff --git a/clippy_lints/src/strings.rs b/clippy_lints/src/strings.rs index 483f860a8b5..8658009eba4 100644 --- a/clippy_lints/src/strings.rs +++ b/clippy_lints/src/strings.rs @@ -2,7 +2,7 @@ use clippy_utils::diagnostics::{span_lint, span_lint_and_help, span_lint_and_sug use clippy_utils::source::{snippet, snippet_with_applicability}; use clippy_utils::ty::is_type_lang_item; use clippy_utils::{get_expr_use_or_unification_node, peel_blocks, SpanlessEq}; -use clippy_utils::{get_parent_expr, is_lint_allowed, match_function_call, method_calls, paths}; +use clippy_utils::{get_parent_expr, is_lint_allowed, is_path_diagnostic_item, method_calls}; use if_chain::if_chain; use rustc_errors::Applicability; use rustc_hir::def_id::DefId; @@ -255,7 +255,8 @@ impl<'tcx> LateLintPass<'tcx> for StringLitAsBytes { if_chain! { // Find std::str::converts::from_utf8 - if let Some(args) = match_function_call(cx, e, &paths::STR_FROM_UTF8); + if let ExprKind::Call(fun, args) = e.kind; + if is_path_diagnostic_item(cx, fun, sym::str_from_utf8); // Find string::as_bytes if let ExprKind::AddrOf(BorrowKind::Ref, _, args) = args[0].kind; diff --git a/clippy_lints/src/unused_async.rs b/clippy_lints/src/unused_async.rs index 55651a28be9..117dda09222 100644 --- a/clippy_lints/src/unused_async.rs +++ b/clippy_lints/src/unused_async.rs @@ -1,5 +1,5 @@ -use clippy_utils::diagnostics::span_lint_and_help; -use rustc_hir::intravisit::{walk_expr, walk_fn, FnKind, Visitor}; +use clippy_utils::diagnostics::span_lint_and_then; +use rustc_hir::intravisit::{walk_body, walk_expr, walk_fn, FnKind, Visitor}; use rustc_hir::{Body, Expr, ExprKind, FnDecl, YieldSource}; use rustc_lint::{LateContext, LateLintPass}; use rustc_middle::hir::nested_filter; @@ -42,6 +42,10 @@ declare_lint_pass!(UnusedAsync => [UNUSED_ASYNC]); struct AsyncFnVisitor<'a, 'tcx> { cx: &'a LateContext<'tcx>, found_await: bool, + /// Also keep track of `await`s in nested async blocks so we can mention + /// it in a note + await_in_async_block: Option, + async_depth: usize, } impl<'a, 'tcx> Visitor<'tcx> for AsyncFnVisitor<'a, 'tcx> { @@ -49,7 +53,11 @@ impl<'a, 'tcx> Visitor<'tcx> for AsyncFnVisitor<'a, 'tcx> { fn visit_expr(&mut self, ex: &'tcx Expr<'tcx>) { if let ExprKind::Yield(_, YieldSource::Await { .. }) = ex.kind { - self.found_await = true; + if self.async_depth == 1 { + self.found_await = true; + } else if self.await_in_async_block.is_none() { + self.await_in_async_block = Some(ex.span); + } } walk_expr(self, ex); } @@ -57,6 +65,20 @@ impl<'a, 'tcx> Visitor<'tcx> for AsyncFnVisitor<'a, 'tcx> { fn nested_visit_map(&mut self) -> Self::Map { self.cx.tcx.hir() } + + fn visit_body(&mut self, b: &'tcx Body<'tcx>) { + let is_async_block = matches!(b.generator_kind, Some(rustc_hir::GeneratorKind::Async(_))); + + if is_async_block { + self.async_depth += 1; + } + + walk_body(self, b); + + if is_async_block { + self.async_depth -= 1; + } + } } impl<'tcx> LateLintPass<'tcx> for UnusedAsync { @@ -70,16 +92,30 @@ impl<'tcx> LateLintPass<'tcx> for UnusedAsync { def_id: LocalDefId, ) { if !span.from_expansion() && fn_kind.asyncness().is_async() { - let mut visitor = AsyncFnVisitor { cx, found_await: false }; + let mut visitor = AsyncFnVisitor { + cx, + found_await: false, + async_depth: 0, + await_in_async_block: None, + }; walk_fn(&mut visitor, fn_kind, fn_decl, body.id(), def_id); if !visitor.found_await { - span_lint_and_help( + span_lint_and_then( cx, UNUSED_ASYNC, span, "unused `async` for function with no await statements", - None, - "consider removing the `async` from this function", + |diag| { + diag.help("consider removing the `async` from this function"); + + if let Some(span) = visitor.await_in_async_block { + diag.span_note( + span, + "`await` used in an async block, which does not require \ + the enclosing function to be `async`", + ); + } + }, ); } } diff --git a/clippy_lints/src/utils/conf.rs b/clippy_lints/src/utils/conf.rs index f6de66bb514..35f40830681 100644 --- a/clippy_lints/src/utils/conf.rs +++ b/clippy_lints/src/utils/conf.rs @@ -2,12 +2,15 @@ #![allow(clippy::module_name_repetitions)] +use rustc_session::Session; +use rustc_span::{BytePos, Pos, SourceFile, Span, SyntaxContext}; use serde::de::{Deserializer, IgnoredAny, IntoDeserializer, MapAccess, Visitor}; use serde::Deserialize; -use std::error::Error; +use std::fmt::{Debug, Display, Formatter}; +use std::ops::Range; use std::path::{Path, PathBuf}; use std::str::FromStr; -use std::{cmp, env, fmt, fs, io, iter}; +use std::{cmp, env, fmt, fs, io}; #[rustfmt::skip] const DEFAULT_DOC_VALID_IDENTS: &[&str] = &[ @@ -67,33 +70,70 @@ impl DisallowedPath { #[derive(Default)] pub struct TryConf { pub conf: Conf, - pub errors: Vec>, - pub warnings: Vec>, + pub errors: Vec, + pub warnings: Vec, } impl TryConf { - fn from_error(error: impl Error + 'static) -> Self { + fn from_toml_error(file: &SourceFile, error: &toml::de::Error) -> Self { + ConfError::from_toml(file, error).into() + } +} + +impl From for TryConf { + fn from(value: ConfError) -> Self { Self { conf: Conf::default(), - errors: vec![Box::new(error)], + errors: vec![value], warnings: vec![], } } } -#[derive(Debug)] -struct ConfError(String); - -impl fmt::Display for ConfError { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - ::fmt(&self.0, f) +impl From for TryConf { + fn from(value: io::Error) -> Self { + ConfError::from(value).into() } } -impl Error for ConfError {} +#[derive(Debug)] +pub struct ConfError { + pub message: String, + pub span: Option, +} -fn conf_error(s: impl Into) -> Box { - Box::new(ConfError(s.into())) +impl ConfError { + fn from_toml(file: &SourceFile, error: &toml::de::Error) -> Self { + if let Some(span) = error.span() { + Self::spanned(file, error.message(), span) + } else { + Self { + message: error.message().to_string(), + span: None, + } + } + } + + fn spanned(file: &SourceFile, message: impl Into, span: Range) -> Self { + Self { + message: message.into(), + span: Some(Span::new( + file.start_pos + BytePos::from_usize(span.start), + file.start_pos + BytePos::from_usize(span.end), + SyntaxContext::root(), + None, + )), + } + } +} + +impl From for ConfError { + fn from(value: io::Error) -> Self { + Self { + message: value.to_string(), + span: None, + } + } } macro_rules! define_Conf { @@ -117,20 +157,14 @@ macro_rules! define_Conf { } } - impl<'de> Deserialize<'de> for TryConf { - fn deserialize(deserializer: D) -> Result where D: Deserializer<'de> { - deserializer.deserialize_map(ConfVisitor) - } - } - #[derive(Deserialize)] #[serde(field_identifier, rename_all = "kebab-case")] #[allow(non_camel_case_types)] enum Field { $($name,)* third_party, } - struct ConfVisitor; + struct ConfVisitor<'a>(&'a SourceFile); - impl<'de> Visitor<'de> for ConfVisitor { + impl<'de> Visitor<'de> for ConfVisitor<'_> { type Value = TryConf; fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result { @@ -141,32 +175,38 @@ macro_rules! define_Conf { let mut errors = Vec::new(); let mut warnings = Vec::new(); $(let mut $name = None;)* - // could get `Field` here directly, but get `str` first for diagnostics - while let Some(name) = map.next_key::<&str>()? { - match Field::deserialize(name.into_deserializer())? { - $(Field::$name => { - $(warnings.push(conf_error(format!("deprecated field `{}`. {}", name, $dep)));)? - match map.next_value() { - Err(e) => errors.push(conf_error(e.to_string())), + // could get `Field` here directly, but get `String` first for diagnostics + while let Some(name) = map.next_key::>()? { + match Field::deserialize(name.get_ref().as_str().into_deserializer()) { + Err(e) => { + let e: FieldError = e; + errors.push(ConfError::spanned(self.0, e.0, name.span())); + } + $(Ok(Field::$name) => { + $(warnings.push(ConfError::spanned(self.0, format!("deprecated field `{}`. {}", name.get_ref(), $dep), name.span()));)? + let raw_value = map.next_value::>()?; + let value_span = raw_value.span(); + match <$ty>::deserialize(raw_value.into_inner()) { + Err(e) => errors.push(ConfError::spanned(self.0, e.to_string().replace('\n', " ").trim(), value_span)), Ok(value) => match $name { - Some(_) => errors.push(conf_error(format!("duplicate field `{}`", name))), + Some(_) => errors.push(ConfError::spanned(self.0, format!("duplicate field `{}`", name.get_ref()), name.span())), None => { $name = Some(value); // $new_conf is the same as one of the defined `$name`s, so // this variable is defined in line 2 of this function. $(match $new_conf { - Some(_) => errors.push(conf_error(concat!( + Some(_) => errors.push(ConfError::spanned(self.0, concat!( "duplicate field `", stringify!($new_conf), "` (provided as `", stringify!($name), "`)" - ))), + ), name.span())), None => $new_conf = $name.clone(), })? }, } } })* - // white-listed; ignore - Field::third_party => drop(map.next_value::()) + // ignore contents of the third_party key + Ok(Field::third_party) => drop(map.next_value::()) } } let conf = Conf { $($name: $name.unwrap_or_else(defaults::$name),)* }; @@ -486,7 +526,7 @@ pub fn lookup_conf_file() -> io::Result<(Option, Vec)> { const CONFIG_FILE_NAMES: [&str; 2] = [".clippy.toml", "clippy.toml"]; // Start looking for a config file in CLIPPY_CONF_DIR, or failing that, CARGO_MANIFEST_DIR. - // If neither of those exist, use ".". + // If neither of those exist, use ".". (Update documentation if this priority changes) let mut current = env::var_os("CLIPPY_CONF_DIR") .or_else(|| env::var_os("CARGO_MANIFEST_DIR")) .map_or_else(|| PathBuf::from("."), PathBuf::from) @@ -532,19 +572,19 @@ pub fn lookup_conf_file() -> io::Result<(Option, Vec)> { /// Read the `toml` configuration file. /// /// In case of error, the function tries to continue as much as possible. -pub fn read(path: &Path) -> TryConf { - let content = match fs::read_to_string(path) { - Err(e) => return TryConf::from_error(e), - Ok(content) => content, +pub fn read(sess: &Session, path: &Path) -> TryConf { + let file = match sess.source_map().load_file(path) { + Err(e) => return e.into(), + Ok(file) => file, }; - match toml::from_str::(&content) { + match toml::de::Deserializer::new(file.src.as_ref().unwrap()).deserialize_map(ConfVisitor(&file)) { Ok(mut conf) => { extend_vec_if_indicator_present(&mut conf.conf.doc_valid_idents, DEFAULT_DOC_VALID_IDENTS); extend_vec_if_indicator_present(&mut conf.conf.disallowed_names, DEFAULT_DISALLOWED_NAMES); conf }, - Err(e) => TryConf::from_error(e), + Err(e) => TryConf::from_toml_error(&file, &e), } } @@ -556,65 +596,42 @@ fn extend_vec_if_indicator_present(vec: &mut Vec, default: &[&str]) { const SEPARATOR_WIDTH: usize = 4; -// Check whether the error is "unknown field" and, if so, list the available fields sorted and at -// least one per line, more if `CLIPPY_TERMINAL_WIDTH` is set and allows it. -pub fn format_error(error: Box) -> String { - let s = error.to_string(); +#[derive(Debug)] +struct FieldError(String); - if_chain! { - if error.downcast::().is_ok(); - if let Some((prefix, mut fields, suffix)) = parse_unknown_field_message(&s); - then { - use fmt::Write; +impl std::error::Error for FieldError {} - fields.sort_unstable(); - - let (rows, column_widths) = calculate_dimensions(&fields); - - let mut msg = String::from(prefix); - for row in 0..rows { - writeln!(msg).unwrap(); - for (column, column_width) in column_widths.iter().copied().enumerate() { - let index = column * rows + row; - let field = fields.get(index).copied().unwrap_or_default(); - write!( - msg, - "{:SEPARATOR_WIDTH$}{field:column_width$}", - " " - ) - .unwrap(); - } - } - write!(msg, "\n{suffix}").unwrap(); - msg - } else { - s - } +impl Display for FieldError { + fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { + f.pad(&self.0) } } -// `parse_unknown_field_message` will become unnecessary if -// https://github.com/alexcrichton/toml-rs/pull/364 is merged. -fn parse_unknown_field_message(s: &str) -> Option<(&str, Vec<&str>, &str)> { - // An "unknown field" message has the following form: - // unknown field `UNKNOWN`, expected one of `FIELD0`, `FIELD1`, ..., `FIELDN` at line X column Y - // ^^ ^^^^ ^^ - if_chain! { - if s.starts_with("unknown field"); - let slices = s.split("`, `").collect::>(); - let n = slices.len(); - if n >= 2; - if let Some((prefix, first_field)) = slices[0].rsplit_once(" `"); - if let Some((last_field, suffix)) = slices[n - 1].split_once("` "); - then { - let fields = iter::once(first_field) - .chain(slices[1..n - 1].iter().copied()) - .chain(iter::once(last_field)) - .collect::>(); - Some((prefix, fields, suffix)) - } else { - None +impl serde::de::Error for FieldError { + fn custom(msg: T) -> Self { + Self(msg.to_string()) + } + + fn unknown_field(field: &str, expected: &'static [&'static str]) -> Self { + // List the available fields sorted and at least one per line, more if `CLIPPY_TERMINAL_WIDTH` is + // set and allows it. + use fmt::Write; + + let mut expected = expected.to_vec(); + expected.sort_unstable(); + + let (rows, column_widths) = calculate_dimensions(&expected); + + let mut msg = format!("unknown field `{field}`, expected one of"); + for row in 0..rows { + writeln!(msg).unwrap(); + for (column, column_width) in column_widths.iter().copied().enumerate() { + let index = column * rows + row; + let field = expected.get(index).copied().unwrap_or_default(); + write!(msg, "{:SEPARATOR_WIDTH$}{field:column_width$}", " ").unwrap(); + } } + Self(msg) } } diff --git a/clippy_lints/src/wildcard_imports.rs b/clippy_lints/src/wildcard_imports.rs index a9089fba3c5..b6e4cd22789 100644 --- a/clippy_lints/src/wildcard_imports.rs +++ b/clippy_lints/src/wildcard_imports.rs @@ -65,8 +65,9 @@ declare_clippy_lint! { /// This can lead to confusing error messages at best and to unexpected behavior at worst. /// /// ### Exceptions - /// Wildcard imports are allowed from modules named `prelude`. Many crates (including the standard library) - /// provide modules named "prelude" specifically designed for wildcard import. + /// Wildcard imports are allowed from modules that their name contains `prelude`. Many crates + /// (including the standard library) provide modules named "prelude" specifically designed + /// for wildcard import. /// /// `use super::*` is allowed in test modules. This is defined as any module with "test" in the name. /// @@ -212,7 +213,9 @@ impl WildcardImports { // Allow "...prelude::..::*" imports. // Many crates have a prelude, and it is imported as a glob by design. fn is_prelude_import(segments: &[PathSegment<'_>]) -> bool { - segments.iter().any(|ps| ps.ident.name == sym::prelude) + segments + .iter() + .any(|ps| ps.ident.name.as_str().contains(sym::prelude.as_str())) } // Allow "super::*" imports in tests. diff --git a/clippy_utils/Cargo.toml b/clippy_utils/Cargo.toml index 66a5079fa85..cfe686eb9b0 100644 --- a/clippy_utils/Cargo.toml +++ b/clippy_utils/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "clippy_utils" -version = "0.1.71" +version = "0.1.72" edition = "2021" publish = false diff --git a/clippy_utils/src/lib.rs b/clippy_utils/src/lib.rs index 575c29a6b6f..8c883445a79 100644 --- a/clippy_utils/src/lib.rs +++ b/clippy_utils/src/lib.rs @@ -287,7 +287,7 @@ pub fn is_wild(pat: &Pat<'_>) -> bool { /// Checks if the given `QPath` belongs to a type alias. pub fn is_ty_alias(qpath: &QPath<'_>) -> bool { match *qpath { - QPath::Resolved(_, path) => matches!(path.res, Res::Def(DefKind::TyAlias, ..)), + QPath::Resolved(_, path) => matches!(path.res, Res::Def(DefKind::TyAlias | DefKind::AssocTy, ..)), QPath::TypeRelative(ty, _) if let TyKind::Path(qpath) = ty.kind => { is_ty_alias(&qpath) }, _ => false, } diff --git a/clippy_utils/src/msrvs.rs b/clippy_utils/src/msrvs.rs index e05de2dc99c..6f102308f0b 100644 --- a/clippy_utils/src/msrvs.rs +++ b/clippy_utils/src/msrvs.rs @@ -20,7 +20,7 @@ macro_rules! msrv_aliases { // names may refer to stabilized feature flags or library items msrv_aliases! { 1,68,0 { PATH_MAIN_SEPARATOR_STR } - 1,65,0 { LET_ELSE } + 1,65,0 { LET_ELSE, POINTER_CAST_CONSTNESS } 1,62,0 { BOOL_THEN_SOME, DEFAULT_ENUM_ATTRIBUTE } 1,58,0 { FORMAT_ARGS_CAPTURE, PATTERN_TRAIT_CHAR_ARRAY } 1,55,0 { SEEK_REWIND } diff --git a/clippy_utils/src/paths.rs b/clippy_utils/src/paths.rs index 0f0792fdaa9..38ee84fb76c 100644 --- a/clippy_utils/src/paths.rs +++ b/clippy_utils/src/paths.rs @@ -125,8 +125,6 @@ pub const STRING_NEW: [&str; 4] = ["alloc", "string", "String", "new"]; pub const STR_BYTES: [&str; 4] = ["core", "str", "", "bytes"]; pub const STR_CHARS: [&str; 4] = ["core", "str", "", "chars"]; pub const STR_ENDS_WITH: [&str; 4] = ["core", "str", "", "ends_with"]; -pub const STR_FROM_UTF8: [&str; 4] = ["core", "str", "converts", "from_utf8"]; -pub const STR_FROM_UTF8_UNCHECKED: [&str; 4] = ["core", "str", "converts", "from_utf8_unchecked"]; pub const STR_LEN: [&str; 4] = ["core", "str", "", "len"]; pub const STR_STARTS_WITH: [&str; 4] = ["core", "str", "", "starts_with"]; #[cfg(feature = "internal")] @@ -163,3 +161,5 @@ 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"]; +pub const FORMATTER: [&str; 3] = ["core", "fmt", "Formatter"]; +pub const DEBUG_STRUCT: [&str; 4] = ["core", "fmt", "builders", "DebugStruct"]; diff --git a/clippy_utils/src/source.rs b/clippy_utils/src/source.rs index 0f60290644a..582337b47e8 100644 --- a/clippy_utils/src/source.rs +++ b/clippy_utils/src/source.rs @@ -4,7 +4,7 @@ use rustc_data_structures::sync::Lrc; use rustc_errors::Applicability; -use rustc_hir::{Expr, ExprKind}; +use rustc_hir::{BlockCheckMode, Expr, ExprKind, UnsafeSource}; use rustc_lint::{LateContext, LintContext}; use rustc_session::Session; use rustc_span::source_map::{original_sp, SourceMap}; @@ -71,11 +71,16 @@ pub fn expr_block( app: &mut Applicability, ) -> String { let (code, from_macro) = snippet_block_with_context(cx, expr.span, outer, default, indent_relative_to, app); - if from_macro { - format!("{{ {code} }}") - } else if let ExprKind::Block(_, _) = expr.kind { + if !from_macro && + let ExprKind::Block(block, _) = expr.kind && + block.rules != BlockCheckMode::UnsafeBlock(UnsafeSource::UserProvided) + { format!("{code}") } else { + // FIXME: add extra indent for the unsafe blocks: + // original code: unsafe { ... } + // result code: { unsafe { ... } } + // desired code: {\n unsafe { ... }\n} format!("{{ {code} }}") } } diff --git a/declare_clippy_lint/Cargo.toml b/declare_clippy_lint/Cargo.toml index 139102798c4..4dc906d00db 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.71" +version = "0.1.72" edition = "2021" publish = false diff --git a/lintcheck/Cargo.toml b/lintcheck/Cargo.toml index 27d32f39003..a828d123704 100644 --- a/lintcheck/Cargo.toml +++ b/lintcheck/Cargo.toml @@ -22,7 +22,7 @@ rayon = "1.5.1" serde = { version = "1.0", features = ["derive"] } serde_json = "1.0.85" tar = "0.4" -toml = "0.5" +toml = "0.7.3" ureq = "2.2" walkdir = "2.3" diff --git a/rust-toolchain b/rust-toolchain index bc7fb711ed8..0d2e1eee643 100644 --- a/rust-toolchain +++ b/rust-toolchain @@ -1,3 +1,3 @@ [toolchain] -channel = "nightly-2023-05-20" +channel = "nightly-2023-06-02" components = ["cargo", "llvm-tools", "rust-src", "rust-std", "rustc", "rustc-dev", "rustfmt"] diff --git a/src/driver.rs b/src/driver.rs index 59bf447a7cd..3c5b6e12b96 100644 --- a/src/driver.rs +++ b/src/driver.rs @@ -70,7 +70,7 @@ fn track_clippy_args(parse_sess: &mut ParseSess, args_env_var: &Option) /// Track files that may be accessed at runtime in `file_depinfo` so that cargo will re-run clippy /// when any of them are modified -fn track_files(parse_sess: &mut ParseSess, conf_path_string: Option) { +fn track_files(parse_sess: &mut ParseSess) { let file_depinfo = parse_sess.file_depinfo.get_mut(); // Used by `clippy::cargo` lints and to determine the MSRV. `cargo clippy` executes `clippy-driver` @@ -79,10 +79,7 @@ fn track_files(parse_sess: &mut ParseSess, conf_path_string: Option) { file_depinfo.insert(Symbol::intern("Cargo.toml")); } - // `clippy.toml` - if let Some(path) = conf_path_string { - file_depinfo.insert(Symbol::intern(&path)); - } + // `clippy.toml` will be automatically tracked as it's loaded with `sess.source_map().load_file()` // During development track the `clippy-driver` executable so that cargo will re-run clippy whenever // it is rebuilt @@ -126,17 +123,11 @@ 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 { - path.to_str().map(String::from) - } else { - None - }; - let previous = config.register_lints.take(); let clippy_args_var = self.clippy_args_var.take(); config.parse_sess_created = Some(Box::new(move |parse_sess| { track_clippy_args(parse_sess, &clippy_args_var); - track_files(parse_sess, conf_path_string); + track_files(parse_sess); })); config.register_lints = Some(Box::new(move |sess, lint_store| { // technically we're ~guaranteed that this is none but might as well call anything that diff --git a/tests/ui-cargo/multiple_crate_versions/fail/Cargo.lock b/tests/ui-cargo/multiple_crate_versions/fail/Cargo.lock index 7e96aa36feb..e4de82ad3b8 100644 --- a/tests/ui-cargo/multiple_crate_versions/fail/Cargo.lock +++ b/tests/ui-cargo/multiple_crate_versions/fail/Cargo.lock @@ -1,5 +1,7 @@ # This file is automatically @generated by Cargo. # It is not intended for manual editing. +version = 3 + [[package]] name = "ansi_term" version = "0.11.0" @@ -9,71 +11,14 @@ dependencies = [ "winapi 0.3.9", ] -[[package]] -name = "bitflags" -version = "0.9.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4efd02e230a02e18f92fc2735f44597385ed02ad8f831e7c1c1156ee5e1ab3a5" - -[[package]] -name = "cfg-if" -version = "0.1.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822" - -[[package]] -name = "ctrlc" -version = "3.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "653abc99aa905f693d89df4797fadc08085baee379db92be9f2496cefe8a6f2c" -dependencies = [ - "kernel32-sys", - "nix", - "winapi 0.2.8", -] - -[[package]] -name = "kernel32-sys" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d" -dependencies = [ - "winapi 0.2.8", - "winapi-build", -] - -[[package]] -name = "libc" -version = "0.2.71" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9457b06509d27052635f90d6466700c65095fdf75409b3fbdd903e988b886f49" - [[package]] name = "multiple_crate_versions" version = "0.1.0" dependencies = [ "ansi_term", - "ctrlc", + "winapi 0.2.8", ] -[[package]] -name = "nix" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a2c5afeb0198ec7be8569d666644b574345aad2e95a53baf3a532da3e0f3fb32" -dependencies = [ - "bitflags", - "cfg-if", - "libc", - "void", -] - -[[package]] -name = "void" -version = "1.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6a02e4885ed3bc0f2de90ea6dd45ebcbb66dacffe03547fadbb0eeae2770887d" - [[package]] name = "winapi" version = "0.2.8" @@ -90,12 +35,6 @@ dependencies = [ "winapi-x86_64-pc-windows-gnu", ] -[[package]] -name = "winapi-build" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2d315eee3b34aca4797b2da6b13ed88266e6d612562a0c46390af8299fc699bc" - [[package]] name = "winapi-i686-pc-windows-gnu" version = "0.4.0" diff --git a/tests/ui-cargo/multiple_crate_versions/fail/Cargo.toml b/tests/ui-cargo/multiple_crate_versions/fail/Cargo.toml index 4f97b011334..79317659ac0 100644 --- a/tests/ui-cargo/multiple_crate_versions/fail/Cargo.toml +++ b/tests/ui-cargo/multiple_crate_versions/fail/Cargo.toml @@ -6,5 +6,5 @@ publish = false [workspace] [dependencies] -ctrlc = "=3.1.0" +winapi = "0.2" ansi_term = "=0.11.0" diff --git a/tests/ui-internal/custom_ice_message.rs b/tests/ui-internal/custom_ice_message.rs index 99ce7028390..9b0db660c99 100644 --- a/tests/ui-internal/custom_ice_message.rs +++ b/tests/ui-internal/custom_ice_message.rs @@ -3,7 +3,7 @@ //@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: "running on .*" -> "running on " +//@normalize-stderr-test: "rustc 1\.\d+.* running on .*" -> "rustc running on " //@normalize-stderr-test: "(?ms)query stack during panic:\n.*end of query stack\n" -> "" #![deny(clippy::internal)] diff --git a/tests/ui-internal/custom_ice_message.stderr b/tests/ui-internal/custom_ice_message.stderr index 0fc385cd693..b9ea5a64de7 100644 --- a/tests/ui-internal/custom_ice_message.stderr +++ b/tests/ui-internal/custom_ice_message.stderr @@ -5,10 +5,9 @@ error: the compiler unexpectedly panicked. this is a bug. note: we would appreciate a bug report: https://github.com/rust-lang/rust-clippy/issues/new -note: rustc 1.71.0-nightly (521f4dae1 2023-05-19) running on +note: rustc running on note: compiler flags: -C prefer-dynamic -Z ui-testing -note: Clippy version: foo - -thread panicked while panicking. aborting. +query stack during panic: +thread panicked while processing panic. aborting. diff --git a/tests/ui-toml/bad_toml/conf_bad_toml.stderr b/tests/ui-toml/bad_toml/conf_bad_toml.stderr index 28c1a568a63..5b7e8c0db74 100644 --- a/tests/ui-toml/bad_toml/conf_bad_toml.stderr +++ b/tests/ui-toml/bad_toml/conf_bad_toml.stderr @@ -1,4 +1,8 @@ -error: error reading Clippy's configuration file `$DIR/clippy.toml`: expected an equals, found an identifier at line 1 column 4 +error: error reading Clippy's configuration file: expected `.`, `=` + --> $DIR/clippy.toml:1:4 + | +LL | fn this_is_obviously(not: a, toml: file) { + | ^ error: aborting due to previous error diff --git a/tests/ui-toml/bad_toml_type/conf_bad_type.stderr b/tests/ui-toml/bad_toml_type/conf_bad_type.stderr index e3ec6019204..386e1135df9 100644 --- a/tests/ui-toml/bad_toml_type/conf_bad_type.stderr +++ b/tests/ui-toml/bad_toml_type/conf_bad_type.stderr @@ -1,4 +1,8 @@ -error: error reading Clippy's configuration file `$DIR/clippy.toml`: invalid type: integer `42`, expected a sequence for key `disallowed-names` +error: error reading Clippy's configuration file: invalid type: integer `42`, expected a sequence + --> $DIR/clippy.toml:1:20 + | +LL | disallowed-names = 42 + | ^^ error: aborting due to previous error diff --git a/tests/ui-toml/conf_deprecated_key/conf_deprecated_key.stderr b/tests/ui-toml/conf_deprecated_key/conf_deprecated_key.stderr index 630bad07c5b..123ad94dd09 100644 --- a/tests/ui-toml/conf_deprecated_key/conf_deprecated_key.stderr +++ b/tests/ui-toml/conf_deprecated_key/conf_deprecated_key.stderr @@ -1,6 +1,14 @@ -warning: error reading Clippy's configuration file `$DIR/clippy.toml`: deprecated field `cyclomatic-complexity-threshold`. Please use `cognitive-complexity-threshold` instead +warning: error reading Clippy's configuration file: deprecated field `cyclomatic-complexity-threshold`. Please use `cognitive-complexity-threshold` instead + --> $DIR/clippy.toml:2:1 + | +LL | cyclomatic-complexity-threshold = 2 + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -warning: error reading Clippy's configuration file `$DIR/clippy.toml`: deprecated field `blacklisted-names`. Please use `disallowed-names` instead +warning: error reading Clippy's configuration file: deprecated field `blacklisted-names`. Please use `disallowed-names` instead + --> $DIR/clippy.toml:3:1 + | +LL | blacklisted-names = [ "..", "wibble" ] + | ^^^^^^^^^^^^^^^^^ error: the function has a cognitive complexity of (3/2) --> $DIR/conf_deprecated_key.rs:6:4 diff --git a/tests/ui-toml/duplicated_keys/clippy.toml b/tests/ui-toml/duplicated_keys/clippy.toml index 63a893cc6c7..55789afc1b7 100644 --- a/tests/ui-toml/duplicated_keys/clippy.toml +++ b/tests/ui-toml/duplicated_keys/clippy.toml @@ -1,5 +1,2 @@ cognitive-complexity-threshold = 2 -# This is the deprecated name for the same key -cyclomatic-complexity-threshold = 3 -# Check we get duplication warning regardless of order cognitive-complexity-threshold = 4 diff --git a/tests/ui-toml/duplicated_keys/duplicated_keys.stderr b/tests/ui-toml/duplicated_keys/duplicated_keys.stderr index d99490a242d..54997735274 100644 --- a/tests/ui-toml/duplicated_keys/duplicated_keys.stderr +++ b/tests/ui-toml/duplicated_keys/duplicated_keys.stderr @@ -1,8 +1,8 @@ -error: error reading Clippy's configuration file `$DIR/clippy.toml`: duplicate field `cognitive_complexity_threshold` (provided as `cyclomatic_complexity_threshold`) +error: error reading Clippy's configuration file: duplicate key `cognitive-complexity-threshold` in document root + --> $DIR/clippy.toml:2:1 + | +LL | cognitive-complexity-threshold = 4 + | ^ -error: error reading Clippy's configuration file `$DIR/clippy.toml`: duplicate field `cognitive-complexity-threshold` - -warning: error reading Clippy's configuration file `$DIR/clippy.toml`: deprecated field `cyclomatic-complexity-threshold`. Please use `cognitive-complexity-threshold` instead - -error: aborting due to 2 previous errors; 1 warning emitted +error: aborting due to previous error diff --git a/tests/ui-toml/duplicated_keys_deprecated/clippy.toml b/tests/ui-toml/duplicated_keys_deprecated/clippy.toml new file mode 100644 index 00000000000..7932c43ebd2 --- /dev/null +++ b/tests/ui-toml/duplicated_keys_deprecated/clippy.toml @@ -0,0 +1,3 @@ +cognitive-complexity-threshold = 2 +# This is the deprecated name for the same key +cyclomatic-complexity-threshold = 3 diff --git a/tests/ui-toml/duplicated_keys_deprecated/duplicated_keys.rs b/tests/ui-toml/duplicated_keys_deprecated/duplicated_keys.rs new file mode 100644 index 00000000000..f328e4d9d04 --- /dev/null +++ b/tests/ui-toml/duplicated_keys_deprecated/duplicated_keys.rs @@ -0,0 +1 @@ +fn main() {} diff --git a/tests/ui-toml/duplicated_keys_deprecated/duplicated_keys.stderr b/tests/ui-toml/duplicated_keys_deprecated/duplicated_keys.stderr new file mode 100644 index 00000000000..2ae7848f183 --- /dev/null +++ b/tests/ui-toml/duplicated_keys_deprecated/duplicated_keys.stderr @@ -0,0 +1,14 @@ +error: error reading Clippy's configuration file: duplicate field `cognitive_complexity_threshold` (provided as `cyclomatic_complexity_threshold`) + --> $DIR/clippy.toml:3:1 + | +LL | cyclomatic-complexity-threshold = 3 + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +warning: error reading Clippy's configuration file: deprecated field `cyclomatic-complexity-threshold`. Please use `cognitive-complexity-threshold` instead + --> $DIR/clippy.toml:3:1 + | +LL | cyclomatic-complexity-threshold = 3 + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to previous error; 1 warning emitted + diff --git a/tests/ui-toml/duplicated_keys_deprecated_2/clippy.toml b/tests/ui-toml/duplicated_keys_deprecated_2/clippy.toml new file mode 100644 index 00000000000..53c634b727e --- /dev/null +++ b/tests/ui-toml/duplicated_keys_deprecated_2/clippy.toml @@ -0,0 +1,4 @@ +# This is the deprecated name for cognitive-complexity-threshold +cyclomatic-complexity-threshold = 3 +# Check we get duplication warning regardless of order +cognitive-complexity-threshold = 4 diff --git a/tests/ui-toml/duplicated_keys_deprecated_2/duplicated_keys.rs b/tests/ui-toml/duplicated_keys_deprecated_2/duplicated_keys.rs new file mode 100644 index 00000000000..f328e4d9d04 --- /dev/null +++ b/tests/ui-toml/duplicated_keys_deprecated_2/duplicated_keys.rs @@ -0,0 +1 @@ +fn main() {} diff --git a/tests/ui-toml/duplicated_keys_deprecated_2/duplicated_keys.stderr b/tests/ui-toml/duplicated_keys_deprecated_2/duplicated_keys.stderr new file mode 100644 index 00000000000..53ad4271246 --- /dev/null +++ b/tests/ui-toml/duplicated_keys_deprecated_2/duplicated_keys.stderr @@ -0,0 +1,14 @@ +error: error reading Clippy's configuration file: duplicate field `cognitive-complexity-threshold` + --> $DIR/clippy.toml:4:1 + | +LL | cognitive-complexity-threshold = 4 + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +warning: error reading Clippy's configuration file: deprecated field `cyclomatic-complexity-threshold`. Please use `cognitive-complexity-threshold` instead + --> $DIR/clippy.toml:2:1 + | +LL | cyclomatic-complexity-threshold = 3 + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to previous error; 1 warning emitted + diff --git a/tests/ui-toml/ifs_same_cond/ifs_same_cond.rs b/tests/ui-toml/ifs_same_cond/ifs_same_cond.rs index d623ac7e020..4882416c414 100644 --- a/tests/ui-toml/ifs_same_cond/ifs_same_cond.rs +++ b/tests/ui-toml/ifs_same_cond/ifs_same_cond.rs @@ -1,5 +1,5 @@ #![warn(clippy::ifs_same_cond)] -#![allow(clippy::if_same_then_else, clippy::comparison_chain)] +#![allow(clippy::if_same_then_else, clippy::comparison_chain, clippy::needless_else)] fn main() {} diff --git a/tests/ui-toml/toml_unknown_key/clippy.toml b/tests/ui-toml/toml_unknown_key/clippy.toml index 554b87cc50b..b77b4580051 100644 --- a/tests/ui-toml/toml_unknown_key/clippy.toml +++ b/tests/ui-toml/toml_unknown_key/clippy.toml @@ -1,6 +1,8 @@ # that one is an error foobar = 42 +# so is this one +barfoo = 53 -# that one is white-listed +# that one is ignored [third-party] clippy-feature = "nightly" 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 44710b09648..b6038f031f3 100644 --- a/tests/ui-toml/toml_unknown_key/conf_unknown_key.stderr +++ b/tests/ui-toml/toml_unknown_key/conf_unknown_key.stderr @@ -1,4 +1,4 @@ -error: error reading Clippy's configuration file `$DIR/clippy.toml`: unknown field `foobar`, expected one of +error: error reading Clippy's configuration file: unknown field `foobar`, expected one of allow-dbg-in-tests allow-expect-in-tests allow-mixed-uninlined-format-args @@ -54,7 +54,71 @@ error: error reading Clippy's configuration file `$DIR/clippy.toml`: unknown fie vec-box-size-threshold verbose-bit-mask-threshold warn-on-all-wildcard-imports - at line 5 column 1 + --> $DIR/clippy.toml:2:1 + | +LL | foobar = 42 + | ^^^^^^ -error: aborting due to previous error +error: error reading Clippy's configuration file: unknown field `barfoo`, expected one of + allow-dbg-in-tests + allow-expect-in-tests + allow-mixed-uninlined-format-args + allow-print-in-tests + allow-unwrap-in-tests + allowed-scripts + arithmetic-side-effects-allowed + arithmetic-side-effects-allowed-binary + arithmetic-side-effects-allowed-unary + array-size-threshold + avoid-breaking-exported-api + await-holding-invalid-types + blacklisted-names + cargo-ignore-publish + cognitive-complexity-threshold + cyclomatic-complexity-threshold + disallowed-macros + disallowed-methods + disallowed-names + disallowed-types + doc-valid-idents + enable-raw-pointer-heuristic-for-send + enforced-import-renames + enum-variant-name-threshold + enum-variant-size-threshold + future-size-threshold + ignore-interior-mutability + large-error-threshold + literal-representation-threshold + matches-for-let-else + max-fn-params-bools + max-include-file-size + max-struct-bools + max-suggested-slice-pattern-length + max-trait-bounds + missing-docs-in-crate-items + msrv + pass-by-value-size-limit + semicolon-inside-block-ignore-singleline + semicolon-outside-block-ignore-multiline + single-char-binding-names-threshold + standard-macro-braces + suppress-restriction-lint-in-const + third-party + too-large-for-stack + too-many-arguments-threshold + 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 + verbose-bit-mask-threshold + warn-on-all-wildcard-imports + --> $DIR/clippy.toml:4:1 + | +LL | barfoo = 53 + | ^^^^^^ + +error: aborting due to 2 previous errors diff --git a/tests/ui/auxiliary/wildcard_imports_helper.rs b/tests/ui/auxiliary/wildcard_imports_helper.rs index d75cdd625f9..44f49c080cd 100644 --- a/tests/ui/auxiliary/wildcard_imports_helper.rs +++ b/tests/ui/auxiliary/wildcard_imports_helper.rs @@ -25,3 +25,9 @@ pub mod prelude { pub struct PreludeModAnywhere; } } + +pub mod extern_prelude { + pub mod v1 { + pub struct ExternPreludeModAnywhere; + } +} diff --git a/tests/ui/branches_sharing_code/valid_if_blocks.rs b/tests/ui/branches_sharing_code/valid_if_blocks.rs index 2d6055eb6c4..5780ea08937 100644 --- a/tests/ui/branches_sharing_code/valid_if_blocks.rs +++ b/tests/ui/branches_sharing_code/valid_if_blocks.rs @@ -1,6 +1,10 @@ #![deny(clippy::branches_sharing_code, clippy::if_same_then_else)] #![allow(dead_code)] -#![allow(clippy::mixed_read_write_in_expression, clippy::uninlined_format_args)] +#![allow( + clippy::mixed_read_write_in_expression, + clippy::uninlined_format_args, + clippy::needless_else +)] // This tests valid if blocks that shouldn't trigger the lint diff --git a/tests/ui/branches_sharing_code/valid_if_blocks.stderr b/tests/ui/branches_sharing_code/valid_if_blocks.stderr index ce7fff0122f..a7e72b780af 100644 --- a/tests/ui/branches_sharing_code/valid_if_blocks.stderr +++ b/tests/ui/branches_sharing_code/valid_if_blocks.stderr @@ -1,5 +1,5 @@ error: this `if` has identical blocks - --> $DIR/valid_if_blocks.rs:105:14 + --> $DIR/valid_if_blocks.rs:109:14 | LL | if false { | ______________^ @@ -7,7 +7,7 @@ LL | | } else { | |_____^ | note: same as this - --> $DIR/valid_if_blocks.rs:106:12 + --> $DIR/valid_if_blocks.rs:110:12 | LL | } else { | ____________^ @@ -20,7 +20,7 @@ LL | #![deny(clippy::branches_sharing_code, clippy::if_same_then_else)] | ^^^^^^^^^^^^^^^^^^^^^^^^^ error: this `if` has identical blocks - --> $DIR/valid_if_blocks.rs:116:15 + --> $DIR/valid_if_blocks.rs:120:15 | LL | if x == 0 { | _______________^ @@ -31,7 +31,7 @@ LL | | } else { | |_____^ | note: same as this - --> $DIR/valid_if_blocks.rs:120:12 + --> $DIR/valid_if_blocks.rs:124:12 | LL | } else { | ____________^ @@ -42,19 +42,19 @@ LL | | } | |_____^ error: this `if` has identical blocks - --> $DIR/valid_if_blocks.rs:127:23 + --> $DIR/valid_if_blocks.rs:131:23 | LL | let _ = if x == 6 { 7 } else { 7 }; | ^^^^^ | note: same as this - --> $DIR/valid_if_blocks.rs:127:34 + --> $DIR/valid_if_blocks.rs:131:34 | LL | let _ = if x == 6 { 7 } else { 7 }; | ^^^^^ error: this `if` has identical blocks - --> $DIR/valid_if_blocks.rs:133:23 + --> $DIR/valid_if_blocks.rs:137:23 | LL | } else if x == 68 { | _______________________^ @@ -66,7 +66,7 @@ LL | | } else { | |_____^ | note: same as this - --> $DIR/valid_if_blocks.rs:138:12 + --> $DIR/valid_if_blocks.rs:142:12 | LL | } else { | ____________^ @@ -78,7 +78,7 @@ LL | | }; | |_____^ error: this `if` has identical blocks - --> $DIR/valid_if_blocks.rs:147:23 + --> $DIR/valid_if_blocks.rs:151:23 | LL | } else if x == 68 { | _______________________^ @@ -88,7 +88,7 @@ LL | | } else { | |_____^ | note: same as this - --> $DIR/valid_if_blocks.rs:150:12 + --> $DIR/valid_if_blocks.rs:154:12 | LL | } else { | ____________^ diff --git a/tests/ui/crashes/ice-7410.rs b/tests/ui/crashes/ice-7410.rs index ffe20ab1c31..a5373cdcae1 100644 --- a/tests/ui/crashes/ice-7410.rs +++ b/tests/ui/crashes/ice-7410.rs @@ -6,6 +6,7 @@ #![no_std] #![allow(clippy::if_same_then_else)] #![allow(clippy::redundant_pattern_matching)] +#![allow(clippy::needless_else)] use core::panic::PanicInfo; diff --git a/tests/ui/default_constructed_unit_structs.fixed b/tests/ui/default_constructed_unit_structs.fixed index e1012f38bba..ac5fe38ff44 100644 --- a/tests/ui/default_constructed_unit_structs.fixed +++ b/tests/ui/default_constructed_unit_structs.fixed @@ -101,6 +101,28 @@ struct EmptyStruct {} #[non_exhaustive] struct NonExhaustiveStruct; +mod issue_10755 { + struct Sqlite {} + + trait HasArguments<'q> { + type Arguments; + } + + impl<'q> HasArguments<'q> for Sqlite { + type Arguments = std::marker::PhantomData<&'q ()>; + } + + type SqliteArguments<'q> = >::Arguments; + + fn foo() { + // should not lint + // type alias cannot be used as a constructor + let _ = ::Arguments::default(); + + let _ = SqliteArguments::default(); + } +} + fn main() { // should lint let _ = PhantomData::; diff --git a/tests/ui/default_constructed_unit_structs.rs b/tests/ui/default_constructed_unit_structs.rs index c7b4313dbf0..de7f14ffbd9 100644 --- a/tests/ui/default_constructed_unit_structs.rs +++ b/tests/ui/default_constructed_unit_structs.rs @@ -101,6 +101,28 @@ struct EmptyStruct {} #[non_exhaustive] struct NonExhaustiveStruct; +mod issue_10755 { + struct Sqlite {} + + trait HasArguments<'q> { + type Arguments; + } + + impl<'q> HasArguments<'q> for Sqlite { + type Arguments = std::marker::PhantomData<&'q ()>; + } + + type SqliteArguments<'q> = >::Arguments; + + fn foo() { + // should not lint + // type alias cannot be used as a constructor + let _ = ::Arguments::default(); + + let _ = SqliteArguments::default(); + } +} + fn main() { // should lint let _ = PhantomData::::default(); diff --git a/tests/ui/default_constructed_unit_structs.stderr b/tests/ui/default_constructed_unit_structs.stderr index 61a32fb10e5..13abb9149da 100644 --- a/tests/ui/default_constructed_unit_structs.stderr +++ b/tests/ui/default_constructed_unit_structs.stderr @@ -13,25 +13,25 @@ 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:106:33 + --> $DIR/default_constructed_unit_structs.rs:128: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:107:42 + --> $DIR/default_constructed_unit_structs.rs:129: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:108:55 + --> $DIR/default_constructed_unit_structs.rs:130:55 | LL | let _: PhantomData = std::marker::PhantomData::default(); | ^^^^^^^^^^^ help: remove this call to `default` error: use of `default` to create a unit struct - --> $DIR/default_constructed_unit_structs.rs:109:23 + --> $DIR/default_constructed_unit_structs.rs:131:23 | LL | let _ = UnitStruct::default(); | ^^^^^^^^^^^ help: remove this call to `default` diff --git a/tests/ui/ifs_same_cond.rs b/tests/ui/ifs_same_cond.rs index 9ce9a87626a..f62da157d1b 100644 --- a/tests/ui/ifs_same_cond.rs +++ b/tests/ui/ifs_same_cond.rs @@ -1,5 +1,5 @@ #![warn(clippy::ifs_same_cond)] -#![allow(clippy::if_same_then_else, clippy::comparison_chain)] // all empty blocks +#![allow(clippy::if_same_then_else, clippy::comparison_chain, clippy::needless_else)] // all empty blocks fn ifs_same_cond() { let a = 0; diff --git a/tests/ui/large_stack_arrays.rs b/tests/ui/large_stack_arrays.rs index 99787ffd3d3..3e9d5e6a4ca 100644 --- a/tests/ui/large_stack_arrays.rs +++ b/tests/ui/large_stack_arrays.rs @@ -18,6 +18,19 @@ pub static DOESNOTLINT2: [u8; 512_001] = { [x; 512_001] }; +fn issue_10741() { + #[derive(Copy, Clone)] + struct Large([u32; 100_000]); + + fn build() -> Large { + Large([0; 100_000]) + } + + let _x = [build(); 3]; + + let _y = [build(), build(), build()]; +} + fn main() { let bad = ( [0u32; 20_000_000], diff --git a/tests/ui/large_stack_arrays.stderr b/tests/ui/large_stack_arrays.stderr index 24e90094982..118d39566ab 100644 --- a/tests/ui/large_stack_arrays.stderr +++ b/tests/ui/large_stack_arrays.stderr @@ -1,14 +1,30 @@ error: allocating a local array larger than 512000 bytes - --> $DIR/large_stack_arrays.rs:23:9 + --> $DIR/large_stack_arrays.rs:29:14 + | +LL | let _x = [build(); 3]; + | ^^^^^^^^^^^^ + | + = help: consider allocating on the heap with `vec![build(); 3].into_boxed_slice()` + = note: `-D clippy::large-stack-arrays` implied by `-D warnings` + +error: allocating a local array larger than 512000 bytes + --> $DIR/large_stack_arrays.rs:31:14 + | +LL | let _y = [build(), build(), build()]; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: consider allocating on the heap with `vec![build(), build(), build()].into_boxed_slice()` + +error: allocating a local array larger than 512000 bytes + --> $DIR/large_stack_arrays.rs:36:9 | LL | [0u32; 20_000_000], | ^^^^^^^^^^^^^^^^^^ | = help: consider allocating on the heap with `vec![0u32; 20_000_000].into_boxed_slice()` - = note: `-D clippy::large-stack-arrays` implied by `-D warnings` error: allocating a local array larger than 512000 bytes - --> $DIR/large_stack_arrays.rs:24:9 + --> $DIR/large_stack_arrays.rs:37:9 | LL | [S { data: [0; 32] }; 5000], | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -16,7 +32,7 @@ LL | [S { data: [0; 32] }; 5000], = help: consider allocating on the heap with `vec![S { data: [0; 32] }; 5000].into_boxed_slice()` error: allocating a local array larger than 512000 bytes - --> $DIR/large_stack_arrays.rs:25:9 + --> $DIR/large_stack_arrays.rs:38:9 | LL | [Some(""); 20_000_000], | ^^^^^^^^^^^^^^^^^^^^^^ @@ -24,7 +40,7 @@ LL | [Some(""); 20_000_000], = help: consider allocating on the heap with `vec![Some(""); 20_000_000].into_boxed_slice()` error: allocating a local array larger than 512000 bytes - --> $DIR/large_stack_arrays.rs:26:9 + --> $DIR/large_stack_arrays.rs:39:9 | LL | [E::T(0); 5000], | ^^^^^^^^^^^^^^^ @@ -32,12 +48,12 @@ LL | [E::T(0); 5000], = help: consider allocating on the heap with `vec![E::T(0); 5000].into_boxed_slice()` error: allocating a local array larger than 512000 bytes - --> $DIR/large_stack_arrays.rs:27:9 + --> $DIR/large_stack_arrays.rs:40:9 | LL | [0u8; usize::MAX], | ^^^^^^^^^^^^^^^^^ | = help: consider allocating on the heap with `vec![0u8; usize::MAX].into_boxed_slice()` -error: aborting due to 5 previous errors +error: aborting due to 7 previous errors diff --git a/tests/ui/manual_let_else.rs b/tests/ui/manual_let_else.rs index 3996d775f55..351ea0e4f50 100644 --- a/tests/ui/manual_let_else.rs +++ b/tests/ui/manual_let_else.rs @@ -146,10 +146,20 @@ fn fire() { Variant::A(0, 0) } - // Should not be renamed let v = if let Variant::A(a, 0) = e() { a } else { return }; - // Should be renamed - let v = if let Variant::B(b) = e() { b } else { return }; + + // `mut v` is inserted into the pattern + let mut v = if let Variant::B(b) = e() { b } else { return }; + + // Nesting works + let nested = Ok(Some(e())); + let v = if let Ok(Some(Variant::B(b))) | Err(Some(Variant::A(b, _))) = nested { + b + } else { + return; + }; + // dot dot works + let v = if let Variant::A(.., a) = e() { a } else { return }; } fn not_fire() { diff --git a/tests/ui/manual_let_else.stderr b/tests/ui/manual_let_else.stderr index f6f56f7b00e..0e876797134 100644 --- a/tests/ui/manual_let_else.stderr +++ b/tests/ui/manual_let_else.stderr @@ -260,19 +260,42 @@ LL | create_binding_if_some!(w, g()); = note: this error originates in the macro `create_binding_if_some` (in Nightly builds, run with -Z macro-backtrace for more info) error: this could be rewritten as `let...else` - --> $DIR/manual_let_else.rs:150:5 + --> $DIR/manual_let_else.rs:149:5 | LL | let v = if let Variant::A(a, 0) = e() { a } else { return }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider writing: `let Variant::A(a, 0) = e() else { return };` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider writing: `let Variant::A(v, 0) = e() else { return };` error: this could be rewritten as `let...else` --> $DIR/manual_let_else.rs:152:5 | -LL | let v = if let Variant::B(b) = e() { b } else { return }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider writing: `let Variant::B(v) = e() else { return };` +LL | let mut v = if let Variant::B(b) = e() { b } else { return }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider writing: `let Variant::B(mut v) = e() else { return };` error: this could be rewritten as `let...else` - --> $DIR/manual_let_else.rs:262:5 + --> $DIR/manual_let_else.rs:156:5 + | +LL | / let v = if let Ok(Some(Variant::B(b))) | Err(Some(Variant::A(b, _))) = nested { +LL | | b +LL | | } else { +LL | | return; +LL | | }; + | |______^ + | +help: consider writing + | +LL ~ let (Ok(Some(Variant::B(v))) | Err(Some(Variant::A(v, _)))) = nested else { +LL + return; +LL + }; + | + +error: this could be rewritten as `let...else` + --> $DIR/manual_let_else.rs:162:5 + | +LL | let v = if let Variant::A(.., a) = e() { a } else { return }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider writing: `let Variant::A(.., v) = e() else { return };` + +error: this could be rewritten as `let...else` + --> $DIR/manual_let_else.rs:272:5 | LL | / let _ = match ff { LL | | Some(value) => value, @@ -280,5 +303,5 @@ LL | | _ => macro_call!(), LL | | }; | |______^ help: consider writing: `let Some(_) = ff else { macro_call!() };` -error: aborting due to 20 previous errors +error: aborting due to 22 previous errors diff --git a/tests/ui/manual_let_else_match.rs b/tests/ui/manual_let_else_match.rs index 73b74679125..dfca3b023cd 100644 --- a/tests/ui/manual_let_else_match.rs +++ b/tests/ui/manual_let_else_match.rs @@ -68,7 +68,7 @@ fn fire() { let f = Variant::Bar(1); let _value = match f { - Variant::Bar(_) | Variant::Baz(_) => (), + Variant::Bar(v) | Variant::Baz(v) => v, _ => return, }; diff --git a/tests/ui/manual_let_else_match.stderr b/tests/ui/manual_let_else_match.stderr index bacc14dc967..13ed35bc1d5 100644 --- a/tests/ui/manual_let_else_match.stderr +++ b/tests/ui/manual_let_else_match.stderr @@ -58,10 +58,10 @@ error: this could be rewritten as `let...else` --> $DIR/manual_let_else_match.rs:70:5 | LL | / let _value = match f { -LL | | Variant::Bar(_) | Variant::Baz(_) => (), +LL | | Variant::Bar(v) | Variant::Baz(v) => v, LL | | _ => return, LL | | }; - | |______^ help: consider writing: `let (Variant::Bar(_) | Variant::Baz(_)) = f else { return };` + | |______^ help: consider writing: `let (Variant::Bar(_value) | Variant::Baz(_value)) = f else { return };` error: this could be rewritten as `let...else` --> $DIR/manual_let_else_match.rs:76:5 diff --git a/tests/ui/match_wild_err_arm.rs b/tests/ui/match_wild_err_arm.rs index 823be65efe0..5a552e4ae51 100644 --- a/tests/ui/match_wild_err_arm.rs +++ b/tests/ui/match_wild_err_arm.rs @@ -1,7 +1,20 @@ #![feature(exclusive_range_pattern)] -#![allow(clippy::match_same_arms)] +#![allow(clippy::match_same_arms, dead_code)] #![warn(clippy::match_wild_err_arm)] +fn issue_10635() { + enum Error { + A, + B, + } + + // Don't trigger in const contexts. Const unwrap is not yet stable + const X: () = match Ok::<_, Error>(()) { + Ok(x) => x, + Err(_) => panic!(), + }; +} + fn match_wild_err_arm() { let x: Result = Ok(3); diff --git a/tests/ui/match_wild_err_arm.stderr b/tests/ui/match_wild_err_arm.stderr index b016d682698..a9f54feacdb 100644 --- a/tests/ui/match_wild_err_arm.stderr +++ b/tests/ui/match_wild_err_arm.stderr @@ -1,5 +1,5 @@ error: `Err(_)` matches all errors - --> $DIR/match_wild_err_arm.rs:11:9 + --> $DIR/match_wild_err_arm.rs:24:9 | LL | Err(_) => panic!("err"), | ^^^^^^ @@ -8,7 +8,7 @@ LL | Err(_) => panic!("err"), = note: `-D clippy::match-wild-err-arm` implied by `-D warnings` error: `Err(_)` matches all errors - --> $DIR/match_wild_err_arm.rs:17:9 + --> $DIR/match_wild_err_arm.rs:30:9 | LL | Err(_) => panic!(), | ^^^^^^ @@ -16,7 +16,7 @@ LL | Err(_) => panic!(), = note: match each error separately or use the error output, or use `.expect(msg)` if the error case is unreachable error: `Err(_)` matches all errors - --> $DIR/match_wild_err_arm.rs:23:9 + --> $DIR/match_wild_err_arm.rs:36:9 | LL | Err(_) => { | ^^^^^^ @@ -24,7 +24,7 @@ LL | Err(_) => { = note: match each error separately or use the error output, or use `.expect(msg)` if the error case is unreachable error: `Err(_e)` matches all errors - --> $DIR/match_wild_err_arm.rs:31:9 + --> $DIR/match_wild_err_arm.rs:44:9 | LL | Err(_e) => panic!(), | ^^^^^^^ diff --git a/tests/ui/missing_fields_in_debug.rs b/tests/ui/missing_fields_in_debug.rs new file mode 100644 index 00000000000..c156d394ece --- /dev/null +++ b/tests/ui/missing_fields_in_debug.rs @@ -0,0 +1,191 @@ +#![allow(unused)] +#![warn(clippy::missing_fields_in_debug)] + +use std::fmt; +use std::marker::PhantomData; +use std::ops::Deref; + +struct NamedStruct1Ignored { + data: u8, + hidden: u32, +} + +impl fmt::Debug for NamedStruct1Ignored { + // unused field: hidden + fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result { + formatter + .debug_struct("NamedStruct1Ignored") + .field("data", &self.data) + .finish() + } +} + +struct NamedStructMultipleIgnored { + data: u8, + hidden: u32, + hidden2: String, + hidden3: Vec>, + hidden4: ((((u8), u16), u32), u64), +} + +impl fmt::Debug for NamedStructMultipleIgnored { + // unused fields: hidden, hidden2, hidden4 + fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result { + formatter + .debug_struct("NamedStructMultipleIgnored") + .field("data", &self.data) + .field("hidden3", &self.hidden3) + .finish() + } +} + +struct Unit; + +// ok +impl fmt::Debug for Unit { + fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result { + formatter.debug_struct("Unit").finish() + } +} + +struct UnnamedStruct1Ignored(String); + +impl fmt::Debug for UnnamedStruct1Ignored { + fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result { + formatter.debug_tuple("UnnamedStruct1Ignored").finish() + } +} + +struct UnnamedStructMultipleIgnored(String, Vec, i32); + +// tuple structs are not linted +impl fmt::Debug for UnnamedStructMultipleIgnored { + fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result { + formatter + .debug_tuple("UnnamedStructMultipleIgnored") + .field(&self.1) + .finish() + } +} + +struct NamedStructNonExhaustive { + a: u8, + b: String, +} + +// ok +impl fmt::Debug for NamedStructNonExhaustive { + fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result { + formatter + .debug_struct("NamedStructNonExhaustive") + .field("a", &self.a) + .finish_non_exhaustive() // should not warn here + } +} + +struct MultiExprDebugImpl { + a: u8, + b: String, +} + +// ok +impl fmt::Debug for MultiExprDebugImpl { + fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result { + let mut f = formatter.debug_struct("MultiExprDebugImpl"); + f.field("a", &self.a); + f.finish() + } +} + +#[derive(Debug)] +struct DerivedStruct { + a: u8, + b: i32, +} + +// https://github.com/rust-lang/rust-clippy/pull/10616#discussion_r1166846953 + +struct Inner { + a: usize, + b: usize, +} + +struct HasInner { + inner: Inner, +} + +impl HasInner { + fn get(&self) -> &Inner { + &self.inner + } +} + +impl fmt::Debug for HasInner { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + let inner = self.get(); + + f.debug_struct("HasInner") + .field("a", &inner.a) + .field("b", &inner.b) + .finish() + } +} + +// https://github.com/rust-lang/rust-clippy/pull/10616#discussion_r1170306053 +struct Foo { + a: u8, + b: u8, +} + +impl fmt::Debug for Foo { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("Foo").field("a", &self.a).field("b", &()).finish() + } +} + +// https://github.com/rust-lang/rust-clippy/pull/10616#discussion_r1175473620 +mod comment1175473620 { + use super::*; + + struct Inner { + a: usize, + b: usize, + } + struct Wrapper(Inner); + + impl Deref for Wrapper { + type Target = Inner; + + fn deref(&self) -> &Self::Target { + &self.0 + } + } + + impl fmt::Debug for Wrapper { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("Wrapper") + .field("a", &self.a) + .field("b", &self.b) + .finish() + } + } +} + +// https://github.com/rust-lang/rust-clippy/pull/10616#discussion_r1175488757 +// PhantomData is an exception and does not need to be included +struct WithPD { + a: u8, + b: u8, + c: PhantomData, +} + +impl fmt::Debug for WithPD { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("WithPD") + .field("a", &self.a) + .field("b", &self.b) + .finish() + } +} + +fn main() {} diff --git a/tests/ui/missing_fields_in_debug.stderr b/tests/ui/missing_fields_in_debug.stderr new file mode 100644 index 00000000000..ef9d02abab7 --- /dev/null +++ b/tests/ui/missing_fields_in_debug.stderr @@ -0,0 +1,73 @@ +error: manual `Debug` impl does not include all fields + --> $DIR/missing_fields_in_debug.rs:13:1 + | +LL | / impl fmt::Debug for NamedStruct1Ignored { +LL | | // unused field: hidden +LL | | fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result { +LL | | formatter +... | +LL | | } +LL | | } + | |_^ + | +note: this field is unused + --> $DIR/missing_fields_in_debug.rs:10:5 + | +LL | hidden: u32, + | ^^^^^^^^^^^ + = help: consider including all fields in this `Debug` impl + = help: consider calling `.finish_non_exhaustive()` if you intend to ignore fields + = note: `-D clippy::missing-fields-in-debug` implied by `-D warnings` + +error: manual `Debug` impl does not include all fields + --> $DIR/missing_fields_in_debug.rs:31:1 + | +LL | / impl fmt::Debug for NamedStructMultipleIgnored { +LL | | // unused fields: hidden, hidden2, hidden4 +LL | | fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result { +LL | | formatter +... | +LL | | } +LL | | } + | |_^ + | +note: this field is unused + --> $DIR/missing_fields_in_debug.rs:25:5 + | +LL | hidden: u32, + | ^^^^^^^^^^^ +note: this field is unused + --> $DIR/missing_fields_in_debug.rs:26:5 + | +LL | hidden2: String, + | ^^^^^^^^^^^^^^^ +note: this field is unused + --> $DIR/missing_fields_in_debug.rs:28:5 + | +LL | hidden4: ((((u8), u16), u32), u64), + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + = help: consider including all fields in this `Debug` impl + = help: consider calling `.finish_non_exhaustive()` if you intend to ignore fields + +error: manual `Debug` impl does not include all fields + --> $DIR/missing_fields_in_debug.rs:92:1 + | +LL | / impl fmt::Debug for MultiExprDebugImpl { +LL | | fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result { +LL | | let mut f = formatter.debug_struct("MultiExprDebugImpl"); +LL | | f.field("a", &self.a); +LL | | f.finish() +LL | | } +LL | | } + | |_^ + | +note: this field is unused + --> $DIR/missing_fields_in_debug.rs:88:5 + | +LL | b: String, + | ^^^^^^^^^ + = help: consider including all fields in this `Debug` impl + = help: consider calling `.finish_non_exhaustive()` if you intend to ignore fields + +error: aborting due to 3 previous errors + diff --git a/tests/ui/needless_else.fixed b/tests/ui/needless_else.fixed new file mode 100644 index 00000000000..06a16162790 --- /dev/null +++ b/tests/ui/needless_else.fixed @@ -0,0 +1,57 @@ +//@run-rustfix +#![allow(unused)] +#![warn(clippy::needless_else)] +#![allow(clippy::suspicious_else_formatting)] + +macro_rules! mac { + ($test:expr) => { + if $test { + println!("Test successful!"); + } else { + } + }; +} + +macro_rules! empty_expansion { + () => {}; +} + +fn main() { + let b = std::hint::black_box(true); + + if b { + println!("Foobar"); + } + + if b { + println!("Foobar"); + } else { + // Do not lint because this comment might be important + } + + if b { + println!("Foobar"); + } else + /* Do not lint because this comment might be important */ + { + } + + // Do not lint because of the expression + let _ = if b { 1 } else { 2 }; + + // Do not lint because inside a macro + mac!(b); + + if b { + println!("Foobar"); + } else { + #[cfg(foo)] + "Do not lint cfg'd out code" + } + + if b { + println!("Foobar"); + } else { + empty_expansion!(); + } +} diff --git a/tests/ui/needless_else.rs b/tests/ui/needless_else.rs new file mode 100644 index 00000000000..728032c47a6 --- /dev/null +++ b/tests/ui/needless_else.rs @@ -0,0 +1,58 @@ +//@run-rustfix +#![allow(unused)] +#![warn(clippy::needless_else)] +#![allow(clippy::suspicious_else_formatting)] + +macro_rules! mac { + ($test:expr) => { + if $test { + println!("Test successful!"); + } else { + } + }; +} + +macro_rules! empty_expansion { + () => {}; +} + +fn main() { + let b = std::hint::black_box(true); + + if b { + println!("Foobar"); + } else { + } + + if b { + println!("Foobar"); + } else { + // Do not lint because this comment might be important + } + + if b { + println!("Foobar"); + } else + /* Do not lint because this comment might be important */ + { + } + + // Do not lint because of the expression + let _ = if b { 1 } else { 2 }; + + // Do not lint because inside a macro + mac!(b); + + if b { + println!("Foobar"); + } else { + #[cfg(foo)] + "Do not lint cfg'd out code" + } + + if b { + println!("Foobar"); + } else { + empty_expansion!(); + } +} diff --git a/tests/ui/needless_else.stderr b/tests/ui/needless_else.stderr new file mode 100644 index 00000000000..ea693085164 --- /dev/null +++ b/tests/ui/needless_else.stderr @@ -0,0 +1,12 @@ +error: this else branch is empty + --> $DIR/needless_else.rs:24:7 + | +LL | } else { + | _______^ +LL | | } + | |_____^ help: you can remove it + | + = note: `-D clippy::needless-else` implied by `-D warnings` + +error: aborting due to previous error + diff --git a/tests/ui/needless_return.fixed b/tests/ui/needless_return.fixed index d49ae5d8636..4dabf313963 100644 --- a/tests/ui/needless_return.fixed +++ b/tests/ui/needless_return.fixed @@ -7,7 +7,8 @@ clippy::if_same_then_else, clippy::single_match, clippy::needless_bool, - clippy::equatable_if_let + clippy::equatable_if_let, + clippy::needless_else )] #![warn(clippy::needless_return)] diff --git a/tests/ui/needless_return.rs b/tests/ui/needless_return.rs index 36763826174..542f562b314 100644 --- a/tests/ui/needless_return.rs +++ b/tests/ui/needless_return.rs @@ -7,7 +7,8 @@ clippy::if_same_then_else, clippy::single_match, clippy::needless_bool, - clippy::equatable_if_let + clippy::equatable_if_let, + clippy::needless_else )] #![warn(clippy::needless_return)] diff --git a/tests/ui/needless_return.stderr b/tests/ui/needless_return.stderr index 05f6038cd25..1d9d23d3008 100644 --- a/tests/ui/needless_return.stderr +++ b/tests/ui/needless_return.stderr @@ -1,390 +1,582 @@ error: unneeded `return` statement - --> $DIR/needless_return.rs:27:5 + --> $DIR/needless_return.rs:28:5 | LL | return true; | ^^^^^^^^^^^ | = note: `-D clippy::needless-return` implied by `-D warnings` - = help: remove `return` +help: remove `return` + | +LL - return true; +LL + true + | error: unneeded `return` statement - --> $DIR/needless_return.rs:31:5 + --> $DIR/needless_return.rs:32:5 | LL | return true; | ^^^^^^^^^^^ | - = help: remove `return` +help: remove `return` + | +LL - return true; +LL + true + | error: unneeded `return` statement - --> $DIR/needless_return.rs:36:5 + --> $DIR/needless_return.rs:37:5 | LL | return true;;; | ^^^^^^^^^^^ | - = help: remove `return` +help: remove `return` + | +LL - return true;;; +LL + true + | error: unneeded `return` statement - --> $DIR/needless_return.rs:41:5 + --> $DIR/needless_return.rs:42:5 | LL | return true;; ; ; | ^^^^^^^^^^^ | - = help: remove `return` +help: remove `return` + | +LL - return true;; ; ; +LL + true + | error: unneeded `return` statement - --> $DIR/needless_return.rs:46:9 + --> $DIR/needless_return.rs:47:9 | LL | return true; | ^^^^^^^^^^^ | - = help: remove `return` +help: remove `return` + | +LL - return true; +LL + true + | error: unneeded `return` statement - --> $DIR/needless_return.rs:48:9 + --> $DIR/needless_return.rs:49:9 | LL | return false; | ^^^^^^^^^^^^ | - = help: remove `return` +help: remove `return` + | +LL - return false; +LL + false + | error: unneeded `return` statement - --> $DIR/needless_return.rs:54:17 + --> $DIR/needless_return.rs:55:17 | LL | true => return false, | ^^^^^^^^^^^^ | - = help: remove `return` +help: remove `return` + | +LL | true => false, + | ~~~~~ error: unneeded `return` statement - --> $DIR/needless_return.rs:56:13 + --> $DIR/needless_return.rs:57:13 | LL | return true; | ^^^^^^^^^^^ | - = help: remove `return` +help: remove `return` + | +LL - return true; +LL + true + | error: unneeded `return` statement - --> $DIR/needless_return.rs:63:9 + --> $DIR/needless_return.rs:64:9 | LL | return true; | ^^^^^^^^^^^ | - = help: remove `return` +help: remove `return` + | +LL - return true; +LL + true + | error: unneeded `return` statement - --> $DIR/needless_return.rs:65:16 + --> $DIR/needless_return.rs:66:16 | LL | let _ = || return true; | ^^^^^^^^^^^ | - = help: remove `return` +help: remove `return` + | +LL | let _ = || true; + | ~~~~ error: unneeded `return` statement - --> $DIR/needless_return.rs:69:5 + --> $DIR/needless_return.rs:70:5 | LL | return the_answer!(); | ^^^^^^^^^^^^^^^^^^^^ | - = help: remove `return` +help: remove `return` + | +LL - return the_answer!(); +LL + the_answer!() + | error: unneeded `return` statement - --> $DIR/needless_return.rs:72:21 + --> $DIR/needless_return.rs:73:21 | LL | fn test_void_fun() { | _____________________^ LL | | return; | |__________^ | - = help: remove `return` +help: remove `return` + | +LL - fn test_void_fun() { +LL - return; +LL + fn test_void_fun() { + | error: unneeded `return` statement - --> $DIR/needless_return.rs:77:11 + --> $DIR/needless_return.rs:78:11 | LL | if b { | ___________^ LL | | return; | |______________^ | - = help: remove `return` +help: remove `return` + | +LL - if b { +LL - return; +LL + if b { + | error: unneeded `return` statement - --> $DIR/needless_return.rs:79:13 + --> $DIR/needless_return.rs:80:13 | LL | } else { | _____________^ LL | | return; | |______________^ | - = help: remove `return` +help: remove `return` + | +LL - } else { +LL - return; +LL + } else { + | error: unneeded `return` statement - --> $DIR/needless_return.rs:87:14 + --> $DIR/needless_return.rs:88:14 | LL | _ => return, | ^^^^^^ | - = help: replace `return` with a unit value +help: replace `return` with a unit value + | +LL | _ => (), + | ~~ error: unneeded `return` statement - --> $DIR/needless_return.rs:95:24 + --> $DIR/needless_return.rs:96:24 | LL | let _ = 42; | ________________________^ LL | | return; | |__________________^ | - = help: remove `return` +help: remove `return` + | +LL - let _ = 42; +LL - return; +LL + let _ = 42; + | error: unneeded `return` statement - --> $DIR/needless_return.rs:98:14 + --> $DIR/needless_return.rs:99:14 | LL | _ => return, | ^^^^^^ | - = help: replace `return` with a unit value +help: replace `return` with a unit value + | +LL | _ => (), + | ~~ error: unneeded `return` statement - --> $DIR/needless_return.rs:111:9 + --> $DIR/needless_return.rs:112:9 | LL | return String::from("test"); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ | - = help: remove `return` +help: remove `return` + | +LL - return String::from("test"); +LL + String::from("test") + | error: unneeded `return` statement - --> $DIR/needless_return.rs:113:9 + --> $DIR/needless_return.rs:114:9 | LL | return String::new(); | ^^^^^^^^^^^^^^^^^^^^ | - = help: remove `return` +help: remove `return` + | +LL - return String::new(); +LL + String::new() + | error: unneeded `return` statement - --> $DIR/needless_return.rs:135:32 + --> $DIR/needless_return.rs:136:32 | LL | bar.unwrap_or_else(|_| return) | ^^^^^^ | - = help: replace `return` with an empty block +help: replace `return` with an empty block + | +LL | bar.unwrap_or_else(|_| {}) + | ~~ error: unneeded `return` statement - --> $DIR/needless_return.rs:139:21 + --> $DIR/needless_return.rs:140:21 | LL | let _ = || { | _____________________^ LL | | return; | |__________________^ | - = help: remove `return` +help: remove `return` + | +LL - let _ = || { +LL - return; +LL + let _ = || { + | error: unneeded `return` statement - --> $DIR/needless_return.rs:142:20 + --> $DIR/needless_return.rs:143:20 | LL | let _ = || return; | ^^^^^^ | - = help: replace `return` with an empty block +help: replace `return` with an empty block + | +LL | let _ = || {}; + | ~~ error: unneeded `return` statement - --> $DIR/needless_return.rs:148:32 + --> $DIR/needless_return.rs:149:32 | LL | res.unwrap_or_else(|_| return Foo) | ^^^^^^^^^^ | - = help: remove `return` +help: remove `return` + | +LL | res.unwrap_or_else(|_| Foo) + | ~~~ error: unneeded `return` statement - --> $DIR/needless_return.rs:157:5 + --> $DIR/needless_return.rs:158:5 | LL | return true; | ^^^^^^^^^^^ | - = help: remove `return` +help: remove `return` + | +LL - return true; +LL + true + | error: unneeded `return` statement - --> $DIR/needless_return.rs:161:5 + --> $DIR/needless_return.rs:162:5 | LL | return true; | ^^^^^^^^^^^ | - = help: remove `return` +help: remove `return` + | +LL - return true; +LL + true + | error: unneeded `return` statement - --> $DIR/needless_return.rs:166:9 + --> $DIR/needless_return.rs:167:9 | LL | return true; | ^^^^^^^^^^^ | - = help: remove `return` +help: remove `return` + | +LL - return true; +LL + true + | error: unneeded `return` statement - --> $DIR/needless_return.rs:168:9 + --> $DIR/needless_return.rs:169:9 | LL | return false; | ^^^^^^^^^^^^ | - = help: remove `return` +help: remove `return` + | +LL - return false; +LL + false + | error: unneeded `return` statement - --> $DIR/needless_return.rs:174:17 + --> $DIR/needless_return.rs:175:17 | LL | true => return false, | ^^^^^^^^^^^^ | - = help: remove `return` +help: remove `return` + | +LL | true => false, + | ~~~~~ error: unneeded `return` statement - --> $DIR/needless_return.rs:176:13 + --> $DIR/needless_return.rs:177:13 | LL | return true; | ^^^^^^^^^^^ | - = help: remove `return` +help: remove `return` + | +LL - return true; +LL + true + | error: unneeded `return` statement - --> $DIR/needless_return.rs:183:9 + --> $DIR/needless_return.rs:184:9 | LL | return true; | ^^^^^^^^^^^ | - = help: remove `return` +help: remove `return` + | +LL - return true; +LL + true + | error: unneeded `return` statement - --> $DIR/needless_return.rs:185:16 + --> $DIR/needless_return.rs:186:16 | LL | let _ = || return true; | ^^^^^^^^^^^ | - = help: remove `return` +help: remove `return` + | +LL | let _ = || true; + | ~~~~ error: unneeded `return` statement - --> $DIR/needless_return.rs:189:5 + --> $DIR/needless_return.rs:190:5 | LL | return the_answer!(); | ^^^^^^^^^^^^^^^^^^^^ | - = help: remove `return` +help: remove `return` + | +LL - return the_answer!(); +LL + the_answer!() + | error: unneeded `return` statement - --> $DIR/needless_return.rs:192:33 + --> $DIR/needless_return.rs:193:33 | LL | async fn async_test_void_fun() { | _________________________________^ LL | | return; | |__________^ | - = help: remove `return` +help: remove `return` + | +LL - async fn async_test_void_fun() { +LL - return; +LL + async fn async_test_void_fun() { + | error: unneeded `return` statement - --> $DIR/needless_return.rs:197:11 + --> $DIR/needless_return.rs:198:11 | LL | if b { | ___________^ LL | | return; | |______________^ | - = help: remove `return` +help: remove `return` + | +LL - if b { +LL - return; +LL + if b { + | error: unneeded `return` statement - --> $DIR/needless_return.rs:199:13 + --> $DIR/needless_return.rs:200:13 | LL | } else { | _____________^ LL | | return; | |______________^ | - = help: remove `return` +help: remove `return` + | +LL - } else { +LL - return; +LL + } else { + | error: unneeded `return` statement - --> $DIR/needless_return.rs:207:14 + --> $DIR/needless_return.rs:208:14 | LL | _ => return, | ^^^^^^ | - = help: replace `return` with a unit value +help: replace `return` with a unit value + | +LL | _ => (), + | ~~ error: unneeded `return` statement - --> $DIR/needless_return.rs:220:9 + --> $DIR/needless_return.rs:221:9 | LL | return String::from("test"); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ | - = help: remove `return` +help: remove `return` + | +LL - return String::from("test"); +LL + String::from("test") + | error: unneeded `return` statement - --> $DIR/needless_return.rs:222:9 + --> $DIR/needless_return.rs:223:9 | LL | return String::new(); | ^^^^^^^^^^^^^^^^^^^^ | - = help: remove `return` +help: remove `return` + | +LL - return String::new(); +LL + String::new() + | error: unneeded `return` statement - --> $DIR/needless_return.rs:238:5 + --> $DIR/needless_return.rs:239:5 | LL | return format!("Hello {}", "world!"); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | - = help: remove `return` +help: remove `return` + | +LL - return format!("Hello {}", "world!"); +LL + format!("Hello {}", "world!") + | error: unneeded `return` statement - --> $DIR/needless_return.rs:250:9 + --> $DIR/needless_return.rs:251:9 | LL | return true; | ^^^^^^^^^^^ | - = help: remove `return` +help: remove `return` + | +LL ~ true +LL | } else { +LL | return false; +LL ~ } + | error: unneeded `return` statement - --> $DIR/needless_return.rs:252:9 + --> $DIR/needless_return.rs:253:9 | LL | return false; | ^^^^^^^^^^^^ | - = help: remove `return` +help: remove `return` + | +LL ~ false +LL ~ } + | error: unneeded `return` statement - --> $DIR/needless_return.rs:259:13 + --> $DIR/needless_return.rs:260:13 | LL | return 10; | ^^^^^^^^^ | - = help: remove `return` +help: remove `return` + | +LL ~ 10 +LL | }, + ... +LL | }, +LL ~ } + | error: unneeded `return` statement - --> $DIR/needless_return.rs:262:13 + --> $DIR/needless_return.rs:263:13 | LL | return 100; | ^^^^^^^^^^ | - = help: remove `return` +help: remove `return` + | +LL ~ 100 +LL | }, +LL ~ } + | error: unneeded `return` statement - --> $DIR/needless_return.rs:270:9 + --> $DIR/needless_return.rs:271:9 | LL | return 0; | ^^^^^^^^ | - = help: remove `return` +help: remove `return` + | +LL ~ 0 +LL ~ } + | error: unneeded `return` statement - --> $DIR/needless_return.rs:277:13 + --> $DIR/needless_return.rs:278:13 | LL | return *(x as *const isize); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ | - = help: remove `return` +help: remove `return` + | +LL ~ *(x as *const isize) +LL | } else { +LL | return !*(x as *const isize); +LL ~ } +LL ~ } + | error: unneeded `return` statement - --> $DIR/needless_return.rs:279:13 + --> $DIR/needless_return.rs:280:13 | LL | return !*(x as *const isize); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | - = help: remove `return` +help: remove `return` + | +LL ~ !*(x as *const isize) +LL ~ } +LL ~ } + | error: unneeded `return` statement - --> $DIR/needless_return.rs:286:20 + --> $DIR/needless_return.rs:287:20 | LL | let _ = 42; | ____________________^ @@ -392,47 +584,73 @@ LL | | LL | | return; | |______________^ | - = help: remove `return` +help: remove `return` + | +LL - let _ = 42; +LL - +LL - return; +LL + let _ = 42; + | error: unneeded `return` statement - --> $DIR/needless_return.rs:293:20 + --> $DIR/needless_return.rs:294:20 | LL | let _ = 42; return; | ^^^^^^^ | - = help: remove `return` +help: remove `return` + | +LL - let _ = 42; return; +LL + let _ = 42; + | error: unneeded `return` statement - --> $DIR/needless_return.rs:305:9 + --> $DIR/needless_return.rs:306:9 | LL | return Ok(format!("ok!")); | ^^^^^^^^^^^^^^^^^^^^^^^^^ | - = help: remove `return` +help: remove `return` + | +LL - return Ok(format!("ok!")); +LL + Ok(format!("ok!")) + | error: unneeded `return` statement - --> $DIR/needless_return.rs:307:9 + --> $DIR/needless_return.rs:308:9 | LL | return Err(format!("err!")); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ | - = help: remove `return` +help: remove `return` + | +LL - return Err(format!("err!")); +LL + Err(format!("err!")) + | error: unneeded `return` statement - --> $DIR/needless_return.rs:313:9 + --> $DIR/needless_return.rs:314:9 | LL | return if true { 1 } else { 2 }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | - = help: remove `return` +help: remove `return` + | +LL - return if true { 1 } else { 2 }; +LL + if true { 1 } else { 2 } + | error: unneeded `return` statement - --> $DIR/needless_return.rs:317:9 + --> $DIR/needless_return.rs:318:9 | LL | return if b1 { 0 } else { 1 } | if b2 { 2 } else { 3 } | if b3 { 4 } else { 5 }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | - = help: remove `return` and wrap the sequence with parentheses +help: remove `return` and wrap the sequence with parentheses + | +LL - return if b1 { 0 } else { 1 } | if b2 { 2 } else { 3 } | if b3 { 4 } else { 5 }; +LL + (if b1 { 0 } else { 1 } | if b2 { 2 } else { 3 } | if b3 { 4 } else { 5 }) + | error: aborting due to 52 previous errors diff --git a/tests/ui/nonminimal_bool.rs b/tests/ui/nonminimal_bool.rs index 80cc7c60f56..fec6b7713ee 100644 --- a/tests/ui/nonminimal_bool.rs +++ b/tests/ui/nonminimal_bool.rs @@ -110,3 +110,17 @@ fn issue_10435() { println!("{}", line!()); } } + +fn issue10836() { + struct Foo(bool); + impl std::ops::Not for Foo { + type Output = bool; + + fn not(self) -> Self::Output { + !self.0 + } + } + + // Should not lint + let _: bool = !!Foo(true); +} diff --git a/tests/ui/ptr_cast_constness.fixed b/tests/ui/ptr_cast_constness.fixed new file mode 100644 index 00000000000..24de573d083 --- /dev/null +++ b/tests/ui/ptr_cast_constness.fixed @@ -0,0 +1,55 @@ +//@run-rustfix +//@aux-build:proc_macros.rs + +#![warn(clippy::ptr_cast_constness)] + +extern crate proc_macros; +use proc_macros::{external, inline_macros}; + +#[inline_macros] +fn main() { + let ptr: *const u32 = &42_u32; + let mut_ptr: *mut u32 = &mut 42_u32; + + let _ = ptr as *const i32; + let _ = mut_ptr as *mut i32; + + // Make sure the lint can handle the difference in their operator precedences. + unsafe { + let ptr_ptr: *const *const u32 = &ptr; + let _ = (*ptr_ptr).cast_mut(); + } + + let _ = ptr.cast_mut(); + let _ = mut_ptr.cast_const(); + + // Lint this, since pointer::cast_mut and pointer::cast_const have ?Sized + let ptr_of_array: *const [u32; 4] = &[1, 2, 3, 4]; + let _ = ptr_of_array as *const [u32]; + let _ = ptr_of_array as *const dyn std::fmt::Debug; + + // Make sure the lint is triggered inside a macro + let _ = inline!($ptr as *const i32); + + // Do not lint inside macros from external crates + let _ = external!($ptr as *const i32); +} + +#[clippy::msrv = "1.64"] +fn _msrv_1_64() { + let ptr: *const u32 = &42_u32; + let mut_ptr: *mut u32 = &mut 42_u32; + + // `pointer::cast_const` and `pointer::cast_mut` were stabilized in 1.65. Do not lint this + let _ = ptr as *mut i32; + let _ = mut_ptr as *const i32; +} + +#[clippy::msrv = "1.65"] +fn _msrv_1_65() { + let ptr: *const u32 = &42_u32; + let mut_ptr: *mut u32 = &mut 42_u32; + + let _ = ptr.cast_mut(); + let _ = mut_ptr.cast_const(); +} diff --git a/tests/ui/ptr_cast_constness.rs b/tests/ui/ptr_cast_constness.rs new file mode 100644 index 00000000000..63d973a9fca --- /dev/null +++ b/tests/ui/ptr_cast_constness.rs @@ -0,0 +1,55 @@ +//@run-rustfix +//@aux-build:proc_macros.rs + +#![warn(clippy::ptr_cast_constness)] + +extern crate proc_macros; +use proc_macros::{external, inline_macros}; + +#[inline_macros] +fn main() { + let ptr: *const u32 = &42_u32; + let mut_ptr: *mut u32 = &mut 42_u32; + + let _ = ptr as *const i32; + let _ = mut_ptr as *mut i32; + + // Make sure the lint can handle the difference in their operator precedences. + unsafe { + let ptr_ptr: *const *const u32 = &ptr; + let _ = *ptr_ptr as *mut i32; + } + + let _ = ptr as *mut i32; + let _ = mut_ptr as *const i32; + + // Lint this, since pointer::cast_mut and pointer::cast_const have ?Sized + let ptr_of_array: *const [u32; 4] = &[1, 2, 3, 4]; + let _ = ptr_of_array as *const [u32]; + let _ = ptr_of_array as *const dyn std::fmt::Debug; + + // Make sure the lint is triggered inside a macro + let _ = inline!($ptr as *const i32); + + // Do not lint inside macros from external crates + let _ = external!($ptr as *const i32); +} + +#[clippy::msrv = "1.64"] +fn _msrv_1_64() { + let ptr: *const u32 = &42_u32; + let mut_ptr: *mut u32 = &mut 42_u32; + + // `pointer::cast_const` and `pointer::cast_mut` were stabilized in 1.65. Do not lint this + let _ = ptr as *mut i32; + let _ = mut_ptr as *const i32; +} + +#[clippy::msrv = "1.65"] +fn _msrv_1_65() { + let ptr: *const u32 = &42_u32; + let mut_ptr: *mut u32 = &mut 42_u32; + + let _ = ptr as *mut i32; + let _ = mut_ptr as *const i32; +} diff --git a/tests/ui/ptr_cast_constness.stderr b/tests/ui/ptr_cast_constness.stderr new file mode 100644 index 00000000000..43816c87c19 --- /dev/null +++ b/tests/ui/ptr_cast_constness.stderr @@ -0,0 +1,34 @@ +error: `as` casting between raw pointers while changing its constness + --> $DIR/ptr_cast_constness.rs:20:17 + | +LL | let _ = *ptr_ptr as *mut i32; + | ^^^^^^^^^^^^^^^^^^^^ help: try `pointer::cast_mut`, a safer alternative: `(*ptr_ptr).cast_mut()` + | + = note: `-D clippy::ptr-cast-constness` implied by `-D warnings` + +error: `as` casting between raw pointers while changing its constness + --> $DIR/ptr_cast_constness.rs:23:13 + | +LL | let _ = ptr as *mut i32; + | ^^^^^^^^^^^^^^^ help: try `pointer::cast_mut`, a safer alternative: `ptr.cast_mut()` + +error: `as` casting between raw pointers while changing its constness + --> $DIR/ptr_cast_constness.rs:24:13 + | +LL | let _ = mut_ptr as *const i32; + | ^^^^^^^^^^^^^^^^^^^^^ help: try `pointer::cast_const`, a safer alternative: `mut_ptr.cast_const()` + +error: `as` casting between raw pointers while changing its constness + --> $DIR/ptr_cast_constness.rs:53:13 + | +LL | let _ = ptr as *mut i32; + | ^^^^^^^^^^^^^^^ help: try `pointer::cast_mut`, a safer alternative: `ptr.cast_mut()` + +error: `as` casting between raw pointers while changing its constness + --> $DIR/ptr_cast_constness.rs:54:13 + | +LL | let _ = mut_ptr as *const i32; + | ^^^^^^^^^^^^^^^^^^^^^ help: try `pointer::cast_const`, a safer alternative: `mut_ptr.cast_const()` + +error: aborting due to 5 previous errors + diff --git a/tests/ui/redundant_pattern_matching_drop_order.fixed b/tests/ui/redundant_pattern_matching_drop_order.fixed index bebdf89716f..481c9b263fb 100644 --- a/tests/ui/redundant_pattern_matching_drop_order.fixed +++ b/tests/ui/redundant_pattern_matching_drop_order.fixed @@ -2,7 +2,7 @@ // Issue #5746 #![warn(clippy::redundant_pattern_matching)] -#![allow(clippy::if_same_then_else, clippy::equatable_if_let)] +#![allow(clippy::if_same_then_else, clippy::equatable_if_let, clippy::needless_else)] use std::task::Poll::{Pending, Ready}; fn main() { diff --git a/tests/ui/redundant_pattern_matching_drop_order.rs b/tests/ui/redundant_pattern_matching_drop_order.rs index 8fb6ed5f7ec..86e46d41e65 100644 --- a/tests/ui/redundant_pattern_matching_drop_order.rs +++ b/tests/ui/redundant_pattern_matching_drop_order.rs @@ -2,7 +2,7 @@ // Issue #5746 #![warn(clippy::redundant_pattern_matching)] -#![allow(clippy::if_same_then_else, clippy::equatable_if_let)] +#![allow(clippy::if_same_then_else, clippy::equatable_if_let, clippy::needless_else)] use std::task::Poll::{Pending, Ready}; fn main() { diff --git a/tests/ui/redundant_pattern_matching_option.fixed b/tests/ui/redundant_pattern_matching_option.fixed index accdf1da9dd..dae931541d4 100644 --- a/tests/ui/redundant_pattern_matching_option.fixed +++ b/tests/ui/redundant_pattern_matching_option.fixed @@ -47,6 +47,7 @@ fn main() { issue6067(); issue10726(); + issue10803(); let _ = if gen_opt().is_some() { 1 @@ -107,3 +108,14 @@ fn issue10726() { _ => false, }; } + +fn issue10803() { + let x = Some(42); + + let _ = x.is_some(); + + let _ = x.is_none(); + + // Don't lint + let _ = matches!(x, Some(16)); +} diff --git a/tests/ui/redundant_pattern_matching_option.rs b/tests/ui/redundant_pattern_matching_option.rs index ec684bdf71c..3f2fa3f53ce 100644 --- a/tests/ui/redundant_pattern_matching_option.rs +++ b/tests/ui/redundant_pattern_matching_option.rs @@ -56,6 +56,7 @@ fn main() { issue6067(); issue10726(); + issue10803(); let _ = if let Some(_) = gen_opt() { 1 @@ -134,3 +135,14 @@ fn issue10726() { _ => false, }; } + +fn issue10803() { + let x = Some(42); + + let _ = matches!(x, Some(_)); + + let _ = matches!(x, None); + + // Don't lint + let _ = matches!(x, Some(16)); +} diff --git a/tests/ui/redundant_pattern_matching_option.stderr b/tests/ui/redundant_pattern_matching_option.stderr index a69eb390520..93760ce97a8 100644 --- a/tests/ui/redundant_pattern_matching_option.stderr +++ b/tests/ui/redundant_pattern_matching_option.stderr @@ -77,49 +77,49 @@ LL | let _ = if let Some(_) = opt { true } else { false }; | -------^^^^^^^------ help: try this: `if opt.is_some()` error: redundant pattern matching, consider using `is_some()` - --> $DIR/redundant_pattern_matching_option.rs:60:20 + --> $DIR/redundant_pattern_matching_option.rs:61:20 | LL | let _ = if let Some(_) = gen_opt() { | -------^^^^^^^------------ help: try this: `if gen_opt().is_some()` error: redundant pattern matching, consider using `is_none()` - --> $DIR/redundant_pattern_matching_option.rs:62:19 + --> $DIR/redundant_pattern_matching_option.rs:63:19 | 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:68:12 + --> $DIR/redundant_pattern_matching_option.rs:69: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:83:12 + --> $DIR/redundant_pattern_matching_option.rs:84: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:85:12 + --> $DIR/redundant_pattern_matching_option.rs:86: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:87:15 + --> $DIR/redundant_pattern_matching_option.rs:88: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:89:15 + --> $DIR/redundant_pattern_matching_option.rs:90: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:91:5 + --> $DIR/redundant_pattern_matching_option.rs:92:5 | LL | / match Some(42) { LL | | Some(_) => true, @@ -128,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:96:5 + --> $DIR/redundant_pattern_matching_option.rs:97:5 | LL | / match None::<()> { LL | | Some(_) => false, @@ -137,19 +137,19 @@ LL | | }; | |_____^ help: try this: `None::<()>.is_none()` error: redundant pattern matching, consider using `is_none()` - --> $DIR/redundant_pattern_matching_option.rs:104:12 + --> $DIR/redundant_pattern_matching_option.rs:105: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:105:12 + --> $DIR/redundant_pattern_matching_option.rs:106: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:111:5 + --> $DIR/redundant_pattern_matching_option.rs:112:5 | LL | / match x { LL | | Some(_) => true, @@ -158,7 +158,7 @@ LL | | }; | |_____^ help: try this: `x.is_some()` error: redundant pattern matching, consider using `is_none()` - --> $DIR/redundant_pattern_matching_option.rs:116:5 + --> $DIR/redundant_pattern_matching_option.rs:117:5 | LL | / match x { LL | | None => true, @@ -167,7 +167,7 @@ LL | | }; | |_____^ help: try this: `x.is_none()` error: redundant pattern matching, consider using `is_none()` - --> $DIR/redundant_pattern_matching_option.rs:121:5 + --> $DIR/redundant_pattern_matching_option.rs:122:5 | LL | / match x { LL | | Some(_) => false, @@ -176,7 +176,7 @@ LL | | }; | |_____^ help: try this: `x.is_none()` error: redundant pattern matching, consider using `is_some()` - --> $DIR/redundant_pattern_matching_option.rs:126:5 + --> $DIR/redundant_pattern_matching_option.rs:127:5 | LL | / match x { LL | | None => false, @@ -184,5 +184,17 @@ LL | | _ => true, LL | | }; | |_____^ help: try this: `x.is_some()` -error: aborting due to 26 previous errors +error: redundant pattern matching, consider using `is_some()` + --> $DIR/redundant_pattern_matching_option.rs:142:13 + | +LL | let _ = matches!(x, Some(_)); + | ^^^^^^^^^^^^^^^^^^^^ help: try this: `x.is_some()` + +error: redundant pattern matching, consider using `is_none()` + --> $DIR/redundant_pattern_matching_option.rs:144:13 + | +LL | let _ = matches!(x, None); + | ^^^^^^^^^^^^^^^^^ help: try this: `x.is_none()` + +error: aborting due to 28 previous errors diff --git a/tests/ui/redundant_pattern_matching_result.fixed b/tests/ui/redundant_pattern_matching_result.fixed index e4032ae44b7..d77a2af7616 100644 --- a/tests/ui/redundant_pattern_matching_result.fixed +++ b/tests/ui/redundant_pattern_matching_result.fixed @@ -44,6 +44,7 @@ fn main() { issue6067(); issue6065(); issue10726(); + issue10803(); let _ = if gen_res().is_ok() { 1 @@ -133,3 +134,17 @@ fn issue10726() { _ => true, }; } + +fn issue10803() { + let x: Result = Ok(42); + + let _ = x.is_ok(); + + let _ = x.is_err(); + + // Don't lint + let _ = matches!(x, Ok(16)); + + // Don't lint + let _ = matches!(x, Err(16)); +} diff --git a/tests/ui/redundant_pattern_matching_result.rs b/tests/ui/redundant_pattern_matching_result.rs index 39eb10df878..aa884ac6bb1 100644 --- a/tests/ui/redundant_pattern_matching_result.rs +++ b/tests/ui/redundant_pattern_matching_result.rs @@ -56,6 +56,7 @@ fn main() { issue6067(); issue6065(); issue10726(); + issue10803(); let _ = if let Ok(_) = gen_res() { 1 @@ -163,3 +164,17 @@ fn issue10726() { _ => true, }; } + +fn issue10803() { + let x: Result = Ok(42); + + let _ = matches!(x, Ok(_)); + + let _ = matches!(x, Err(_)); + + // Don't lint + let _ = matches!(x, Ok(16)); + + // Don't lint + let _ = matches!(x, Err(16)); +} diff --git a/tests/ui/redundant_pattern_matching_result.stderr b/tests/ui/redundant_pattern_matching_result.stderr index 5893ae4dcc4..b462f7f41b9 100644 --- a/tests/ui/redundant_pattern_matching_result.stderr +++ b/tests/ui/redundant_pattern_matching_result.stderr @@ -73,67 +73,67 @@ LL | let _ = if let Ok(_) = Ok::(4) { true } else { false }; | -------^^^^^--------------------- help: try this: `if Ok::(4).is_ok()` error: redundant pattern matching, consider using `is_ok()` - --> $DIR/redundant_pattern_matching_result.rs:60:20 + --> $DIR/redundant_pattern_matching_result.rs:61:20 | LL | let _ = if let Ok(_) = gen_res() { | -------^^^^^------------ help: try this: `if gen_res().is_ok()` error: redundant pattern matching, consider using `is_err()` - --> $DIR/redundant_pattern_matching_result.rs:62:19 + --> $DIR/redundant_pattern_matching_result.rs:63:19 | LL | } else if let Err(_) = gen_res() { | -------^^^^^^------------ help: try this: `if gen_res().is_err()` error: redundant pattern matching, consider using `is_some()` - --> $DIR/redundant_pattern_matching_result.rs:85:19 + --> $DIR/redundant_pattern_matching_result.rs:86:19 | LL | while let Some(_) = r#try!(result_opt()) {} | ----------^^^^^^^----------------------- help: try this: `while r#try!(result_opt()).is_some()` error: redundant pattern matching, consider using `is_some()` - --> $DIR/redundant_pattern_matching_result.rs:86:16 + --> $DIR/redundant_pattern_matching_result.rs:87:16 | LL | if let Some(_) = r#try!(result_opt()) {} | -------^^^^^^^----------------------- help: try this: `if r#try!(result_opt()).is_some()` error: redundant pattern matching, consider using `is_some()` - --> $DIR/redundant_pattern_matching_result.rs:92:12 + --> $DIR/redundant_pattern_matching_result.rs:93:12 | LL | if let Some(_) = m!() {} | -------^^^^^^^------- help: try this: `if m!().is_some()` error: redundant pattern matching, consider using `is_some()` - --> $DIR/redundant_pattern_matching_result.rs:93:15 + --> $DIR/redundant_pattern_matching_result.rs:94:15 | LL | while let Some(_) = m!() {} | ----------^^^^^^^------- help: try this: `while m!().is_some()` error: redundant pattern matching, consider using `is_ok()` - --> $DIR/redundant_pattern_matching_result.rs:111:12 + --> $DIR/redundant_pattern_matching_result.rs:112:12 | LL | if let Ok(_) = Ok::(42) {} | -------^^^^^--------------------- help: try this: `if Ok::(42).is_ok()` error: redundant pattern matching, consider using `is_err()` - --> $DIR/redundant_pattern_matching_result.rs:113:12 + --> $DIR/redundant_pattern_matching_result.rs:114:12 | LL | if let Err(_) = Err::(42) {} | -------^^^^^^---------------------- help: try this: `if Err::(42).is_err()` error: redundant pattern matching, consider using `is_ok()` - --> $DIR/redundant_pattern_matching_result.rs:115:15 + --> $DIR/redundant_pattern_matching_result.rs:116:15 | LL | while let Ok(_) = Ok::(10) {} | ----------^^^^^--------------------- help: try this: `while Ok::(10).is_ok()` error: redundant pattern matching, consider using `is_err()` - --> $DIR/redundant_pattern_matching_result.rs:117:15 + --> $DIR/redundant_pattern_matching_result.rs:118:15 | LL | while let Err(_) = Ok::(10) {} | ----------^^^^^^--------------------- help: try this: `while Ok::(10).is_err()` error: redundant pattern matching, consider using `is_ok()` - --> $DIR/redundant_pattern_matching_result.rs:119:5 + --> $DIR/redundant_pattern_matching_result.rs:120:5 | LL | / match Ok::(42) { LL | | Ok(_) => true, @@ -142,7 +142,7 @@ LL | | }; | |_____^ help: try this: `Ok::(42).is_ok()` error: redundant pattern matching, consider using `is_err()` - --> $DIR/redundant_pattern_matching_result.rs:124:5 + --> $DIR/redundant_pattern_matching_result.rs:125:5 | LL | / match Err::(42) { LL | | Ok(_) => false, @@ -151,7 +151,7 @@ LL | | }; | |_____^ help: try this: `Err::(42).is_err()` error: redundant pattern matching, consider using `is_ok()` - --> $DIR/redundant_pattern_matching_result.rs:134:5 + --> $DIR/redundant_pattern_matching_result.rs:135:5 | LL | / match x { LL | | Ok(_) => true, @@ -160,7 +160,7 @@ LL | | }; | |_____^ help: try this: `x.is_ok()` error: redundant pattern matching, consider using `is_err()` - --> $DIR/redundant_pattern_matching_result.rs:139:5 + --> $DIR/redundant_pattern_matching_result.rs:140:5 | LL | / match x { LL | | Ok(_) => false, @@ -169,7 +169,7 @@ LL | | }; | |_____^ help: try this: `x.is_err()` error: redundant pattern matching, consider using `is_err()` - --> $DIR/redundant_pattern_matching_result.rs:144:5 + --> $DIR/redundant_pattern_matching_result.rs:145:5 | LL | / match x { LL | | Err(_) => true, @@ -178,7 +178,7 @@ LL | | }; | |_____^ help: try this: `x.is_err()` error: redundant pattern matching, consider using `is_ok()` - --> $DIR/redundant_pattern_matching_result.rs:149:5 + --> $DIR/redundant_pattern_matching_result.rs:150:5 | LL | / match x { LL | | Err(_) => false, @@ -186,5 +186,17 @@ LL | | _ => true, LL | | }; | |_____^ help: try this: `x.is_ok()` -error: aborting due to 26 previous errors +error: redundant pattern matching, consider using `is_ok()` + --> $DIR/redundant_pattern_matching_result.rs:171:13 + | +LL | let _ = matches!(x, Ok(_)); + | ^^^^^^^^^^^^^^^^^^ help: try this: `x.is_ok()` + +error: redundant pattern matching, consider using `is_err()` + --> $DIR/redundant_pattern_matching_result.rs:173:13 + | +LL | let _ = matches!(x, Err(_)); + | ^^^^^^^^^^^^^^^^^^^ help: try this: `x.is_err()` + +error: aborting due to 28 previous errors diff --git a/tests/ui/regex.rs b/tests/ui/regex.rs index a5f79b139bc..1c8e47ab594 100644 --- a/tests/ui/regex.rs +++ b/tests/ui/regex.rs @@ -42,6 +42,11 @@ fn syntax_error() { let escaped_string_span = Regex::new("\\b\\c"); let aux_span = Regex::new("(?ixi)"); + + let should_not_lint = Regex::new("(?u)."); + let should_not_lint = BRegex::new("(?u)."); + let invalid_utf8_should_not_lint = BRegex::new("(?-u)."); + let invalid_utf8_should_lint = Regex::new("(?-u)."); } fn trivial_regex() { @@ -71,6 +76,8 @@ fn trivial_regex() { // non-trivial regexes let non_trivial_dot = Regex::new("a.b"); let non_trivial_dot_builder = RegexBuilder::new("a.b"); + let non_trivial_dot = Regex::new("."); + let non_trivial_dot = BRegex::new("."); let non_trivial_eq = Regex::new("^foo|bar$"); let non_trivial_starts_with = Regex::new("^foo|bar"); let non_trivial_ends_with = Regex::new("^foo|bar"); diff --git a/tests/ui/regex.stderr b/tests/ui/regex.stderr index 6b8a772e7f0..1e8a21283cd 100644 --- a/tests/ui/regex.stderr +++ b/tests/ui/regex.stderr @@ -99,8 +99,14 @@ error: regex syntax error: duplicate flag LL | let aux_span = Regex::new("(?ixi)"); | ^ ^ +error: regex syntax error: pattern can match invalid UTF-8 + --> $DIR/regex.rs:49:53 + | +LL | let invalid_utf8_should_lint = Regex::new("(?-u)."); + | ^ + error: trivial regex - --> $DIR/regex.rs:48:33 + --> $DIR/regex.rs:53:33 | LL | let trivial_eq = Regex::new("^foobar$"); | ^^^^^^^^^^ @@ -108,7 +114,7 @@ LL | let trivial_eq = Regex::new("^foobar$"); = help: consider using `==` on `str`s error: trivial regex - --> $DIR/regex.rs:50:48 + --> $DIR/regex.rs:55:48 | LL | let trivial_eq_builder = RegexBuilder::new("^foobar$"); | ^^^^^^^^^^ @@ -116,7 +122,7 @@ LL | let trivial_eq_builder = RegexBuilder::new("^foobar$"); = help: consider using `==` on `str`s error: trivial regex - --> $DIR/regex.rs:52:42 + --> $DIR/regex.rs:57:42 | LL | let trivial_starts_with = Regex::new("^foobar"); | ^^^^^^^^^ @@ -124,7 +130,7 @@ LL | let trivial_starts_with = Regex::new("^foobar"); = help: consider using `str::starts_with` error: trivial regex - --> $DIR/regex.rs:54:40 + --> $DIR/regex.rs:59:40 | LL | let trivial_ends_with = Regex::new("foobar$"); | ^^^^^^^^^ @@ -132,7 +138,7 @@ LL | let trivial_ends_with = Regex::new("foobar$"); = help: consider using `str::ends_with` error: trivial regex - --> $DIR/regex.rs:56:39 + --> $DIR/regex.rs:61:39 | LL | let trivial_contains = Regex::new("foobar"); | ^^^^^^^^ @@ -140,7 +146,7 @@ LL | let trivial_contains = Regex::new("foobar"); = help: consider using `str::contains` error: trivial regex - --> $DIR/regex.rs:58:39 + --> $DIR/regex.rs:63:39 | LL | let trivial_contains = Regex::new(NOT_A_REAL_REGEX); | ^^^^^^^^^^^^^^^^ @@ -148,7 +154,7 @@ LL | let trivial_contains = Regex::new(NOT_A_REAL_REGEX); = help: consider using `str::contains` error: trivial regex - --> $DIR/regex.rs:60:40 + --> $DIR/regex.rs:65:40 | LL | let trivial_backslash = Regex::new("a/.b"); | ^^^^^^^ @@ -156,7 +162,7 @@ LL | let trivial_backslash = Regex::new("a/.b"); = help: consider using `str::contains` error: trivial regex - --> $DIR/regex.rs:63:36 + --> $DIR/regex.rs:68:36 | LL | let trivial_empty = Regex::new(""); | ^^ @@ -164,7 +170,7 @@ LL | let trivial_empty = Regex::new(""); = help: the regex is unlikely to be useful as it is error: trivial regex - --> $DIR/regex.rs:65:36 + --> $DIR/regex.rs:70:36 | LL | let trivial_empty = Regex::new("^"); | ^^^ @@ -172,7 +178,7 @@ LL | let trivial_empty = Regex::new("^"); = help: the regex is unlikely to be useful as it is error: trivial regex - --> $DIR/regex.rs:67:36 + --> $DIR/regex.rs:72:36 | LL | let trivial_empty = Regex::new("^$"); | ^^^^ @@ -180,12 +186,12 @@ LL | let trivial_empty = Regex::new("^$"); = help: consider using `str::is_empty` error: trivial regex - --> $DIR/regex.rs:69:44 + --> $DIR/regex.rs:74:44 | LL | let binary_trivial_empty = BRegex::new("^$"); | ^^^^ | = help: consider using `str::is_empty` -error: aborting due to 23 previous errors +error: aborting due to 24 previous errors diff --git a/tests/ui/rename.fixed b/tests/ui/rename.fixed index f7854b89ee4..30f2bfc8c1a 100644 --- a/tests/ui/rename.fixed +++ b/tests/ui/rename.fixed @@ -28,6 +28,7 @@ #![allow(clippy::module_name_repetitions)] #![allow(clippy::recursive_format_impl)] #![allow(clippy::invisible_characters)] +#![allow(cast_ref_to_mut)] #![allow(suspicious_double_ref_op)] #![allow(cast_ref_to_mut)] #![allow(drop_bounds)] diff --git a/tests/ui/rename.rs b/tests/ui/rename.rs index fa347d395ef..3939914d422 100644 --- a/tests/ui/rename.rs +++ b/tests/ui/rename.rs @@ -28,6 +28,7 @@ #![allow(clippy::module_name_repetitions)] #![allow(clippy::recursive_format_impl)] #![allow(clippy::invisible_characters)] +#![allow(cast_ref_to_mut)] #![allow(suspicious_double_ref_op)] #![allow(cast_ref_to_mut)] #![allow(drop_bounds)] diff --git a/tests/ui/rename.stderr b/tests/ui/rename.stderr index 9dffe51e5d7..7290cf32e5b 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:51:9 + --> $DIR/rename.rs:52:9 | LL | #![warn(clippy::almost_complete_letter_range)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::almost_complete_range` @@ -7,295 +7,295 @@ 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:52:9 + --> $DIR/rename.rs:53: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:53:9 + --> $DIR/rename.rs:54: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:54:9 + --> $DIR/rename.rs:55: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:55:9 + --> $DIR/rename.rs:56: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:56:9 + --> $DIR/rename.rs:57: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:57:9 + --> $DIR/rename.rs:58: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:58:9 + --> $DIR/rename.rs:59: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:59:9 + --> $DIR/rename.rs:60: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:60:9 + --> $DIR/rename.rs:61: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:61:9 + --> $DIR/rename.rs:62: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:62:9 + --> $DIR/rename.rs:63: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:63:9 + --> $DIR/rename.rs:64:9 | LL | #![warn(clippy::if_let_some_result)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::match_result_ok` error: lint `clippy::integer_arithmetic` has been renamed to `clippy::arithmetic_side_effects` - --> $DIR/rename.rs:64:9 + --> $DIR/rename.rs:65:9 | LL | #![warn(clippy::integer_arithmetic)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::arithmetic_side_effects` error: lint `clippy::logic_bug` has been renamed to `clippy::overly_complex_bool_expr` - --> $DIR/rename.rs:65:9 + --> $DIR/rename.rs:66: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:66:9 + --> $DIR/rename.rs:67: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:67:9 + --> $DIR/rename.rs:68: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:68:9 + --> $DIR/rename.rs:69: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:69:9 + --> $DIR/rename.rs:70: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:70:9 + --> $DIR/rename.rs:71: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:71:9 + --> $DIR/rename.rs:72: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:72:9 + --> $DIR/rename.rs:73: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:73:9 + --> $DIR/rename.rs:74: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:74:9 + --> $DIR/rename.rs:75: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:75:9 + --> $DIR/rename.rs:76: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:76:9 + --> $DIR/rename.rs:77: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:77:9 + --> $DIR/rename.rs:78: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:78:9 + --> $DIR/rename.rs:79: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:79:9 + --> $DIR/rename.rs:80:9 | LL | #![warn(clippy::zero_width_space)] | ^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::invisible_characters` error: lint `clippy::cast_ref_to_mut` has been renamed to `cast_ref_to_mut` - --> $DIR/rename.rs:80:9 + --> $DIR/rename.rs:81:9 | LL | #![warn(clippy::cast_ref_to_mut)] | ^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `cast_ref_to_mut` error: lint `clippy::clone_double_ref` has been renamed to `suspicious_double_ref_op` - --> $DIR/rename.rs:81:9 + --> $DIR/rename.rs:82: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:82:9 + --> $DIR/rename.rs:83:9 | LL | #![warn(clippy::drop_bounds)] | ^^^^^^^^^^^^^^^^^^^ help: use the new name: `drop_bounds` error: lint `clippy::drop_copy` has been renamed to `dropping_copy_types` - --> $DIR/rename.rs:83:9 + --> $DIR/rename.rs:84:9 | LL | #![warn(clippy::drop_copy)] | ^^^^^^^^^^^^^^^^^ help: use the new name: `dropping_copy_types` error: lint `clippy::drop_ref` has been renamed to `dropping_references` - --> $DIR/rename.rs:84:9 + --> $DIR/rename.rs:85:9 | LL | #![warn(clippy::drop_ref)] | ^^^^^^^^^^^^^^^^ help: use the new name: `dropping_references` error: lint `clippy::for_loop_over_option` has been renamed to `for_loops_over_fallibles` - --> $DIR/rename.rs:85:9 + --> $DIR/rename.rs:86: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:86:9 + --> $DIR/rename.rs:87: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:87:9 + --> $DIR/rename.rs:88:9 | LL | #![warn(clippy::for_loops_over_fallibles)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `for_loops_over_fallibles` error: lint `clippy::forget_copy` has been renamed to `forgetting_copy_types` - --> $DIR/rename.rs:88:9 + --> $DIR/rename.rs:89:9 | LL | #![warn(clippy::forget_copy)] | ^^^^^^^^^^^^^^^^^^^ help: use the new name: `forgetting_copy_types` error: lint `clippy::forget_ref` has been renamed to `forgetting_references` - --> $DIR/rename.rs:89:9 + --> $DIR/rename.rs:90:9 | LL | #![warn(clippy::forget_ref)] | ^^^^^^^^^^^^^^^^^^ help: use the new name: `forgetting_references` error: lint `clippy::into_iter_on_array` has been renamed to `array_into_iter` - --> $DIR/rename.rs:90:9 + --> $DIR/rename.rs:91: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:91:9 + --> $DIR/rename.rs:92: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:92:9 + --> $DIR/rename.rs:93:9 | LL | #![warn(clippy::invalid_ref)] | ^^^^^^^^^^^^^^^^^^^ help: use the new name: `invalid_value` error: lint `clippy::invalid_utf8_in_unchecked` has been renamed to `invalid_from_utf8_unchecked` - --> $DIR/rename.rs:93:9 + --> $DIR/rename.rs:94:9 | LL | #![warn(clippy::invalid_utf8_in_unchecked)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `invalid_from_utf8_unchecked` error: lint `clippy::let_underscore_drop` has been renamed to `let_underscore_drop` - --> $DIR/rename.rs:94:9 + --> $DIR/rename.rs:95: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:95:9 + --> $DIR/rename.rs:96: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:96:9 + --> $DIR/rename.rs:97: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:97:9 + --> $DIR/rename.rs:98: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:98:9 + --> $DIR/rename.rs:99: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:99:9 + --> $DIR/rename.rs:100: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:100:9 + --> $DIR/rename.rs:101:9 | LL | #![warn(clippy::unused_label)] | ^^^^^^^^^^^^^^^^^^^^ help: use the new name: `unused_labels` diff --git a/tests/ui/single_match.fixed b/tests/ui/single_match.fixed new file mode 100644 index 00000000000..77a2cf3b991 --- /dev/null +++ b/tests/ui/single_match.fixed @@ -0,0 +1,209 @@ +//@run-rustfix +#![warn(clippy::single_match)] +#![allow(unused, clippy::uninlined_format_args, clippy::redundant_pattern_matching)] +fn dummy() {} + +fn single_match() { + let x = Some(1u8); + + if let Some(y) = x { + println!("{:?}", y); + }; + + let x = Some(1u8); + if let Some(y) = x { println!("{:?}", y) } + + let z = (1u8, 1u8); + if let (2..=3, 7..=9) = z { dummy() }; + + // Not linted (pattern guards used) + match x { + Some(y) if y == 0 => println!("{:?}", y), + _ => (), + } + + // Not linted (no block with statements in the single arm) + match z { + (2..=3, 7..=9) => println!("{:?}", z), + _ => println!("nope"), + } +} + +enum Foo { + Bar, + Baz(u8), +} +use std::borrow::Cow; +use Foo::*; + +fn single_match_know_enum() { + let x = Some(1u8); + let y: Result<_, i8> = Ok(1i8); + + if let Some(y) = x { dummy() }; + + if let Ok(y) = y { dummy() }; + + let c = Cow::Borrowed(""); + + if let Cow::Borrowed(..) = c { dummy() }; + + let z = Foo::Bar; + // no warning + match z { + Bar => println!("42"), + Baz(_) => (), + } + + match z { + Baz(_) => println!("42"), + Bar => (), + } +} + +// issue #173 +fn if_suggestion() { + let x = "test"; + if x == "test" { println!() } + + #[derive(PartialEq, Eq)] + enum Foo { + A, + B, + C(u32), + } + + let x = Foo::A; + if x == Foo::A { println!() } + + const FOO_C: Foo = Foo::C(0); + if x == FOO_C { println!() } + + if x == Foo::A { println!() } + + let x = &x; + if x == &Foo::A { println!() } + + enum Bar { + A, + B, + } + impl PartialEq for Bar { + fn eq(&self, rhs: &Self) -> bool { + matches!((self, rhs), (Self::A, Self::A) | (Self::B, Self::B)) + } + } + impl Eq for Bar {} + + let x = Bar::A; + if let Bar::A = x { println!() } + + // issue #7038 + struct X; + let x = Some(X); + if let None = x { println!() }; +} + +// See: issue #8282 +fn ranges() { + enum E { + V, + } + let x = (Some(E::V), Some(42)); + + // Don't lint, because the `E` enum can be extended with additional fields later. Thus, the + // proposed replacement to `if let Some(E::V)` may hide non-exhaustive warnings that appeared + // because of `match` construction. + match x { + (Some(E::V), _) => {}, + (None, _) => {}, + } + + // lint + if let (Some(_), _) = x {} + + // lint + if let (Some(E::V), _) = x { todo!() } + + // lint + if let (.., Some(E::V), _) = (Some(42), Some(E::V), Some(42)) {} + + // Don't lint, see above. + match (Some(E::V), Some(E::V), Some(E::V)) { + (.., Some(E::V), _) => {}, + (.., None, _) => {}, + } + + // Don't lint, see above. + match (Some(E::V), Some(E::V), Some(E::V)) { + (Some(E::V), ..) => {}, + (None, ..) => {}, + } + + // Don't lint, see above. + match (Some(E::V), Some(E::V), Some(E::V)) { + (_, Some(E::V), ..) => {}, + (_, None, ..) => {}, + } +} + +fn skip_type_aliases() { + enum OptionEx { + Some(i32), + None, + } + enum ResultEx { + Err(i32), + Ok(i32), + } + + use OptionEx::{None, Some}; + use ResultEx::{Err, Ok}; + + // don't lint + match Err(42) { + Ok(_) => dummy(), + Err(_) => (), + }; + + // don't lint + match Some(1i32) { + Some(_) => dummy(), + None => (), + }; +} + +macro_rules! single_match { + ($num:literal) => { + match $num { + 15 => println!("15"), + _ => (), + } + }; +} + +fn main() { + single_match!(5); + + // Don't lint + let _ = match Some(0) { + #[cfg(feature = "foo")] + Some(10) => 11, + Some(x) => x, + _ => 0, + }; +} + +fn issue_10808(bar: Option) { + if let Some(v) = bar { unsafe { + let r = &v as *const i32; + println!("{}", *r); + } } + + if let Some(v) = bar { + unsafe { + let r = &v as *const i32; + println!("{}", *r); + } + } +} diff --git a/tests/ui/single_match.rs b/tests/ui/single_match.rs index d0c9b7b5663..8d0ab5b99ad 100644 --- a/tests/ui/single_match.rs +++ b/tests/ui/single_match.rs @@ -1,6 +1,6 @@ +//@run-rustfix #![warn(clippy::single_match)] -#![allow(clippy::uninlined_format_args)] - +#![allow(unused, clippy::uninlined_format_args, clippy::redundant_pattern_matching)] fn dummy() {} fn single_match() { @@ -244,3 +244,24 @@ fn main() { _ => 0, }; } + +fn issue_10808(bar: Option) { + match bar { + Some(v) => unsafe { + let r = &v as *const i32; + println!("{}", *r); + }, + _ => {}, + } + + match bar { + #[rustfmt::skip] + Some(v) => { + unsafe { + let r = &v as *const i32; + println!("{}", *r); + } + }, + _ => {}, + } +} diff --git a/tests/ui/single_match.stderr b/tests/ui/single_match.stderr index 7cecc1b7395..dad66e2ab2e 100644 --- a/tests/ui/single_match.stderr +++ b/tests/ui/single_match.stderr @@ -155,5 +155,47 @@ LL | | (..) => {}, LL | | } | |_____^ help: try this: `if let (.., Some(E::V), _) = (Some(42), Some(E::V), Some(42)) {}` -error: aborting due to 16 previous errors +error: you seem to be trying to use `match` for destructuring a single pattern. Consider using `if let` + --> $DIR/single_match.rs:249:5 + | +LL | / match bar { +LL | | Some(v) => unsafe { +LL | | let r = &v as *const i32; +LL | | println!("{}", *r); +LL | | }, +LL | | _ => {}, +LL | | } + | |_____^ + | +help: try this + | +LL ~ if let Some(v) = bar { unsafe { +LL + let r = &v as *const i32; +LL + println!("{}", *r); +LL + } } + | + +error: you seem to be trying to use `match` for destructuring a single pattern. Consider using `if let` + --> $DIR/single_match.rs:257:5 + | +LL | / match bar { +LL | | #[rustfmt::skip] +LL | | Some(v) => { +LL | | unsafe { +... | +LL | | _ => {}, +LL | | } + | |_____^ + | +help: try this + | +LL ~ if let Some(v) = bar { +LL + unsafe { +LL + let r = &v as *const i32; +LL + println!("{}", *r); +LL + } +LL + } + | + +error: aborting due to 18 previous errors diff --git a/tests/ui/single_match_else.fixed b/tests/ui/single_match_else.fixed new file mode 100644 index 00000000000..f88498655a4 --- /dev/null +++ b/tests/ui/single_match_else.fixed @@ -0,0 +1,173 @@ +//@run-rustfix +//@aux-build: proc_macros.rs +#![warn(clippy::single_match_else)] +#![allow(unused, clippy::needless_return, clippy::no_effect, clippy::uninlined_format_args)] +extern crate proc_macros; +use proc_macros::with_span; + +enum ExprNode { + ExprAddrOf, + Butterflies, + Unicorns, +} + +static NODE: ExprNode = ExprNode::Unicorns; + +fn unwrap_addr() -> Option<&'static ExprNode> { + let _ = if let ExprNode::ExprAddrOf = ExprNode::Butterflies { Some(&NODE) } else { + let x = 5; + None + }; + + // Don't lint + with_span!(span match ExprNode::Butterflies { + ExprNode::ExprAddrOf => Some(&NODE), + _ => { + let x = 5; + None + }, + }) +} + +macro_rules! unwrap_addr { + ($expression:expr) => { + match $expression { + ExprNode::ExprAddrOf => Some(&NODE), + _ => { + let x = 5; + None + }, + } + }; +} + +#[rustfmt::skip] +fn main() { + unwrap_addr!(ExprNode::Unicorns); + + // + // don't lint single exprs/statements + // + + // don't lint here + match Some(1) { + Some(a) => println!("${:?}", a), + None => return, + } + + // don't lint here + match Some(1) { + Some(a) => println!("${:?}", a), + None => { + return + }, + } + + // don't lint here + match Some(1) { + Some(a) => println!("${:?}", a), + None => { + return; + }, + } + + // + // lint multiple exprs/statements "else" blocks + // + + // lint here + if let Some(a) = Some(1) { println!("${:?}", a) } else { + println!("else block"); + return + } + + // lint here + if let Some(a) = Some(1) { println!("${:?}", a) } else { + println!("else block"); + return; + } + + // lint here + use std::convert::Infallible; + if let Ok(a) = Result::::Ok(1) { println!("${:?}", a) } else { + println!("else block"); + return; + } + + use std::borrow::Cow; + if let Cow::Owned(a) = Cow::from("moo") { println!("${:?}", a) } else { + println!("else block"); + return; + } +} + +fn issue_10808(bar: Option) { + if let Some(v) = bar { unsafe { + let r = &v as *const i32; + println!("{}", *r); + } } else { + println!("None1"); + println!("None2"); + } + + if let Some(v) = bar { + println!("Some"); + println!("{v}"); + } else { unsafe { + let v = 0; + let r = &v as *const i32; + println!("{}", *r); + } } + + if let Some(v) = bar { unsafe { + let r = &v as *const i32; + println!("{}", *r); + } } else { unsafe { + let v = 0; + let r = &v as *const i32; + println!("{}", *r); + } } + + if let Some(v) = bar { + unsafe { + let r = &v as *const i32; + println!("{}", *r); + } + } else { + println!("None"); + println!("None"); + } + + match bar { + Some(v) => { + println!("Some"); + println!("{v}"); + }, + #[rustfmt::skip] + None => { + unsafe { + let v = 0; + let r = &v as *const i32; + println!("{}", *r); + } + }, + } + + match bar { + #[rustfmt::skip] + Some(v) => { + unsafe { + let r = &v as *const i32; + println!("{}", *r); + } + }, + #[rustfmt::skip] + None => { + unsafe { + let v = 0; + let r = &v as *const i32; + println!("{}", *r); + } + }, + } +} diff --git a/tests/ui/single_match_else.rs b/tests/ui/single_match_else.rs index c8ac768b60f..b34b9553919 100644 --- a/tests/ui/single_match_else.rs +++ b/tests/ui/single_match_else.rs @@ -1,7 +1,7 @@ +//@run-rustfix //@aux-build: proc_macros.rs #![warn(clippy::single_match_else)] -#![allow(clippy::needless_return, clippy::no_effect, clippy::uninlined_format_args)] - +#![allow(unused, clippy::needless_return, clippy::no_effect, clippy::uninlined_format_args)] extern crate proc_macros; use proc_macros::with_span; @@ -115,3 +115,87 @@ fn main() { } } } + +fn issue_10808(bar: Option) { + match bar { + Some(v) => unsafe { + let r = &v as *const i32; + println!("{}", *r); + }, + None => { + println!("None1"); + println!("None2"); + }, + } + + match bar { + Some(v) => { + println!("Some"); + println!("{v}"); + }, + None => unsafe { + let v = 0; + let r = &v as *const i32; + println!("{}", *r); + }, + } + + match bar { + Some(v) => unsafe { + let r = &v as *const i32; + println!("{}", *r); + }, + None => unsafe { + let v = 0; + let r = &v as *const i32; + println!("{}", *r); + }, + } + + match bar { + #[rustfmt::skip] + Some(v) => { + unsafe { + let r = &v as *const i32; + println!("{}", *r); + } + }, + None => { + println!("None"); + println!("None"); + }, + } + + match bar { + Some(v) => { + println!("Some"); + println!("{v}"); + }, + #[rustfmt::skip] + None => { + unsafe { + let v = 0; + let r = &v as *const i32; + println!("{}", *r); + } + }, + } + + match bar { + #[rustfmt::skip] + Some(v) => { + unsafe { + let r = &v as *const i32; + println!("{}", *r); + } + }, + #[rustfmt::skip] + None => { + unsafe { + let v = 0; + let r = &v as *const i32; + println!("{}", *r); + } + }, + } +} diff --git a/tests/ui/single_match_else.stderr b/tests/ui/single_match_else.stderr index 62876a55dc6..228236f3bb8 100644 --- a/tests/ui/single_match_else.stderr +++ b/tests/ui/single_match_else.stderr @@ -100,5 +100,101 @@ LL + return; LL + } | -error: aborting due to 5 previous errors +error: you seem to be trying to use `match` for destructuring a single pattern. Consider using `if let` + --> $DIR/single_match_else.rs:120:5 + | +LL | / match bar { +LL | | Some(v) => unsafe { +LL | | let r = &v as *const i32; +LL | | println!("{}", *r); +... | +LL | | }, +LL | | } + | |_____^ + | +help: try this + | +LL ~ if let Some(v) = bar { unsafe { +LL + let r = &v as *const i32; +LL + println!("{}", *r); +LL + } } else { +LL + println!("None1"); +LL + println!("None2"); +LL + } + | + +error: you seem to be trying to use `match` for destructuring a single pattern. Consider using `if let` + --> $DIR/single_match_else.rs:131:5 + | +LL | / match bar { +LL | | Some(v) => { +LL | | println!("Some"); +LL | | println!("{v}"); +... | +LL | | }, +LL | | } + | |_____^ + | +help: try this + | +LL ~ if let Some(v) = bar { +LL + println!("Some"); +LL + println!("{v}"); +LL + } else { unsafe { +LL + let v = 0; +LL + let r = &v as *const i32; +LL + println!("{}", *r); +LL + } } + | + +error: you seem to be trying to use `match` for destructuring a single pattern. Consider using `if let` + --> $DIR/single_match_else.rs:143:5 + | +LL | / match bar { +LL | | Some(v) => unsafe { +LL | | let r = &v as *const i32; +LL | | println!("{}", *r); +... | +LL | | }, +LL | | } + | |_____^ + | +help: try this + | +LL ~ if let Some(v) = bar { unsafe { +LL + let r = &v as *const i32; +LL + println!("{}", *r); +LL + } } else { unsafe { +LL + let v = 0; +LL + let r = &v as *const i32; +LL + println!("{}", *r); +LL + } } + | + +error: you seem to be trying to use `match` for destructuring a single pattern. Consider using `if let` + --> $DIR/single_match_else.rs:155:5 + | +LL | / match bar { +LL | | #[rustfmt::skip] +LL | | Some(v) => { +LL | | unsafe { +... | +LL | | }, +LL | | } + | |_____^ + | +help: try this + | +LL ~ if let Some(v) = bar { +LL + unsafe { +LL + let r = &v as *const i32; +LL + println!("{}", *r); +LL + } +LL + } else { +LL + println!("None"); +LL + println!("None"); +LL + } + | + +error: aborting due to 9 previous errors diff --git a/tests/ui/suspicious_else_formatting.rs b/tests/ui/suspicious_else_formatting.rs index e0153cdd8cd..4823d909208 100644 --- a/tests/ui/suspicious_else_formatting.rs +++ b/tests/ui/suspicious_else_formatting.rs @@ -1,7 +1,7 @@ //@aux-build:proc_macro_suspicious_else_formatting.rs #![warn(clippy::suspicious_else_formatting)] -#![allow(clippy::if_same_then_else, clippy::let_unit_value)] +#![allow(clippy::if_same_then_else, clippy::let_unit_value, clippy::needless_else)] extern crate proc_macro_suspicious_else_formatting; use proc_macro_suspicious_else_formatting::DeriveBadSpan; diff --git a/tests/ui/unused_async.rs b/tests/ui/unused_async.rs index 4ca7f29b34c..bfaa5dadfa5 100644 --- a/tests/ui/unused_async.rs +++ b/tests/ui/unused_async.rs @@ -3,6 +3,26 @@ use std::future::Future; use std::pin::Pin; +mod issue10800 { + #![allow(dead_code, unused_must_use, clippy::no_effect)] + + use std::future::ready; + + async fn async_block_await() { + async { + ready(()).await; + }; + } + + async fn normal_block_await() { + { + { + ready(()).await; + } + } + } +} + async fn foo() -> i32 { 4 } diff --git a/tests/ui/unused_async.stderr b/tests/ui/unused_async.stderr index cff3eccbd32..8ac2066a6b2 100644 --- a/tests/ui/unused_async.stderr +++ b/tests/ui/unused_async.stderr @@ -1,5 +1,23 @@ error: unused `async` for function with no await statements - --> $DIR/unused_async.rs:6:1 + --> $DIR/unused_async.rs:11:5 + | +LL | / async fn async_block_await() { +LL | | async { +LL | | ready(()).await; +LL | | }; +LL | | } + | |_____^ + | + = help: consider removing the `async` from this function +note: `await` used in an async block, which does not require the enclosing function to be `async` + --> $DIR/unused_async.rs:13:23 + | +LL | ready(()).await; + | ^^^^^ + = note: `-D clippy::unused-async` implied by `-D warnings` + +error: unused `async` for function with no await statements + --> $DIR/unused_async.rs:26:1 | LL | / async fn foo() -> i32 { LL | | 4 @@ -7,10 +25,9 @@ LL | | } | |_^ | = help: consider removing the `async` from this function - = note: `-D clippy::unused-async` implied by `-D warnings` error: unused `async` for function with no await statements - --> $DIR/unused_async.rs:17:5 + --> $DIR/unused_async.rs:37:5 | LL | / async fn unused(&self) -> i32 { LL | | 1 @@ -19,5 +36,5 @@ LL | | } | = help: consider removing the `async` from this function -error: aborting due to 2 previous errors +error: aborting due to 3 previous errors diff --git a/tests/ui/wildcard_imports.fixed b/tests/ui/wildcard_imports.fixed index bd845361fa8..733bbcfbcef 100644 --- a/tests/ui/wildcard_imports.fixed +++ b/tests/ui/wildcard_imports.fixed @@ -24,6 +24,7 @@ use wildcard_imports_helper::inner::inner_for_self_import::inner_extern_bar; use wildcard_imports_helper::{ExternA, extern_foo}; use std::io::prelude::*; +use wildcard_imports_helper::extern_prelude::v1::*; use wildcard_imports_helper::prelude::v1::*; struct ReadFoo; @@ -81,6 +82,7 @@ fn main() { let _ = inner_struct_mod::C; let _ = ExternA; let _ = PreludeModAnywhere; + let _ = ExternPreludeModAnywhere; double_struct_import_test!(); double_struct_import_test!(); diff --git a/tests/ui/wildcard_imports.rs b/tests/ui/wildcard_imports.rs index fb51f7bdfcc..4acdd374bde 100644 --- a/tests/ui/wildcard_imports.rs +++ b/tests/ui/wildcard_imports.rs @@ -24,6 +24,7 @@ use wildcard_imports_helper::inner::inner_for_self_import::*; use wildcard_imports_helper::*; use std::io::prelude::*; +use wildcard_imports_helper::extern_prelude::v1::*; use wildcard_imports_helper::prelude::v1::*; struct ReadFoo; @@ -81,6 +82,7 @@ fn main() { let _ = inner_struct_mod::C; let _ = ExternA; let _ = PreludeModAnywhere; + let _ = ExternPreludeModAnywhere; double_struct_import_test!(); double_struct_import_test!(); diff --git a/tests/ui/wildcard_imports.stderr b/tests/ui/wildcard_imports.stderr index 6b469cdfc44..235be2d5708 100644 --- a/tests/ui/wildcard_imports.stderr +++ b/tests/ui/wildcard_imports.stderr @@ -37,55 +37,55 @@ LL | use wildcard_imports_helper::*; | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `wildcard_imports_helper::{ExternA, extern_foo}` error: usage of wildcard import - --> $DIR/wildcard_imports.rs:95:13 + --> $DIR/wildcard_imports.rs:97:13 | LL | use crate::fn_mod::*; | ^^^^^^^^^^^^^^^^ help: try: `crate::fn_mod::foo` error: usage of wildcard import - --> $DIR/wildcard_imports.rs:101:75 + --> $DIR/wildcard_imports.rs:103:75 | LL | use wildcard_imports_helper::inner::inner_for_self_import::{self, *}; | ^ help: try: `inner_extern_foo` error: usage of wildcard import - --> $DIR/wildcard_imports.rs:102:13 + --> $DIR/wildcard_imports.rs:104:13 | LL | use wildcard_imports_helper::*; | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `wildcard_imports_helper::{ExternA, extern_foo}` error: usage of wildcard import - --> $DIR/wildcard_imports.rs:113:20 + --> $DIR/wildcard_imports.rs:115:20 | LL | use self::{inner::*, inner2::*}; | ^^^^^^^^ help: try: `inner::inner_foo` error: usage of wildcard import - --> $DIR/wildcard_imports.rs:113:30 + --> $DIR/wildcard_imports.rs:115:30 | LL | use self::{inner::*, inner2::*}; | ^^^^^^^^^ help: try: `inner2::inner_bar` error: usage of wildcard import - --> $DIR/wildcard_imports.rs:120:13 + --> $DIR/wildcard_imports.rs:122:13 | LL | use wildcard_imports_helper::*; | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `wildcard_imports_helper::{ExternExportedEnum, ExternExportedStruct, extern_exported}` error: usage of wildcard import - --> $DIR/wildcard_imports.rs:149:9 + --> $DIR/wildcard_imports.rs:151:9 | LL | use crate::in_fn_test::*; | ^^^^^^^^^^^^^^^^^^^^ help: try: `crate::in_fn_test::{ExportedEnum, ExportedStruct, exported}` error: usage of wildcard import - --> $DIR/wildcard_imports.rs:158:9 + --> $DIR/wildcard_imports.rs:160:9 | LL | use crate:: in_fn_test:: * ; | ^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `crate:: in_fn_test::exported` error: usage of wildcard import - --> $DIR/wildcard_imports.rs:159:9 + --> $DIR/wildcard_imports.rs:161:9 | LL | use crate:: fn_mod:: | _________^ @@ -93,37 +93,37 @@ LL | | *; | |_________^ help: try: `crate:: fn_mod::foo` error: usage of wildcard import - --> $DIR/wildcard_imports.rs:170:13 + --> $DIR/wildcard_imports.rs:172:13 | LL | use super::*; | ^^^^^^^^ help: try: `super::foofoo` error: usage of wildcard import - --> $DIR/wildcard_imports.rs:205:17 + --> $DIR/wildcard_imports.rs:207:17 | LL | use super::*; | ^^^^^^^^ help: try: `super::insidefoo` error: usage of wildcard import - --> $DIR/wildcard_imports.rs:213:13 + --> $DIR/wildcard_imports.rs:215:13 | LL | use super_imports::*; | ^^^^^^^^^^^^^^^^ help: try: `super_imports::foofoo` error: usage of wildcard import - --> $DIR/wildcard_imports.rs:222:17 + --> $DIR/wildcard_imports.rs:224:17 | LL | use super::super::*; | ^^^^^^^^^^^^^^^ help: try: `super::super::foofoo` error: usage of wildcard import - --> $DIR/wildcard_imports.rs:231:13 + --> $DIR/wildcard_imports.rs:233:13 | LL | use super::super::super_imports::*; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `super::super::super_imports::foofoo` error: usage of wildcard import - --> $DIR/wildcard_imports.rs:239:13 + --> $DIR/wildcard_imports.rs:241:13 | LL | use super::*; | ^^^^^^^^ help: try: `super::foofoo` From 86d57b7bd494f386ce88229622e4522091285f65 Mon Sep 17 00:00:00 2001 From: est31 Date: Fri, 2 Jun 2023 01:00:03 +0200 Subject: [PATCH 047/310] Support multi-binding situations as well as tuple patterns --- clippy_lints/src/manual_let_else.rs | 217 +++++++++++++++++++--------- tests/ui/manual_let_else.rs | 20 ++- tests/ui/manual_let_else.stderr | 14 +- 3 files changed, 174 insertions(+), 77 deletions(-) diff --git a/clippy_lints/src/manual_let_else.rs b/clippy_lints/src/manual_let_else.rs index d5e847e7183..77d673fec24 100644 --- a/clippy_lints/src/manual_let_else.rs +++ b/clippy_lints/src/manual_let_else.rs @@ -6,17 +6,18 @@ use clippy_utils::source::snippet_with_context; use clippy_utils::ty::is_type_diagnostic_item; use clippy_utils::visitors::{Descend, Visitable}; use if_chain::if_chain; -use rustc_data_structures::fx::FxHashSet; +use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_errors::Applicability; use rustc_hir::intravisit::{walk_expr, Visitor}; use rustc_hir::{Expr, ExprKind, HirId, ItemId, Local, MatchSource, Pat, PatKind, QPath, Stmt, StmtKind, Ty}; use rustc_lint::{LateContext, LateLintPass, LintContext}; use rustc_middle::lint::in_external_macro; use rustc_session::{declare_tool_lint, impl_lint_pass}; -use rustc_span::symbol::sym; +use rustc_span::symbol::{sym, Symbol}; use rustc_span::Span; use serde::Deserialize; use std::ops::ControlFlow; +use std::slice; declare_clippy_lint! { /// ### What it does @@ -81,11 +82,11 @@ impl<'tcx> LateLintPass<'tcx> for ManualLetElse { { match if_let_or_match { IfLetOrMatch::IfLet(if_let_expr, let_pat, if_then, if_else) => if_chain! { - if expr_is_simple_identity(let_pat, if_then); + if let Some(ident_map) = expr_simple_identity_map(local.pat, let_pat, if_then); if let Some(if_else) = if_else; if expr_diverges(cx, if_else); then { - emit_manual_let_else(cx, stmt.span, if_let_expr, local.pat, let_pat, if_else); + emit_manual_let_else(cx, stmt.span, if_let_expr, &ident_map, let_pat, if_else); } }, IfLetOrMatch::Match(match_expr, arms, source) => { @@ -118,11 +119,11 @@ impl<'tcx> LateLintPass<'tcx> for ManualLetElse { return; } let pat_arm = &arms[1 - idx]; - if !expr_is_simple_identity(pat_arm.pat, pat_arm.body) { - return; - } + let Some(ident_map) = expr_simple_identity_map(local.pat, pat_arm.pat, pat_arm.body) else { + return + }; - emit_manual_let_else(cx, stmt.span, match_expr, local.pat, pat_arm.pat, diverging_arm.body); + emit_manual_let_else(cx, stmt.span, match_expr, &ident_map, pat_arm.pat, diverging_arm.body); }, } }; @@ -135,7 +136,7 @@ fn emit_manual_let_else( cx: &LateContext<'_>, span: Span, expr: &Expr<'_>, - local: &Pat<'_>, + ident_map: &FxHashMap>, pat: &Pat<'_>, else_body: &Expr<'_>, ) { @@ -159,62 +160,99 @@ fn emit_manual_let_else( } else { format!("{{ {sn_else} }}") }; - let sn_bl = replace_in_pattern(cx, span, local, pat, &mut app, true); + let sn_bl = replace_in_pattern(cx, span, ident_map, pat, &mut app, true); let sugg = format!("let {sn_bl} = {sn_expr} else {else_bl};"); diag.span_suggestion(span, "consider writing", sugg, app); }, ); } -// replaces the locals in the pattern +/// Replaces the locals in the pattern +/// +/// For this example: +/// +/// ```ignore +/// let (a, FooBar { b, c }) = if let Bar { Some(a_i), b_i } = ex { (a_i, b_i) } else { return }; +/// ``` +/// +/// We have: +/// +/// ```ignore +/// pat: Bar { Some(a_i), b_i } +/// ident_map: (a_i) -> (a), (b_i) -> (FooBar { b, c }) +/// ``` +/// +/// We return: +/// +/// ```ignore +/// Bar { Some(a), b_i: FooBar { b, c } } +/// ``` fn replace_in_pattern( cx: &LateContext<'_>, span: Span, - local: &Pat<'_>, + ident_map: &FxHashMap>, pat: &Pat<'_>, app: &mut Applicability, top_level: bool, ) -> String { - let mut bindings_count = 0; - pat.each_binding_or_first(&mut |_, _, _, _| bindings_count += 1); - // If the pattern creates multiple bindings, exit early, - // as otherwise we might paste the pattern to the positions of multiple bindings. - if bindings_count > 1 { - let (sn_pat, _) = snippet_with_context(cx, pat.span, span.ctxt(), "", app); - return sn_pat.into_owned(); - } + // We put a labeled block here so that we can implement the fallback in this function. + // As the function has multiple call sites, implementing the fallback via an Option + // return type and unwrap_or_else would cause repetition. Similarly, the function also + // invokes the fall back multiple times. + 'a: { + // If the ident map is empty, there is no replacement to do. + // The code following this if assumes a non-empty ident_map. + if ident_map.is_empty() { + break 'a; + } - match pat.kind { - PatKind::Binding(..) => { - let (sn_bdg, _) = snippet_with_context(cx, local.span, span.ctxt(), "", app); - return sn_bdg.to_string(); - }, - PatKind::Or(pats) => { - let patterns = pats - .iter() - .map(|pat| replace_in_pattern(cx, span, local, pat, app, false)) - .collect::>(); - let or_pat = patterns.join(" | "); - if top_level { - return format!("({or_pat})"); - } else { + match pat.kind { + PatKind::Binding(_ann, _id, binding_name, opt_subpt) => { + let Some(pat_to_put) = ident_map.get(&binding_name.name) else { break 'a }; + let (sn_ptp, _) = snippet_with_context(cx, pat_to_put.span, span.ctxt(), "", app); + if let Some(subpt) = opt_subpt { + let subpt = replace_in_pattern(cx, span, ident_map, subpt, app, false); + return format!("{sn_ptp} @ {subpt}"); + } + return sn_ptp.to_string(); + }, + PatKind::Or(pats) => { + let patterns = pats + .iter() + .map(|pat| replace_in_pattern(cx, span, ident_map, pat, app, false)) + .collect::>(); + let or_pat = patterns.join(" | "); + if top_level { + return format!("({or_pat})"); + } return or_pat; - } - }, - // Replace the variable name iff `TupleStruct` has one argument like `Variant(v)`. - PatKind::TupleStruct(ref w, args, dot_dot_pos) => { - let mut args = args - .iter() - .map(|pat| replace_in_pattern(cx, span, local, pat, app, false)) - .collect::>(); - if let Some(pos) = dot_dot_pos.as_opt_usize() { - args.insert(pos, "..".to_owned()); - } - let args = args.join(", "); - let sn_wrapper = cx.sess().source_map().span_to_snippet(w.span()).unwrap_or_default(); - return format!("{sn_wrapper}({args})"); - }, - _ => {}, + }, + // Replace the variable name iff `TupleStruct` has one argument like `Variant(v)`. + PatKind::TupleStruct(ref w, args, dot_dot_pos) => { + let mut args = args + .iter() + .map(|pat| replace_in_pattern(cx, span, ident_map, pat, app, false)) + .collect::>(); + if let Some(pos) = dot_dot_pos.as_opt_usize() { + args.insert(pos, "..".to_owned()); + } + let args = args.join(", "); + let sn_wrapper = cx.sess().source_map().span_to_snippet(w.span()).unwrap_or_default(); + return format!("{sn_wrapper}({args})"); + }, + PatKind::Tuple(args, dot_dot_pos) => { + let mut args = args + .iter() + .map(|pat| replace_in_pattern(cx, span, ident_map, pat, app, false)) + .collect::>(); + if let Some(pos) = dot_dot_pos.as_opt_usize() { + args.insert(pos, "..".to_owned()); + } + let args = args.join(", "); + return format!("({args})"); + }, + _ => {}, + } } let (sn_pat, _) = snippet_with_context(cx, pat.span, span.ctxt(), "", app); sn_pat.into_owned() @@ -358,37 +396,74 @@ fn pat_allowed_for_else(cx: &LateContext<'_>, pat: &'_ Pat<'_>, check_types: boo !has_disallowed } -/// Checks if the passed block is a simple identity referring to bindings created by the pattern -fn expr_is_simple_identity(pat: &'_ Pat<'_>, expr: &'_ Expr<'_>) -> bool { - // We support patterns with multiple bindings and tuples, like: - // let ... = if let (Some(foo), bar) = g() { (foo, bar) } else { ... } +/// Checks if the passed block is a simple identity referring to bindings created by the pattern, +/// and if yes, returns a mapping between the relevant sub-pattern and the identifier it corresponds +/// to. +/// +/// We support patterns with multiple bindings and tuples, e.g.: +/// +/// ```ignore +/// let (foo_o, bar_o) = if let (Some(foo), bar) = g() { (foo, bar) } else { ... } +/// ``` +/// +/// The expected params would be: +/// +/// ```ignore +/// local_pat: (foo_o, bar_o) +/// let_pat: (Some(foo), bar) +/// expr: (foo, bar) +/// ``` +/// +/// We build internal `sub_pats` so that it looks like `[foo_o, bar_o]` and `paths` so that it looks +/// like `[foo, bar]`. Then we turn that into `FxHashMap [(foo) -> (foo_o), (bar) -> (bar_o)]` which +/// we return. +fn expr_simple_identity_map<'a, 'hir>( + local_pat: &'a Pat<'hir>, + let_pat: &'_ Pat<'hir>, + expr: &'_ Expr<'hir>, +) -> Option>> { let peeled = peel_blocks(expr); - let paths = match peeled.kind { - ExprKind::Tup(exprs) | ExprKind::Array(exprs) => exprs, - ExprKind::Path(_) => std::slice::from_ref(peeled), - _ => return false, + let (sub_pats, paths) = match (local_pat.kind, peeled.kind) { + (PatKind::Tuple(pats, _), ExprKind::Tup(exprs)) | (PatKind::Slice(pats, ..), ExprKind::Array(exprs)) => { + (pats, exprs) + }, + (_, ExprKind::Path(_)) => (slice::from_ref(local_pat), slice::from_ref(peeled)), + _ => return None, }; + + // There is some length mismatch, which indicates usage of .. in the patterns above e.g.: + // let (a, ..) = if let [a, b, _c] = ex { (a, b) } else { ... }; + // We bail in these cases as they should be rare. + if paths.len() != sub_pats.len() { + return None; + } + let mut pat_bindings = FxHashSet::default(); - pat.each_binding_or_first(&mut |_ann, _hir_id, _sp, ident| { + let_pat.each_binding_or_first(&mut |_ann, _hir_id, _sp, ident| { pat_bindings.insert(ident); }); if pat_bindings.len() < paths.len() { - return false; + // This rebinds some bindings from the outer scope, or it repeats some copy-able bindings multiple + // times. We don't support these cases so we bail here. E.g.: + // let foo = 0; + // let (new_foo, bar, bar_copied) = if let Some(bar) = Some(0) { (foo, bar, bar) } else { .. }; + return None; } - for path in paths { - if_chain! { - if let ExprKind::Path(QPath::Resolved(_ty, path)) = path.kind; - if let [path_seg] = path.segments; - then { - if !pat_bindings.remove(&path_seg.ident) { - return false; - } - } else { - return false; + let mut ident_map = FxHashMap::default(); + for (sub_pat, path) in sub_pats.iter().zip(paths.iter()) { + if let ExprKind::Path(QPath::Resolved(_ty, path)) = path.kind && + let [path_seg] = path.segments + { + let ident = path_seg.ident; + if !pat_bindings.remove(&ident) { + return None; } + ident_map.insert(ident.name, sub_pat); + } else { + return None; } } - true + Some(ident_map) } #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, Deserialize)] diff --git a/tests/ui/manual_let_else.rs b/tests/ui/manual_let_else.rs index 351ea0e4f50..61c3a165009 100644 --- a/tests/ui/manual_let_else.rs +++ b/tests/ui/manual_let_else.rs @@ -127,8 +127,8 @@ fn fire() { return; }; - // Tuples supported for the identity block and pattern - let v = if let (Some(v_some), w_some) = (g(), 0) { + // Tuples supported with multiple bindings + let (w, S { v }) = if let (Some(v_some), w_some) = (g().map(|_| S { v: 0 }), 0) { (w_some, v_some) } else { return; @@ -160,6 +160,9 @@ fn fire() { }; // dot dot works let v = if let Variant::A(.., a) = e() { a } else { return }; + + // () is preserved: a bit of an edge case but make sure it stays around + let w = if let (Some(v), ()) = (g(), ()) { v } else { return }; } fn not_fire() { @@ -284,4 +287,17 @@ fn not_fire() { }; 1 }; + + // This would require creation of a suggestion of the form + // let v @ (Some(_), _) = (...) else { return }; + // Which is too advanced for our code, so we just bail. + let v = if let (Some(v_some), w_some) = (g(), 0) { + (w_some, v_some) + } else { + return; + }; +} + +struct S { + v: u32, } diff --git a/tests/ui/manual_let_else.stderr b/tests/ui/manual_let_else.stderr index 0e876797134..4e83e638cdf 100644 --- a/tests/ui/manual_let_else.stderr +++ b/tests/ui/manual_let_else.stderr @@ -234,7 +234,7 @@ LL + }; error: this could be rewritten as `let...else` --> $DIR/manual_let_else.rs:131:5 | -LL | / let v = if let (Some(v_some), w_some) = (g(), 0) { +LL | / let (w, S { v }) = if let (Some(v_some), w_some) = (g().map(|_| S { v: 0 }), 0) { LL | | (w_some, v_some) LL | | } else { LL | | return; @@ -243,7 +243,7 @@ LL | | }; | help: consider writing | -LL ~ let (Some(v_some), w_some) = (g(), 0) else { +LL ~ let (Some(S { v }), w) = (g().map(|_| S { v: 0 }), 0) else { LL + return; LL + }; | @@ -295,7 +295,13 @@ LL | let v = if let Variant::A(.., a) = e() { a } else { return }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider writing: `let Variant::A(.., v) = e() else { return };` error: this could be rewritten as `let...else` - --> $DIR/manual_let_else.rs:272:5 + --> $DIR/manual_let_else.rs:165:5 + | +LL | let w = if let (Some(v), ()) = (g(), ()) { v } else { return }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider writing: `let (Some(w), ()) = (g(), ()) else { return };` + +error: this could be rewritten as `let...else` + --> $DIR/manual_let_else.rs:275:5 | LL | / let _ = match ff { LL | | Some(value) => value, @@ -303,5 +309,5 @@ LL | | _ => macro_call!(), LL | | }; | |______^ help: consider writing: `let Some(_) = ff else { macro_call!() };` -error: aborting due to 22 previous errors +error: aborting due to 23 previous errors From f5384027012024ab7f28e602b1218ab88463cd79 Mon Sep 17 00:00:00 2001 From: est31 Date: Fri, 2 Jun 2023 01:25:22 +0200 Subject: [PATCH 048/310] Support struct patterns --- clippy_lints/src/manual_let_else.rs | 31 ++++++++++++++-- tests/ui/manual_let_else.rs | 31 ++++++++++++++-- tests/ui/manual_let_else.stderr | 55 +++++++++++++++++++++++++++-- 3 files changed, 111 insertions(+), 6 deletions(-) diff --git a/clippy_lints/src/manual_let_else.rs b/clippy_lints/src/manual_let_else.rs index 77d673fec24..59e421c1622 100644 --- a/clippy_lints/src/manual_let_else.rs +++ b/clippy_lints/src/manual_let_else.rs @@ -147,8 +147,8 @@ fn emit_manual_let_else( "this could be rewritten as `let...else`", |diag| { // This is far from perfect, for example there needs to be: - // * tracking for multi-binding cases: let (foo, bar) = if let (Some(foo), Ok(bar)) = ... - // * renamings of the bindings for many `PatKind`s like structs, slices, etc. + // * renamings of the bindings for many `PatKind`s like slices, etc. + // * limitations in the existing replacement algorithms // * unused binding collision detection with existing ones // for this to be machine applicable. let mut app = Applicability::HasPlaceholders; @@ -227,6 +227,33 @@ fn replace_in_pattern( } return or_pat; }, + PatKind::Struct(path, fields, has_dot_dot) => { + let fields = fields + .iter() + .map(|fld| { + if let PatKind::Binding(_, _, name, None) = fld.pat.kind && + let Some(pat_to_put) = ident_map.get(&name.name) + { + let (sn_fld_name, _) = snippet_with_context(cx, fld.ident.span, span.ctxt(), "", app); + let (sn_ptp, _) = snippet_with_context(cx, pat_to_put.span, span.ctxt(), "", app); + // TODO: this is a bit of a hack, but it does its job. Ideally, we'd check if pat_to_put is + // a PatKind::Binding but that is also hard to get right. + if sn_fld_name == sn_ptp { + // Field init shorthand + return format!("{sn_fld_name}"); + } + return format!("{sn_fld_name}: {sn_ptp}"); + } + let (sn_fld, _) = snippet_with_context(cx, fld.span, span.ctxt(), "", app); + sn_fld.into_owned() + }) + .collect::>(); + let fields_string = fields.join(", "); + + let dot_dot_str = if has_dot_dot { " .." } else { "" }; + let (sn_pth, _) = snippet_with_context(cx, path.span(), span.ctxt(), "", app); + return format!("{sn_pth} {{ {fields_string}{dot_dot_str} }}"); + }, // Replace the variable name iff `TupleStruct` has one argument like `Variant(v)`. PatKind::TupleStruct(ref w, args, dot_dot_pos) => { let mut args = args diff --git a/tests/ui/manual_let_else.rs b/tests/ui/manual_let_else.rs index 61c3a165009..b5c2a5dba34 100644 --- a/tests/ui/manual_let_else.rs +++ b/tests/ui/manual_let_else.rs @@ -163,6 +163,27 @@ fn fire() { // () is preserved: a bit of an edge case but make sure it stays around let w = if let (Some(v), ()) = (g(), ()) { v } else { return }; + + // Tuple structs work + let w = if let Some(S { v: x }) = Some(S { v: 0 }) { + x + } else { + return; + }; + + // Field init shorthand is suggested + let v = if let Some(S { v: x }) = Some(S { v: 0 }) { + x + } else { + return; + }; + + // Multi-field structs also work + let (x, S { v }, w) = if let Some(U { v, w, x }) = None::>> { + (x, v, w) + } else { + return; + }; } fn not_fire() { @@ -298,6 +319,12 @@ fn not_fire() { }; } -struct S { - v: u32, +struct S { + v: T, +} + +struct U { + v: T, + w: T, + x: T, } diff --git a/tests/ui/manual_let_else.stderr b/tests/ui/manual_let_else.stderr index 4e83e638cdf..9d4aef4cad6 100644 --- a/tests/ui/manual_let_else.stderr +++ b/tests/ui/manual_let_else.stderr @@ -301,7 +301,58 @@ LL | let w = if let (Some(v), ()) = (g(), ()) { v } else { return }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider writing: `let (Some(w), ()) = (g(), ()) else { return };` error: this could be rewritten as `let...else` - --> $DIR/manual_let_else.rs:275:5 + --> $DIR/manual_let_else.rs:168:5 + | +LL | / let w = if let Some(S { v: x }) = Some(S { v: 0 }) { +LL | | x +LL | | } else { +LL | | return; +LL | | }; + | |______^ + | +help: consider writing + | +LL ~ let Some(S { v: w }) = Some(S { v: 0 }) else { +LL + return; +LL + }; + | + +error: this could be rewritten as `let...else` + --> $DIR/manual_let_else.rs:175:5 + | +LL | / let v = if let Some(S { v: x }) = Some(S { v: 0 }) { +LL | | x +LL | | } else { +LL | | return; +LL | | }; + | |______^ + | +help: consider writing + | +LL ~ let Some(S { v }) = Some(S { v: 0 }) else { +LL + return; +LL + }; + | + +error: this could be rewritten as `let...else` + --> $DIR/manual_let_else.rs:182:5 + | +LL | / let (x, S { v }, w) = if let Some(U { v, w, x }) = None::>> { +LL | | (x, v, w) +LL | | } else { +LL | | return; +LL | | }; + | |______^ + | +help: consider writing + | +LL ~ let Some(U { v: S { v }, w, x }) = None::>> else { +LL + return; +LL + }; + | + +error: this could be rewritten as `let...else` + --> $DIR/manual_let_else.rs:296:5 | LL | / let _ = match ff { LL | | Some(value) => value, @@ -309,5 +360,5 @@ LL | | _ => macro_call!(), LL | | }; | |______^ help: consider writing: `let Some(_) = ff else { macro_call!() };` -error: aborting due to 23 previous errors +error: aborting due to 26 previous errors From e29a68113f747a4183c3d8153cb7aa1cd2255d8d Mon Sep 17 00:00:00 2001 From: Alex Macleod Date: Fri, 2 Jun 2023 15:13:55 +0000 Subject: [PATCH 049/310] Move redundant_clone to nursery --- clippy_lints/src/redundant_clone.rs | 2 +- tests/ui/redundant_clone.fixed | 1 + tests/ui/redundant_clone.rs | 1 + tests/ui/redundant_clone.stderr | 78 ++++++++++++++--------------- tests/ui/unnecessary_to_owned.fixed | 2 +- tests/ui/unnecessary_to_owned.rs | 2 +- 6 files changed, 44 insertions(+), 42 deletions(-) diff --git a/clippy_lints/src/redundant_clone.rs b/clippy_lints/src/redundant_clone.rs index 944a33cc3e5..685d738cbb7 100644 --- a/clippy_lints/src/redundant_clone.rs +++ b/clippy_lints/src/redundant_clone.rs @@ -57,7 +57,7 @@ declare_clippy_lint! { /// ``` #[clippy::version = "1.32.0"] pub REDUNDANT_CLONE, - perf, + nursery, "`clone()` of an owned value that is going to be dropped immediately" } diff --git a/tests/ui/redundant_clone.fixed b/tests/ui/redundant_clone.fixed index 8bebb5183bc..cb9583aa6ee 100644 --- a/tests/ui/redundant_clone.fixed +++ b/tests/ui/redundant_clone.fixed @@ -1,6 +1,7 @@ //@run-rustfix // rustfix-only-machine-applicable #![feature(lint_reasons)] +#![warn(clippy::redundant_clone)] #![allow(clippy::drop_non_drop, clippy::implicit_clone, clippy::uninlined_format_args)] use std::ffi::OsString; diff --git a/tests/ui/redundant_clone.rs b/tests/ui/redundant_clone.rs index b4bd5d16b1a..e5aeacbb56c 100644 --- a/tests/ui/redundant_clone.rs +++ b/tests/ui/redundant_clone.rs @@ -1,6 +1,7 @@ //@run-rustfix // rustfix-only-machine-applicable #![feature(lint_reasons)] +#![warn(clippy::redundant_clone)] #![allow(clippy::drop_non_drop, clippy::implicit_clone, clippy::uninlined_format_args)] use std::ffi::OsString; diff --git a/tests/ui/redundant_clone.stderr b/tests/ui/redundant_clone.stderr index 782590034d0..bb5c602d63a 100644 --- a/tests/ui/redundant_clone.stderr +++ b/tests/ui/redundant_clone.stderr @@ -1,180 +1,180 @@ error: redundant clone - --> $DIR/redundant_clone.rs:10:42 + --> $DIR/redundant_clone.rs:11:42 | LL | let _s = ["lorem", "ipsum"].join(" ").to_string(); | ^^^^^^^^^^^^ help: remove this | note: this value is dropped without further use - --> $DIR/redundant_clone.rs:10:14 + --> $DIR/redundant_clone.rs:11:14 | LL | let _s = ["lorem", "ipsum"].join(" ").to_string(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ = note: `-D clippy::redundant-clone` implied by `-D warnings` error: redundant clone - --> $DIR/redundant_clone.rs:13:15 + --> $DIR/redundant_clone.rs:14:15 | LL | let _s = s.clone(); | ^^^^^^^^ help: remove this | note: this value is dropped without further use - --> $DIR/redundant_clone.rs:13:14 + --> $DIR/redundant_clone.rs:14:14 | LL | let _s = s.clone(); | ^ error: redundant clone - --> $DIR/redundant_clone.rs:16:15 + --> $DIR/redundant_clone.rs:17:15 | LL | let _s = s.to_string(); | ^^^^^^^^^^^^ help: remove this | note: this value is dropped without further use - --> $DIR/redundant_clone.rs:16:14 + --> $DIR/redundant_clone.rs:17:14 | LL | let _s = s.to_string(); | ^ error: redundant clone - --> $DIR/redundant_clone.rs:19:15 + --> $DIR/redundant_clone.rs:20:15 | LL | let _s = s.to_owned(); | ^^^^^^^^^^^ help: remove this | note: this value is dropped without further use - --> $DIR/redundant_clone.rs:19:14 + --> $DIR/redundant_clone.rs:20:14 | LL | let _s = s.to_owned(); | ^ error: redundant clone - --> $DIR/redundant_clone.rs:21:42 + --> $DIR/redundant_clone.rs:22:42 | LL | let _s = Path::new("/a/b/").join("c").to_owned(); | ^^^^^^^^^^^ help: remove this | note: this value is dropped without further use - --> $DIR/redundant_clone.rs:21:14 + --> $DIR/redundant_clone.rs:22:14 | LL | let _s = Path::new("/a/b/").join("c").to_owned(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: redundant clone - --> $DIR/redundant_clone.rs:23:42 + --> $DIR/redundant_clone.rs:24:42 | LL | let _s = Path::new("/a/b/").join("c").to_path_buf(); | ^^^^^^^^^^^^^^ help: remove this | note: this value is dropped without further use - --> $DIR/redundant_clone.rs:23:14 + --> $DIR/redundant_clone.rs:24:14 | LL | let _s = Path::new("/a/b/").join("c").to_path_buf(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: redundant clone - --> $DIR/redundant_clone.rs:25:29 + --> $DIR/redundant_clone.rs:26:29 | LL | let _s = OsString::new().to_owned(); | ^^^^^^^^^^^ help: remove this | note: this value is dropped without further use - --> $DIR/redundant_clone.rs:25:14 + --> $DIR/redundant_clone.rs:26:14 | LL | let _s = OsString::new().to_owned(); | ^^^^^^^^^^^^^^^ error: redundant clone - --> $DIR/redundant_clone.rs:27:29 + --> $DIR/redundant_clone.rs:28:29 | LL | let _s = OsString::new().to_os_string(); | ^^^^^^^^^^^^^^^ help: remove this | note: this value is dropped without further use - --> $DIR/redundant_clone.rs:27:14 + --> $DIR/redundant_clone.rs:28:14 | LL | let _s = OsString::new().to_os_string(); | ^^^^^^^^^^^^^^^ error: redundant clone - --> $DIR/redundant_clone.rs:38:19 + --> $DIR/redundant_clone.rs:39:19 | LL | let _t = tup.0.clone(); | ^^^^^^^^ help: remove this | note: this value is dropped without further use - --> $DIR/redundant_clone.rs:38:14 + --> $DIR/redundant_clone.rs:39:14 | LL | let _t = tup.0.clone(); | ^^^^^ error: redundant clone - --> $DIR/redundant_clone.rs:70:25 + --> $DIR/redundant_clone.rs:71:25 | LL | if b { (a.clone(), a.clone()) } else { (Alpha, a) } | ^^^^^^^^ help: remove this | note: this value is dropped without further use - --> $DIR/redundant_clone.rs:70:24 + --> $DIR/redundant_clone.rs:71:24 | LL | if b { (a.clone(), a.clone()) } else { (Alpha, a) } | ^ -error: redundant clone - --> $DIR/redundant_clone.rs:127:15 - | -LL | let _s = s.clone(); - | ^^^^^^^^ help: remove this - | -note: this value is dropped without further use - --> $DIR/redundant_clone.rs:127:14 - | -LL | let _s = s.clone(); - | ^ - error: redundant clone --> $DIR/redundant_clone.rs:128:15 | -LL | let _t = t.clone(); +LL | let _s = s.clone(); | ^^^^^^^^ help: remove this | note: this value is dropped without further use --> $DIR/redundant_clone.rs:128:14 | +LL | let _s = s.clone(); + | ^ + +error: redundant clone + --> $DIR/redundant_clone.rs:129:15 + | +LL | let _t = t.clone(); + | ^^^^^^^^ help: remove this + | +note: this value is dropped without further use + --> $DIR/redundant_clone.rs:129:14 + | LL | let _t = t.clone(); | ^ error: redundant clone - --> $DIR/redundant_clone.rs:138:19 + --> $DIR/redundant_clone.rs:139:19 | LL | let _f = f.clone(); | ^^^^^^^^ help: remove this | note: this value is dropped without further use - --> $DIR/redundant_clone.rs:138:18 + --> $DIR/redundant_clone.rs:139:18 | LL | let _f = f.clone(); | ^ error: redundant clone - --> $DIR/redundant_clone.rs:150:14 + --> $DIR/redundant_clone.rs:151:14 | LL | let y = x.clone().join("matthias"); | ^^^^^^^^ help: remove this | note: cloned value is neither consumed nor mutated - --> $DIR/redundant_clone.rs:150:13 + --> $DIR/redundant_clone.rs:151:13 | LL | let y = x.clone().join("matthias"); | ^^^^^^^^^ error: redundant clone - --> $DIR/redundant_clone.rs:204:11 + --> $DIR/redundant_clone.rs:205:11 | LL | foo(&x.clone(), move || { | ^^^^^^^^ help: remove this | note: this value is dropped without further use - --> $DIR/redundant_clone.rs:204:10 + --> $DIR/redundant_clone.rs:205:10 | LL | foo(&x.clone(), move || { | ^ diff --git a/tests/ui/unnecessary_to_owned.fixed b/tests/ui/unnecessary_to_owned.fixed index c879fdc3b6a..08733906b0e 100644 --- a/tests/ui/unnecessary_to_owned.fixed +++ b/tests/ui/unnecessary_to_owned.fixed @@ -1,7 +1,7 @@ //@run-rustfix #![allow(clippy::needless_borrow, clippy::ptr_arg)] -#![warn(clippy::unnecessary_to_owned)] +#![warn(clippy::unnecessary_to_owned, clippy::redundant_clone)] use std::borrow::Cow; use std::ffi::{CStr, CString, OsStr, OsString}; diff --git a/tests/ui/unnecessary_to_owned.rs b/tests/ui/unnecessary_to_owned.rs index 10588beb263..e3589ea0d65 100644 --- a/tests/ui/unnecessary_to_owned.rs +++ b/tests/ui/unnecessary_to_owned.rs @@ -1,7 +1,7 @@ //@run-rustfix #![allow(clippy::needless_borrow, clippy::ptr_arg)] -#![warn(clippy::unnecessary_to_owned)] +#![warn(clippy::unnecessary_to_owned, clippy::redundant_clone)] use std::borrow::Cow; use std::ffi::{CStr, CString, OsStr, OsString}; From ad7c44b3e44b2e100fb55d5ced4e367812233dab Mon Sep 17 00:00:00 2001 From: Centri3 <114838443+Centri3@users.noreply.github.com> Date: Fri, 2 Jun 2023 13:14:16 -0500 Subject: [PATCH 050/310] only lint when `cast_from` and `cast_to`'s ty are the same --- clippy_lints/src/casts/ptr_cast_constness.rs | 13 +++--- tests/ui/ptr_cast_constness.fixed | 19 +++++--- tests/ui/ptr_cast_constness.rs | 29 +++++++----- tests/ui/ptr_cast_constness.stderr | 46 ++++++++++++-------- 4 files changed, 67 insertions(+), 40 deletions(-) diff --git a/clippy_lints/src/casts/ptr_cast_constness.rs b/clippy_lints/src/casts/ptr_cast_constness.rs index ab015f8822e..f0c1df01430 100644 --- a/clippy_lints/src/casts/ptr_cast_constness.rs +++ b/clippy_lints/src/casts/ptr_cast_constness.rs @@ -9,20 +9,21 @@ use rustc_middle::ty::{self, Ty, TypeAndMut}; use super::PTR_CAST_CONSTNESS; -pub(super) fn check( +pub(super) fn check<'tcx>( cx: &LateContext<'_>, expr: &Expr<'_>, cast_expr: &Expr<'_>, - cast_from: Ty<'_>, - cast_to: Ty<'_>, + cast_from: Ty<'tcx>, + cast_to: Ty<'tcx>, msrv: &Msrv, ) { if_chain! { if msrv.meets(POINTER_CAST_CONSTNESS); - if let ty::RawPtr(TypeAndMut { mutbl: from_mutbl, .. }) = cast_from.kind(); - if let ty::RawPtr(TypeAndMut { mutbl: to_mutbl, .. }) = cast_to.kind(); + if let ty::RawPtr(TypeAndMut { mutbl: from_mutbl, ty: from_ty }) = cast_from.kind(); + if let ty::RawPtr(TypeAndMut { mutbl: to_mutbl, ty: to_ty }) = cast_to.kind(); if matches!((from_mutbl, to_mutbl), (Mutability::Not, Mutability::Mut) | (Mutability::Mut, Mutability::Not)); + if from_ty == to_ty; then { let sugg = Sugg::hir(cx, cast_expr, "_"); let constness = match *to_mutbl { @@ -34,7 +35,7 @@ pub(super) fn check( cx, PTR_CAST_CONSTNESS, expr.span, - "`as` casting between raw pointers while changing its constness", + "`as` casting between raw pointers while changing only its constness", &format!("try `pointer::cast_{constness}`, a safer alternative"), format!("{}.cast_{constness}()", sugg.maybe_par()), Applicability::MachineApplicable, diff --git a/tests/ui/ptr_cast_constness.fixed b/tests/ui/ptr_cast_constness.fixed index 24de573d083..36304e4a0f0 100644 --- a/tests/ui/ptr_cast_constness.fixed +++ b/tests/ui/ptr_cast_constness.fixed @@ -2,17 +2,24 @@ //@aux-build:proc_macros.rs #![warn(clippy::ptr_cast_constness)] +#![allow(clippy::transmute_ptr_to_ref, unused)] extern crate proc_macros; use proc_macros::{external, inline_macros}; +unsafe fn ptr_to_ref(p: *const T, om: *mut U) { + let _: &mut T = std::mem::transmute(p.cast_mut()); + let _ = &mut *p.cast_mut(); + let _: &T = &*(om as *const T); +} + #[inline_macros] fn main() { let ptr: *const u32 = &42_u32; let mut_ptr: *mut u32 = &mut 42_u32; - let _ = ptr as *const i32; - let _ = mut_ptr as *mut i32; + let _ = ptr as *const u32; + let _ = mut_ptr as *mut u32; // Make sure the lint can handle the difference in their operator precedences. unsafe { @@ -29,10 +36,10 @@ fn main() { let _ = ptr_of_array as *const dyn std::fmt::Debug; // Make sure the lint is triggered inside a macro - let _ = inline!($ptr as *const i32); + let _ = inline!($ptr as *const u32); // Do not lint inside macros from external crates - let _ = external!($ptr as *const i32); + let _ = external!($ptr as *const u32); } #[clippy::msrv = "1.64"] @@ -41,8 +48,8 @@ fn _msrv_1_64() { let mut_ptr: *mut u32 = &mut 42_u32; // `pointer::cast_const` and `pointer::cast_mut` were stabilized in 1.65. Do not lint this - let _ = ptr as *mut i32; - let _ = mut_ptr as *const i32; + let _ = ptr as *mut u32; + let _ = mut_ptr as *const u32; } #[clippy::msrv = "1.65"] diff --git a/tests/ui/ptr_cast_constness.rs b/tests/ui/ptr_cast_constness.rs index 63d973a9fca..315e828bebe 100644 --- a/tests/ui/ptr_cast_constness.rs +++ b/tests/ui/ptr_cast_constness.rs @@ -2,26 +2,33 @@ //@aux-build:proc_macros.rs #![warn(clippy::ptr_cast_constness)] +#![allow(clippy::transmute_ptr_to_ref, unused)] extern crate proc_macros; use proc_macros::{external, inline_macros}; +unsafe fn ptr_to_ref(p: *const T, om: *mut U) { + let _: &mut T = std::mem::transmute(p as *mut T); + let _ = &mut *(p as *mut T); + let _: &T = &*(om as *const T); +} + #[inline_macros] fn main() { let ptr: *const u32 = &42_u32; let mut_ptr: *mut u32 = &mut 42_u32; - let _ = ptr as *const i32; - let _ = mut_ptr as *mut i32; + let _ = ptr as *const u32; + let _ = mut_ptr as *mut u32; // Make sure the lint can handle the difference in their operator precedences. unsafe { let ptr_ptr: *const *const u32 = &ptr; - let _ = *ptr_ptr as *mut i32; + let _ = *ptr_ptr as *mut u32; } - let _ = ptr as *mut i32; - let _ = mut_ptr as *const i32; + let _ = ptr as *mut u32; + let _ = mut_ptr as *const u32; // Lint this, since pointer::cast_mut and pointer::cast_const have ?Sized let ptr_of_array: *const [u32; 4] = &[1, 2, 3, 4]; @@ -29,10 +36,10 @@ fn main() { let _ = ptr_of_array as *const dyn std::fmt::Debug; // Make sure the lint is triggered inside a macro - let _ = inline!($ptr as *const i32); + let _ = inline!($ptr as *const u32); // Do not lint inside macros from external crates - let _ = external!($ptr as *const i32); + let _ = external!($ptr as *const u32); } #[clippy::msrv = "1.64"] @@ -41,8 +48,8 @@ fn _msrv_1_64() { let mut_ptr: *mut u32 = &mut 42_u32; // `pointer::cast_const` and `pointer::cast_mut` were stabilized in 1.65. Do not lint this - let _ = ptr as *mut i32; - let _ = mut_ptr as *const i32; + let _ = ptr as *mut u32; + let _ = mut_ptr as *const u32; } #[clippy::msrv = "1.65"] @@ -50,6 +57,6 @@ fn _msrv_1_65() { let ptr: *const u32 = &42_u32; let mut_ptr: *mut u32 = &mut 42_u32; - let _ = ptr as *mut i32; - let _ = mut_ptr as *const i32; + let _ = ptr as *mut u32; + let _ = mut_ptr as *const u32; } diff --git a/tests/ui/ptr_cast_constness.stderr b/tests/ui/ptr_cast_constness.stderr index 43816c87c19..0c3ff863685 100644 --- a/tests/ui/ptr_cast_constness.stderr +++ b/tests/ui/ptr_cast_constness.stderr @@ -1,34 +1,46 @@ -error: `as` casting between raw pointers while changing its constness - --> $DIR/ptr_cast_constness.rs:20:17 +error: `as` casting between raw pointers while changing only its constness + --> $DIR/ptr_cast_constness.rs:11:41 | -LL | let _ = *ptr_ptr as *mut i32; - | ^^^^^^^^^^^^^^^^^^^^ help: try `pointer::cast_mut`, a safer alternative: `(*ptr_ptr).cast_mut()` +LL | let _: &mut T = std::mem::transmute(p as *mut T); + | ^^^^^^^^^^^ help: try `pointer::cast_mut`, a safer alternative: `p.cast_mut()` | = note: `-D clippy::ptr-cast-constness` implied by `-D warnings` -error: `as` casting between raw pointers while changing its constness - --> $DIR/ptr_cast_constness.rs:23:13 +error: `as` casting between raw pointers while changing only its constness + --> $DIR/ptr_cast_constness.rs:12:19 | -LL | let _ = ptr as *mut i32; +LL | let _ = &mut *(p as *mut T); + | ^^^^^^^^^^^^^ help: try `pointer::cast_mut`, a safer alternative: `p.cast_mut()` + +error: `as` casting between raw pointers while changing only its constness + --> $DIR/ptr_cast_constness.rs:27:17 + | +LL | let _ = *ptr_ptr as *mut u32; + | ^^^^^^^^^^^^^^^^^^^^ help: try `pointer::cast_mut`, a safer alternative: `(*ptr_ptr).cast_mut()` + +error: `as` casting between raw pointers while changing only its constness + --> $DIR/ptr_cast_constness.rs:30:13 + | +LL | let _ = ptr as *mut u32; | ^^^^^^^^^^^^^^^ help: try `pointer::cast_mut`, a safer alternative: `ptr.cast_mut()` -error: `as` casting between raw pointers while changing its constness - --> $DIR/ptr_cast_constness.rs:24:13 +error: `as` casting between raw pointers while changing only its constness + --> $DIR/ptr_cast_constness.rs:31:13 | -LL | let _ = mut_ptr as *const i32; +LL | let _ = mut_ptr as *const u32; | ^^^^^^^^^^^^^^^^^^^^^ help: try `pointer::cast_const`, a safer alternative: `mut_ptr.cast_const()` -error: `as` casting between raw pointers while changing its constness - --> $DIR/ptr_cast_constness.rs:53:13 +error: `as` casting between raw pointers while changing only its constness + --> $DIR/ptr_cast_constness.rs:60:13 | -LL | let _ = ptr as *mut i32; +LL | let _ = ptr as *mut u32; | ^^^^^^^^^^^^^^^ help: try `pointer::cast_mut`, a safer alternative: `ptr.cast_mut()` -error: `as` casting between raw pointers while changing its constness - --> $DIR/ptr_cast_constness.rs:54:13 +error: `as` casting between raw pointers while changing only its constness + --> $DIR/ptr_cast_constness.rs:61:13 | -LL | let _ = mut_ptr as *const i32; +LL | let _ = mut_ptr as *const u32; | ^^^^^^^^^^^^^^^^^^^^^ help: try `pointer::cast_const`, a safer alternative: `mut_ptr.cast_const()` -error: aborting due to 5 previous errors +error: aborting due to 7 previous errors From cd1d7a3c6f9968c3da89a5788363f042c8f15ebe Mon Sep 17 00:00:00 2001 From: Centri3 <114838443+Centri3@users.noreply.github.com> Date: Fri, 2 Jun 2023 13:26:12 -0500 Subject: [PATCH 051/310] weird --- tests/ui/ptr_cast_constness.fixed | 2 +- tests/ui/ptr_cast_constness.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/ui/ptr_cast_constness.fixed b/tests/ui/ptr_cast_constness.fixed index 36304e4a0f0..ba3eca061df 100644 --- a/tests/ui/ptr_cast_constness.fixed +++ b/tests/ui/ptr_cast_constness.fixed @@ -2,7 +2,7 @@ //@aux-build:proc_macros.rs #![warn(clippy::ptr_cast_constness)] -#![allow(clippy::transmute_ptr_to_ref, unused)] +#![allow(clippy::transmute_ptr_to_ref, clippy::unnecessary_cast, unused)] extern crate proc_macros; use proc_macros::{external, inline_macros}; diff --git a/tests/ui/ptr_cast_constness.rs b/tests/ui/ptr_cast_constness.rs index 315e828bebe..adeb43edf68 100644 --- a/tests/ui/ptr_cast_constness.rs +++ b/tests/ui/ptr_cast_constness.rs @@ -2,7 +2,7 @@ //@aux-build:proc_macros.rs #![warn(clippy::ptr_cast_constness)] -#![allow(clippy::transmute_ptr_to_ref, unused)] +#![allow(clippy::transmute_ptr_to_ref, clippy::unnecessary_cast, unused)] extern crate proc_macros; use proc_macros::{external, inline_macros}; From 7ac15f90002b653f9ba61185858581057d731ee0 Mon Sep 17 00:00:00 2001 From: Raghul Nanth A <61490162+NanthR@users.noreply.github.com> Date: Sun, 7 May 2023 12:10:04 +0530 Subject: [PATCH 052/310] Add lint to check lint formulation messages Fix lints that don't conform to the standard formulation --- clippy_lints/Cargo.toml | 3 +- clippy_lints/src/casts/mod.rs | 2 +- clippy_lints/src/declared_lints.rs | 2 + .../src/default_constructed_unit_structs.rs | 2 +- clippy_lints/src/lib.rs | 3 + clippy_lints/src/loops/mod.rs | 6 +- clippy_lints/src/matches/mod.rs | 2 +- clippy_lints/src/utils/internal_lints.rs | 1 + .../almost_standard_lint_formulation.rs | 87 +++++++++++++++++++ .../allow_incorrect_lint_formulations.rs | 22 +++++ tests/ui-internal/check_formulation.rs | 43 +++++++++ tests/ui-internal/check_formulation.stderr | 19 ++++ 12 files changed, 185 insertions(+), 7 deletions(-) create mode 100644 clippy_lints/src/utils/internal_lints/almost_standard_lint_formulation.rs create mode 100644 tests/ui-internal/allow_incorrect_lint_formulations.rs create mode 100644 tests/ui-internal/check_formulation.rs create mode 100644 tests/ui-internal/check_formulation.stderr diff --git a/clippy_lints/Cargo.toml b/clippy_lints/Cargo.toml index be9261a4704..c23054443bb 100644 --- a/clippy_lints/Cargo.toml +++ b/clippy_lints/Cargo.toml @@ -22,6 +22,7 @@ serde = { version = "1.0", features = ["derive"] } serde_json = { version = "1.0", optional = true } tempfile = { version = "3.3.0", optional = true } toml = "0.7.3" +regex = { version = "1.5", optional = true } unicode-normalization = "0.1" unicode-script = { version = "0.5", default-features = false } semver = "1.0" @@ -31,7 +32,7 @@ url = "2.2" [features] deny-warnings = ["clippy_utils/deny-warnings"] # build clippy with internal lints enabled, off by default -internal = ["clippy_utils/internal", "serde_json", "tempfile"] +internal = ["clippy_utils/internal", "serde_json", "tempfile", "regex"] [package.metadata.rust-analyzer] # This crate uses #[feature(rustc_private)] diff --git a/clippy_lints/src/casts/mod.rs b/clippy_lints/src/casts/mod.rs index 4e8d5c3bccd..d2166872d93 100644 --- a/clippy_lints/src/casts/mod.rs +++ b/clippy_lints/src/casts/mod.rs @@ -522,7 +522,7 @@ declare_clippy_lint! { declare_clippy_lint! { /// ### What it does - /// Check for the usage of `as _` conversion using inferred type. + /// Checks for the usage of `as _` conversion using inferred type. /// /// ### Why is this bad? /// The conversion might include lossy conversion and dangerous cast that might go diff --git a/clippy_lints/src/declared_lints.rs b/clippy_lints/src/declared_lints.rs index a0b8e055f1d..01ef3ef431c 100644 --- a/clippy_lints/src/declared_lints.rs +++ b/clippy_lints/src/declared_lints.rs @@ -3,6 +3,8 @@ // Manual edits will be overwritten. pub(crate) static LINTS: &[&crate::LintInfo] = &[ + #[cfg(feature = "internal")] + crate::utils::internal_lints::almost_standard_lint_formulation::ALMOST_STANDARD_LINT_FORMULATION_INFO, #[cfg(feature = "internal")] crate::utils::internal_lints::clippy_lints_internal::CLIPPY_LINTS_INTERNAL_INFO, #[cfg(feature = "internal")] diff --git a/clippy_lints/src/default_constructed_unit_structs.rs b/clippy_lints/src/default_constructed_unit_structs.rs index fb037bbcbf3..ca9514ccc7d 100644 --- a/clippy_lints/src/default_constructed_unit_structs.rs +++ b/clippy_lints/src/default_constructed_unit_structs.rs @@ -8,7 +8,7 @@ use rustc_session::{declare_lint_pass, declare_tool_lint}; declare_clippy_lint! { /// ### What it does - /// Check for construction on unit struct using `default`. + /// Checks for construction on unit struct using `default`. /// /// ### Why is this bad? /// This adds code complexity and an unnecessary function call. diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index 4a23edb58aa..43ab8a96d86 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -564,6 +564,9 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: store.register_late_pass(|_| Box::::default()); store.register_late_pass(|_| Box::new(utils::internal_lints::outer_expn_data_pass::OuterExpnDataPass)); store.register_late_pass(|_| Box::new(utils::internal_lints::msrv_attr_impl::MsrvAttrImpl)); + store.register_late_pass(|_| { + Box::new(utils::internal_lints::almost_standard_lint_formulation::AlmostStandardFormulation::new()) + }); } let arithmetic_side_effects_allowed = conf.arithmetic_side_effects_allowed.clone(); diff --git a/clippy_lints/src/loops/mod.rs b/clippy_lints/src/loops/mod.rs index f83ad388a74..c7c11809752 100644 --- a/clippy_lints/src/loops/mod.rs +++ b/clippy_lints/src/loops/mod.rs @@ -479,7 +479,7 @@ declare_clippy_lint! { declare_clippy_lint! { /// ### What it does - /// Check for unnecessary `if let` usage in a for loop + /// Checks for unnecessary `if let` usage in a for loop /// where only the `Some` or `Ok` variant of the iterator element is used. /// /// ### Why is this bad? @@ -511,7 +511,7 @@ declare_clippy_lint! { declare_clippy_lint! { /// ### What it does - /// Check for empty spin loops + /// Checks for empty spin loops /// /// ### Why is this bad? /// The loop body should have something like `thread::park()` or at least @@ -547,7 +547,7 @@ declare_clippy_lint! { declare_clippy_lint! { /// ### What it does - /// Check for manual implementations of Iterator::find + /// Checks for manual implementations of Iterator::find /// /// ### Why is this bad? /// It doesn't affect performance, but using `find` is shorter and easier to read. diff --git a/clippy_lints/src/matches/mod.rs b/clippy_lints/src/matches/mod.rs index 0d91051632a..2d27be499f9 100644 --- a/clippy_lints/src/matches/mod.rs +++ b/clippy_lints/src/matches/mod.rs @@ -777,7 +777,7 @@ declare_clippy_lint! { declare_clippy_lint! { /// ### What it does - /// Check for temporaries returned from function calls in a match scrutinee that have the + /// Checks for temporaries returned from function calls in a match scrutinee that have the /// `clippy::has_significant_drop` attribute. /// /// ### Why is this bad? diff --git a/clippy_lints/src/utils/internal_lints.rs b/clippy_lints/src/utils/internal_lints.rs index 71f6c9909dd..e222a5448c9 100644 --- a/clippy_lints/src/utils/internal_lints.rs +++ b/clippy_lints/src/utils/internal_lints.rs @@ -1,3 +1,4 @@ +pub mod almost_standard_lint_formulation; pub mod clippy_lints_internal; pub mod collapsible_calls; pub mod compiler_lint_functions; diff --git a/clippy_lints/src/utils/internal_lints/almost_standard_lint_formulation.rs b/clippy_lints/src/utils/internal_lints/almost_standard_lint_formulation.rs new file mode 100644 index 00000000000..e4cb5316a98 --- /dev/null +++ b/clippy_lints/src/utils/internal_lints/almost_standard_lint_formulation.rs @@ -0,0 +1,87 @@ +use crate::utils::internal_lints::lint_without_lint_pass::is_lint_ref_type; +use clippy_utils::diagnostics::span_lint_and_help; +use regex::Regex; +use rustc_ast as ast; +use rustc_hir::{Item, ItemKind, Mutability}; +use rustc_lint::{LateContext, LateLintPass}; +use rustc_session::{declare_tool_lint, impl_lint_pass}; + +declare_clippy_lint! { + /// ### What it does + /// Checks if lint formulations have a standardized format. + /// + /// ### Why is this bad? + /// It's not neccessarily bad, but we try to enforce a standard in Clippy. + /// + /// ### Example + /// `Checks for use...` can be written as `Checks for usage...` . + pub ALMOST_STANDARD_LINT_FORMULATION, + internal, + "lint formulations must have a standardized format." +} + +impl_lint_pass!(AlmostStandardFormulation => [ALMOST_STANDARD_LINT_FORMULATION]); + +pub struct AlmostStandardFormulation { + standard_formulations: Vec>, +} + +#[derive(Debug)] +struct StandardFormulations<'a> { + wrong_pattern: Regex, + correction: &'a str, +} + +impl AlmostStandardFormulation { + pub fn new() -> Self { + let standard_formulations = vec![StandardFormulations { + wrong_pattern: Regex::new(r"^(Check for|Detects? uses?)").unwrap(), + correction: "Checks for", + }]; + Self { standard_formulations } + } +} + +impl<'tcx> LateLintPass<'tcx> for AlmostStandardFormulation { + fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx Item<'_>) { + let mut check_next = false; + if let ItemKind::Static(ty, Mutability::Not, _) = item.kind { + let lines = cx + .tcx + .hir() + .attrs(item.hir_id()) + .iter() + .filter_map(|attr| ast::Attribute::doc_str(attr).map(|sym| (sym, attr))); + if is_lint_ref_type(cx, ty) { + for (line, attr) in lines { + let cur_line = line.as_str().trim(); + if check_next && !cur_line.is_empty() { + for formulation in &self.standard_formulations { + let starts_with_correct_formulation = cur_line.starts_with(formulation.correction); + if !starts_with_correct_formulation && formulation.wrong_pattern.is_match(cur_line) { + if let Some(ident) = attr.ident() { + span_lint_and_help( + cx, + ALMOST_STANDARD_LINT_FORMULATION, + ident.span, + "non-standard lint formulation", + None, + &format!("try using `{}` instead", formulation.correction), + ); + } + return; + } + } + return; + } else if cur_line.contains("What it does") { + check_next = true; + } else if cur_line.contains("Why is this bad") { + // Formulation documentation is done. Can add check to ensure that missing formulation is added + // and add a check if it matches no accepted formulation + return; + } + } + } + } + } +} diff --git a/tests/ui-internal/allow_incorrect_lint_formulations.rs b/tests/ui-internal/allow_incorrect_lint_formulations.rs new file mode 100644 index 00000000000..7d1e0f26a1b --- /dev/null +++ b/tests/ui-internal/allow_incorrect_lint_formulations.rs @@ -0,0 +1,22 @@ +#![allow(clippy::almost_standard_lint_formulation)] +#![feature(rustc_private)] + +#[macro_use] +extern crate rustc_middle; +#[macro_use] +extern crate rustc_session; +extern crate rustc_lint; + +declare_tool_lint! { + /// # What it does + /// Detects uses of incorrect formulations + #[clippy::version = "pre 1.29.0"] + pub clippy::ALLOWED_INVALID, + Warn, + "One", + report_in_external_macro: true +} + +declare_lint_pass!(Pass => [ALLOWED_INVALID]); + +fn main() {} diff --git a/tests/ui-internal/check_formulation.rs b/tests/ui-internal/check_formulation.rs new file mode 100644 index 00000000000..d6ebadf04c4 --- /dev/null +++ b/tests/ui-internal/check_formulation.rs @@ -0,0 +1,43 @@ +#![warn(clippy::almost_standard_lint_formulation)] +#![feature(rustc_private)] + +#[macro_use] +extern crate rustc_middle; +#[macro_use] +extern crate rustc_session; +extern crate rustc_lint; + +declare_tool_lint! { + /// # What it does + /// + /// Checks for usage of correct lint formulations + #[clippy::version = "pre 1.29.0"] + pub clippy::VALID, + Warn, + "One", + report_in_external_macro: true +} + +declare_tool_lint! { + /// # What it does + /// Check for lint formulations that are correct + #[clippy::version = "pre 1.29.0"] + pub clippy::INVALID1, + Warn, + "One", + report_in_external_macro: true +} + +declare_tool_lint! { + /// # What it does + /// Detects uses of incorrect formulations + #[clippy::version = "pre 1.29.0"] + pub clippy::INVALID2, + Warn, + "One", + report_in_external_macro: true +} + +declare_lint_pass!(Pass => [VALID, INVALID1, INVALID2]); + +fn main() {} diff --git a/tests/ui-internal/check_formulation.stderr b/tests/ui-internal/check_formulation.stderr new file mode 100644 index 00000000000..10eabca4b9d --- /dev/null +++ b/tests/ui-internal/check_formulation.stderr @@ -0,0 +1,19 @@ +error: non-standard lint formulation + --> $DIR/check_formulation.rs:23:5 + | +LL | /// Check for lint formulations that are correct + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: try using `Checks for` instead + = note: `-D clippy::almost-standard-lint-formulation` implied by `-D warnings` + +error: non-standard lint formulation + --> $DIR/check_formulation.rs:33:5 + | +LL | /// Detects uses of incorrect formulations + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: try using `Checks for` instead + +error: aborting due to 2 previous errors + From 50c93bbfd225f202b4b0060c95bd55a6e504dd36 Mon Sep 17 00:00:00 2001 From: Raghul Nanth A <61490162+NanthR@users.noreply.github.com> Date: Fri, 2 Jun 2023 23:56:30 +0530 Subject: [PATCH 053/310] refactor(test): Move attribute to lint level --- .../allow_incorrect_lint_formulations.rs | 22 ------------------- tests/ui-internal/check_formulation.rs | 11 ++++++++++ 2 files changed, 11 insertions(+), 22 deletions(-) delete mode 100644 tests/ui-internal/allow_incorrect_lint_formulations.rs diff --git a/tests/ui-internal/allow_incorrect_lint_formulations.rs b/tests/ui-internal/allow_incorrect_lint_formulations.rs deleted file mode 100644 index 7d1e0f26a1b..00000000000 --- a/tests/ui-internal/allow_incorrect_lint_formulations.rs +++ /dev/null @@ -1,22 +0,0 @@ -#![allow(clippy::almost_standard_lint_formulation)] -#![feature(rustc_private)] - -#[macro_use] -extern crate rustc_middle; -#[macro_use] -extern crate rustc_session; -extern crate rustc_lint; - -declare_tool_lint! { - /// # What it does - /// Detects uses of incorrect formulations - #[clippy::version = "pre 1.29.0"] - pub clippy::ALLOWED_INVALID, - Warn, - "One", - report_in_external_macro: true -} - -declare_lint_pass!(Pass => [ALLOWED_INVALID]); - -fn main() {} diff --git a/tests/ui-internal/check_formulation.rs b/tests/ui-internal/check_formulation.rs index d6ebadf04c4..43fc996033e 100644 --- a/tests/ui-internal/check_formulation.rs +++ b/tests/ui-internal/check_formulation.rs @@ -38,6 +38,17 @@ declare_tool_lint! { report_in_external_macro: true } +declare_tool_lint! { + /// # What it does + /// Detects uses of incorrect formulations (allowed with attribute) + #[allow(clippy::almost_standard_lint_formulation)] + #[clippy::version = "pre 1.29.0"] + pub clippy::ALLOWED_INVALID, + Warn, + "One", + report_in_external_macro: true +} + declare_lint_pass!(Pass => [VALID, INVALID1, INVALID2]); fn main() {} From a6c36556c89ddd6902be7941cadd28812f63d6ed Mon Sep 17 00:00:00 2001 From: Centri3 <114838443+Centri3@users.noreply.github.com> Date: Fri, 2 Jun 2023 14:35:54 -0500 Subject: [PATCH 054/310] use enum for `prefix` instead of `&str` --- clippy_lints/src/endian_bytes.rs | 61 ++++++++++++++------------------ 1 file changed, 27 insertions(+), 34 deletions(-) diff --git a/clippy_lints/src/endian_bytes.rs b/clippy_lints/src/endian_bytes.rs index 19fb74b9050..8328531deff 100644 --- a/clippy_lints/src/endian_bytes.rs +++ b/clippy_lints/src/endian_bytes.rs @@ -76,6 +76,11 @@ enum LintKind { Big, } +enum Prefix { + From, + To, +} + impl LintKind { fn allowed(&self, cx: &LateContext<'_>, expr: &Expr<'_>) -> bool { is_lint_allowed(cx, self.as_lint(), expr.hir_id) @@ -89,29 +94,13 @@ impl LintKind { } } - fn to_name(&self, prefix: &str) -> &str { + fn as_name(&self, prefix: &Prefix) -> &str { + let index = if matches!(prefix, Prefix::From) { 0 } else { 1 }; + match self { - LintKind::Host => { - if prefix == "from" { - HOST_NAMES[0] - } else { - HOST_NAMES[1] - } - }, - LintKind::Little => { - if prefix == "from" { - LITTLE_NAMES[0] - } else { - LITTLE_NAMES[1] - } - }, - LintKind::Big => { - if prefix == "from" { - BIG_NAMES[0] - } else { - BIG_NAMES[1] - } - }, + LintKind::Host => HOST_NAMES[index], + LintKind::Little => LITTLE_NAMES[index], + LintKind::Big => BIG_NAMES[index], } } } @@ -127,7 +116,7 @@ impl LateLintPass<'_> for EndianBytes { if args.is_empty(); let ty = cx.typeck_results().expr_ty(receiver); if ty.is_primitive_ty(); - if maybe_lint_endian_bytes(cx, expr, "to", method_name.ident.name, ty); + if maybe_lint_endian_bytes(cx, expr, &Prefix::To, method_name.ident.name, ty); then { return; } @@ -141,16 +130,16 @@ impl LateLintPass<'_> for EndianBytes { let ty = cx.typeck_results().expr_ty(expr); if ty.is_primitive_ty(); then { - maybe_lint_endian_bytes(cx, expr, "from", *function_name, ty); + maybe_lint_endian_bytes(cx, expr, &Prefix::From, *function_name, ty); } } } } -fn maybe_lint_endian_bytes(cx: &LateContext<'_>, expr: &Expr<'_>, prefix: &str, name: Symbol, ty: Ty<'_>) -> bool { - let ne = LintKind::Host.to_name(prefix); - let le = LintKind::Little.to_name(prefix); - let be = LintKind::Big.to_name(prefix); +fn maybe_lint_endian_bytes(cx: &LateContext<'_>, expr: &Expr<'_>, prefix: &Prefix, name: Symbol, ty: Ty<'_>) -> bool { + let ne = LintKind::Host.as_name(prefix); + let le = LintKind::Little.as_name(prefix); + let be = LintKind::Big.as_name(prefix); let (lint, other_lints) = match name.as_str() { name if name == ne => ((&LintKind::Host), [(&LintKind::Little), (&LintKind::Big)]), @@ -172,14 +161,14 @@ fn maybe_lint_endian_bytes(cx: &LateContext<'_>, expr: &Expr<'_>, prefix: &str, } // ne_bytes and all other lints allowed - if lint.to_name(prefix) == ne && other_lints.iter().all(|lint| lint.allowed(cx, expr)) { + if lint.as_name(prefix) == ne && other_lints.iter().all(|lint| lint.allowed(cx, expr)) { help = Some(Cow::Borrowed("specify the desired endianness explicitly")); break 'build_help; } // le_bytes where ne_bytes allowed but be_bytes is not, or le_bytes where ne_bytes allowed but // le_bytes is not - if (lint.to_name(prefix) == le || lint.to_name(prefix) == be) && LintKind::Host.allowed(cx, expr) { + if (lint.as_name(prefix) == le || lint.as_name(prefix) == be) && LintKind::Host.allowed(cx, expr) { help = Some(Cow::Borrowed("use the native endianness instead")); break 'build_help; } @@ -195,7 +184,7 @@ fn maybe_lint_endian_bytes(cx: &LateContext<'_>, expr: &Expr<'_>, prefix: &str, help_str.push_str("either of "); } - help_str.push_str(&format!("`{ty}::{}` ", lint.to_name(prefix))); + help_str.push_str(&format!("`{ty}::{}` ", lint.as_name(prefix))); if i != len && !only_one { help_str.push_str("or "); @@ -211,9 +200,13 @@ fn maybe_lint_endian_bytes(cx: &LateContext<'_>, expr: &Expr<'_>, prefix: &str, expr.span, &format!( "usage of the {}`{ty}::{}`{}", - if prefix == "from" { "function " } else { "" }, - lint.to_name(prefix), - if prefix == "to" { " method" } else { "" }, + if matches!(prefix, Prefix::From) { + "function " + } else { + "" + }, + lint.as_name(prefix), + if matches!(prefix, Prefix::To) { " method" } else { "" }, ), move |diag| { if let Some(help) = help { From b1a21ae347eac7f6ce5d3bfa368b8ae5fbf1a621 Mon Sep 17 00:00:00 2001 From: Centri3 <114838443+Centri3@users.noreply.github.com> Date: Fri, 2 Jun 2023 14:38:03 -0500 Subject: [PATCH 055/310] Update endian_bytes.rs --- clippy_lints/src/endian_bytes.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clippy_lints/src/endian_bytes.rs b/clippy_lints/src/endian_bytes.rs index 8328531deff..bc7dd8534c3 100644 --- a/clippy_lints/src/endian_bytes.rs +++ b/clippy_lints/src/endian_bytes.rs @@ -95,7 +95,7 @@ impl LintKind { } fn as_name(&self, prefix: &Prefix) -> &str { - let index = if matches!(prefix, Prefix::From) { 0 } else { 1 }; + let index = usize::from(matches!(prefix, Prefix::To)); match self { LintKind::Host => HOST_NAMES[index], From 2e4ef8e72c5e662cc9fe536ff019ab4d5802db84 Mon Sep 17 00:00:00 2001 From: Brian Hetro Date: Fri, 2 Jun 2023 22:57:04 -0400 Subject: [PATCH 056/310] Clippy Lints page - Fix path watch triggering --- util/gh-pages/script.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/util/gh-pages/script.js b/util/gh-pages/script.js index bd4293662a0..b961b7d2d96 100644 --- a/util/gh-pages/script.js +++ b/util/gh-pages/script.js @@ -270,7 +270,7 @@ }, true); // Watch for changes in the URL path and update the search and lint display - $scope.$watch($location.path, function (newPath) { + $scope.$watch(function () { return $location.path(); }, function (newPath) { const searchParameter = newPath.substring(1); if ($scope.search !== searchParameter) { $scope.search = searchParameter; @@ -292,12 +292,12 @@ } }); - $scope.$watch($location.search, function (newParameters) { + $scope.$watch(function () { return $location.search(); }, function (newParameters) { if (!internalURLChange) { loadFromURLParameters(); } internalURLChange = false; - }); + }, true); $scope.updatePath = function () { if (debounceTimeout) { From ac279efdbc5f4a0f1e8edaa629154db811428beb Mon Sep 17 00:00:00 2001 From: Brian Hetro Date: Fri, 2 Jun 2023 22:57:45 -0400 Subject: [PATCH 057/310] Clippy Lints page - Do not show filters in URL if configured as default values --- util/gh-pages/script.js | 58 +++++++++++++++++------------------------ 1 file changed, 24 insertions(+), 34 deletions(-) diff --git a/util/gh-pages/script.js b/util/gh-pages/script.js index b961b7d2d96..f59245e556c 100644 --- a/util/gh-pages/script.js +++ b/util/gh-pages/script.js @@ -156,10 +156,6 @@ Object.entries(versionFilterKeyMap).map(([key, value]) => [value, key]) ); - // An internal URL change occurs when we are modifying the URL parameters in a way - // that should not reload parameters from the URL - let internalURLChange = false; - // loadFromURLParameters retrieves filter settings from the URL parameters and assigns them // to corresponding $scope variables. function loadFromURLParameters() { @@ -211,29 +207,37 @@ $scope.open[searchParameter] = true; scrollToLintByURL($scope, $location); } - - // If there are any filters in the URL, mark that the filters have been changed - if (urlParameters.levels || urlParameters.groups || urlParameters.versions) { - $scope.filtersChanged = true; - } } // updateURLParameter updates the URL parameter with the given key to the given value - function updateURLParameter(filterObj, urlKey, processFilter = filter => filter) { + function updateURLParameter(filterObj, urlKey, defaultValue = {}, processFilter = filter => filter) { const parameter = Object.keys(filterObj) .filter(filter => filterObj[filter]) + .sort() .map(processFilter) .filter(Boolean) // Filters out any falsy values, including null .join(','); - $location.search(urlKey, parameter || null); + const defaultParameter = Object.keys(defaultValue) + .filter(filter => defaultValue[filter]) + .sort() + .map(processFilter) + .filter(Boolean) // Filters out any falsy values, including null + .join(','); + + // if we ended up back at the defaults, just remove it from the URL + if (parameter === defaultParameter) { + $location.search(urlKey, null); + } else { + $location.search(urlKey, parameter || null); + } } // updateVersionURLParameter updates the version URL parameter with the given version filters function updateVersionURLParameter(versionFilters) { updateURLParameter( versionFilters, - 'versions', + 'versions', {}, versionFilter => versionFilters[versionFilter].enabled && versionFilters[versionFilter].minorVersion != null ? `${versionFilterKeyMap[versionFilter]}:${versionFilters[versionFilter].minorVersion}` : null @@ -242,29 +246,26 @@ // updateAllURLParameters updates all the URL parameters with the current filter settings function updateAllURLParameters() { - updateURLParameter($scope.levels, 'levels'); - updateURLParameter($scope.groups, 'groups'); + updateURLParameter($scope.levels, 'levels', LEVEL_FILTERS_DEFAULT); + updateURLParameter($scope.groups, 'groups', GROUPS_FILTER_DEFAULT); updateVersionURLParameter($scope.versionFilters); } // Add $watches to automatically update URL parameters when the data changes $scope.$watch('levels', function (newVal, oldVal) { if (newVal !== oldVal) { - $scope.filtersChanged = true; - updateURLParameter(newVal, 'levels'); + updateURLParameter(newVal, 'levels', LEVEL_FILTERS_DEFAULT); } }, true); $scope.$watch('groups', function (newVal, oldVal) { if (newVal !== oldVal) { - $scope.filtersChanged = true; - updateURLParameter(newVal, 'groups'); + updateURLParameter(newVal, 'groups', GROUPS_FILTER_DEFAULT); } }, true); $scope.$watch('versionFilters', function (newVal, oldVal) { if (newVal !== oldVal) { - $scope.filtersChanged = true; updateVersionURLParameter(newVal); } }, true); @@ -293,10 +294,7 @@ }); $scope.$watch(function () { return $location.search(); }, function (newParameters) { - if (!internalURLChange) { - loadFromURLParameters(); - } - internalURLChange = false; + loadFromURLParameters(); }, true); $scope.updatePath = function () { @@ -330,12 +328,9 @@ }; $scope.resetGroupsToDefault = function () { - const groups = $scope.groups; - for (const [key, value] of Object.entries(GROUPS_FILTER_DEFAULT)) { - groups[key] = value; - } - internalURLChange = true; - $location.search('groups', null); + $scope.groups = { + ...GROUPS_FILTER_DEFAULT + }; }; $scope.selectedValuesCount = function (obj) { @@ -439,10 +434,6 @@ $scope.openLint = function (lint) { $scope.open[lint.id] = true; $location.path(lint.id); - if ($scope.filtersChanged) { - updateAllURLParameters(); - $scope.filtersChanged = false; - } }; $scope.copyToClipboard = function (lint) { @@ -469,7 +460,6 @@ // Get data $scope.open = {}; $scope.loading = true; - $scope.filtersChanged = false; // This will be used to jump into the source code of the version that this documentation is for. $scope.docVersion = window.location.pathname.split('/')[2] || "master"; From 5a7e33e5b25c6ee9b71897f2fd1a84d8c839dcf9 Mon Sep 17 00:00:00 2001 From: y21 <30553356+y21@users.noreply.github.com> Date: Sat, 3 Jun 2023 19:16:39 +0200 Subject: [PATCH 058/310] add plural form to useless_conversion if depth > 0 --- clippy_lints/src/useless_conversion.rs | 22 +++++++++++----------- tests/ui/useless_conversion.stderr | 10 +++++----- 2 files changed, 16 insertions(+), 16 deletions(-) diff --git a/clippy_lints/src/useless_conversion.rs b/clippy_lints/src/useless_conversion.rs index 6f1e9d5f9de..c413e92ea91 100644 --- a/clippy_lints/src/useless_conversion.rs +++ b/clippy_lints/src/useless_conversion.rs @@ -93,14 +93,13 @@ fn into_iter_call<'hir>(cx: &LateContext<'_>, expr: &'hir Expr<'hir>) -> Option< /// Same as [`into_iter_call`], but tries to look for the innermost `.into_iter()` call, e.g.: /// `foo.into_iter().into_iter()` /// ^^^ we want this expression -fn into_iter_deep_call<'hir>(cx: &LateContext<'_>, mut expr: &'hir Expr<'hir>) -> Option<&'hir Expr<'hir>> { - loop { - if let Some(recv) = into_iter_call(cx, expr) { - expr = recv; - } else { - return Some(expr); - } +fn into_iter_deep_call<'hir>(cx: &LateContext<'_>, mut expr: &'hir Expr<'hir>) -> (&'hir Expr<'hir>, usize) { + let mut depth = 0; + while let Some(recv) = into_iter_call(cx, expr) { + expr = recv; + depth += 1; } + (expr, depth) } #[expect(clippy::too_many_lines)] @@ -170,18 +169,19 @@ impl<'tcx> LateLintPass<'tcx> for UselessConversion { && let Some(&into_iter_param) = sig.inputs().get(kind.param_pos(arg_pos)) && let ty::Param(param) = into_iter_param.kind() && let Some(span) = into_iter_bound(cx, parent_fn_did, into_iter_did, param.index) + { // Get the "innermost" `.into_iter()` call, e.g. given this expression: // `foo.into_iter().into_iter()` // ^^^ - // We want this span - && let Some(into_iter_recv) = into_iter_deep_call(cx, into_iter_recv) - { + let (into_iter_recv, depth) = into_iter_deep_call(cx, into_iter_recv); + + let plural = if depth == 0 { "" } else { "s" }; let mut applicability = Applicability::MachineApplicable; let sugg = snippet_with_applicability(cx, into_iter_recv.span.source_callsite(), "", &mut applicability).into_owned(); span_lint_and_then(cx, USELESS_CONVERSION, e.span, "explicit call to `.into_iter()` in function argument accepting `IntoIterator`", |diag| { diag.span_suggestion( e.span, - "consider removing `.into_iter()`", + format!("consider removing the `.into_iter()`{plural}"), sugg, applicability, ); diff --git a/tests/ui/useless_conversion.stderr b/tests/ui/useless_conversion.stderr index 68f38faab59..4957f73a469 100644 --- a/tests/ui/useless_conversion.stderr +++ b/tests/ui/useless_conversion.stderr @@ -122,7 +122,7 @@ error: explicit call to `.into_iter()` in function argument accepting `IntoItera --> $DIR/useless_conversion.rs:171:7 | LL | b(vec![1, 2].into_iter()); - | ^^^^^^^^^^^^^^^^^^^^^^ help: consider removing `.into_iter()`: `vec![1, 2]` + | ^^^^^^^^^^^^^^^^^^^^^^ help: consider removing the `.into_iter()`: `vec![1, 2]` | note: this parameter accepts any `IntoIterator`, so you don't need to call `.into_iter()` --> $DIR/useless_conversion.rs:161:13 @@ -134,7 +134,7 @@ error: explicit call to `.into_iter()` in function argument accepting `IntoItera --> $DIR/useless_conversion.rs:172:7 | LL | c(vec![1, 2].into_iter()); - | ^^^^^^^^^^^^^^^^^^^^^^ help: consider removing `.into_iter()`: `vec![1, 2]` + | ^^^^^^^^^^^^^^^^^^^^^^ help: consider removing the `.into_iter()`: `vec![1, 2]` | note: this parameter accepts any `IntoIterator`, so you don't need to call `.into_iter()` --> $DIR/useless_conversion.rs:162:18 @@ -146,7 +146,7 @@ error: explicit call to `.into_iter()` in function argument accepting `IntoItera --> $DIR/useless_conversion.rs:173:7 | LL | d(vec![1, 2].into_iter()); - | ^^^^^^^^^^^^^^^^^^^^^^ help: consider removing `.into_iter()`: `vec![1, 2]` + | ^^^^^^^^^^^^^^^^^^^^^^ help: consider removing the `.into_iter()`: `vec![1, 2]` | note: this parameter accepts any `IntoIterator`, so you don't need to call `.into_iter()` --> $DIR/useless_conversion.rs:165:12 @@ -158,7 +158,7 @@ error: explicit call to `.into_iter()` in function argument accepting `IntoItera --> $DIR/useless_conversion.rs:176:7 | LL | b(vec![1, 2].into_iter().into_iter()); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider removing `.into_iter()`: `vec![1, 2]` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider removing the `.into_iter()`s: `vec![1, 2]` | note: this parameter accepts any `IntoIterator`, so you don't need to call `.into_iter()` --> $DIR/useless_conversion.rs:161:13 @@ -170,7 +170,7 @@ error: explicit call to `.into_iter()` in function argument accepting `IntoItera --> $DIR/useless_conversion.rs:177:7 | LL | b(vec![1, 2].into_iter().into_iter().into_iter()); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider removing `.into_iter()`: `vec![1, 2]` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider removing the `.into_iter()`s: `vec![1, 2]` | note: this parameter accepts any `IntoIterator`, so you don't need to call `.into_iter()` --> $DIR/useless_conversion.rs:161:13 From 7fe200ed0586b690cc6a0981fa4e7b74c248e273 Mon Sep 17 00:00:00 2001 From: Centri3 <114838443+Centri3@users.noreply.github.com> Date: Sat, 3 Jun 2023 14:31:40 -0500 Subject: [PATCH 059/310] derive Copy/PartialEq for `Prefix` --- clippy_lints/src/endian_bytes.rs | 19 ++++++++----------- 1 file changed, 8 insertions(+), 11 deletions(-) diff --git a/clippy_lints/src/endian_bytes.rs b/clippy_lints/src/endian_bytes.rs index bc7dd8534c3..f470987833e 100644 --- a/clippy_lints/src/endian_bytes.rs +++ b/clippy_lints/src/endian_bytes.rs @@ -76,6 +76,7 @@ enum LintKind { Big, } +#[derive(Clone, Copy, PartialEq)] enum Prefix { From, To, @@ -94,8 +95,8 @@ impl LintKind { } } - fn as_name(&self, prefix: &Prefix) -> &str { - let index = usize::from(matches!(prefix, Prefix::To)); + fn as_name(&self, prefix: Prefix) -> &str { + let index = usize::from(prefix == Prefix::To); match self { LintKind::Host => HOST_NAMES[index], @@ -116,7 +117,7 @@ impl LateLintPass<'_> for EndianBytes { if args.is_empty(); let ty = cx.typeck_results().expr_ty(receiver); if ty.is_primitive_ty(); - if maybe_lint_endian_bytes(cx, expr, &Prefix::To, method_name.ident.name, ty); + if maybe_lint_endian_bytes(cx, expr, Prefix::To, method_name.ident.name, ty); then { return; } @@ -130,13 +131,13 @@ impl LateLintPass<'_> for EndianBytes { let ty = cx.typeck_results().expr_ty(expr); if ty.is_primitive_ty(); then { - maybe_lint_endian_bytes(cx, expr, &Prefix::From, *function_name, ty); + maybe_lint_endian_bytes(cx, expr, Prefix::From, *function_name, ty); } } } } -fn maybe_lint_endian_bytes(cx: &LateContext<'_>, expr: &Expr<'_>, prefix: &Prefix, name: Symbol, ty: Ty<'_>) -> bool { +fn maybe_lint_endian_bytes(cx: &LateContext<'_>, expr: &Expr<'_>, prefix: Prefix, name: Symbol, ty: Ty<'_>) -> bool { let ne = LintKind::Host.as_name(prefix); let le = LintKind::Little.as_name(prefix); let be = LintKind::Big.as_name(prefix); @@ -200,13 +201,9 @@ fn maybe_lint_endian_bytes(cx: &LateContext<'_>, expr: &Expr<'_>, prefix: &Prefi expr.span, &format!( "usage of the {}`{ty}::{}`{}", - if matches!(prefix, Prefix::From) { - "function " - } else { - "" - }, + if prefix == Prefix::From { "function " } else { "" }, lint.as_name(prefix), - if matches!(prefix, Prefix::To) { " method" } else { "" }, + if prefix == Prefix::To { " method" } else { "" }, ), move |diag| { if let Some(help) = help { From 05bfcbd9113e3f06adcbfdb773e839dfe2ec205b Mon Sep 17 00:00:00 2001 From: Centri3 <114838443+Centri3@users.noreply.github.com> Date: Sat, 3 Jun 2023 14:38:16 -0500 Subject: [PATCH 060/310] remove tuple --- clippy_lints/src/allow_attributes.rs | 6 +++--- clippy_lints/src/attrs.rs | 4 ++-- clippy_utils/src/check_proc_macro.rs | 7 ++++--- 3 files changed, 9 insertions(+), 8 deletions(-) diff --git a/clippy_lints/src/allow_attributes.rs b/clippy_lints/src/allow_attributes.rs index 69ccbeb7b06..eb21184713e 100644 --- a/clippy_lints/src/allow_attributes.rs +++ b/clippy_lints/src/allow_attributes.rs @@ -1,4 +1,4 @@ -use ast::AttrStyle; +use ast::{AttrStyle, Attribute}; use clippy_utils::{diagnostics::span_lint_and_sugg, is_from_proc_macro}; use rustc_ast as ast; use rustc_errors::Applicability; @@ -50,14 +50,14 @@ declare_lint_pass!(AllowAttribute => [ALLOW_ATTRIBUTES]); impl LateLintPass<'_> for AllowAttribute { // Separate each crate's features. - fn check_attribute(&mut self, cx: &LateContext<'_>, attr: &ast::Attribute) { + fn check_attribute<'cx>(&mut self, cx: &LateContext<'cx>, attr: &'cx 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(); if ident.name == rustc_span::symbol::sym::allow; - if !is_from_proc_macro(cx, &(attr, cx)); + if !is_from_proc_macro(cx, &attr); then { span_lint_and_sugg( cx, diff --git a/clippy_lints/src/attrs.rs b/clippy_lints/src/attrs.rs index e989cde0f3c..b882eee8a65 100644 --- a/clippy_lints/src/attrs.rs +++ b/clippy_lints/src/attrs.rs @@ -543,7 +543,7 @@ fn check_clippy_lint_names(cx: &LateContext<'_>, name: Symbol, items: &[NestedMe } } -fn check_lint_reason(cx: &LateContext<'_>, name: Symbol, items: &[NestedMetaItem], attr: &Attribute) { +fn check_lint_reason<'cx>(cx: &LateContext<'cx>, name: Symbol, items: &[NestedMetaItem], attr: &'cx Attribute) { // Check for the feature if !cx.tcx.features().lint_reasons { return; @@ -558,7 +558,7 @@ fn check_lint_reason(cx: &LateContext<'_>, name: Symbol, items: &[NestedMetaItem } // Check if the attribute is in an external macro and therefore out of the developer's control - if in_external_macro(cx.sess(), attr.span) || is_from_proc_macro(cx, &(attr, cx)) { + if in_external_macro(cx.sess(), attr.span) || is_from_proc_macro(cx, &attr) { return; } diff --git a/clippy_utils/src/check_proc_macro.rs b/clippy_utils/src/check_proc_macro.rs index fd04f2ddf7c..7e954898460 100644 --- a/clippy_utils/src/check_proc_macro.rs +++ b/clippy_utils/src/check_proc_macro.rs @@ -358,15 +358,16 @@ impl<'cx> WithSearchPat for (&FnKind<'cx>, &Body<'cx>, HirId, Span) { } } -impl<'cx> WithSearchPat for (&Attribute, &LateContext<'cx>) { +// `Attribute` does not have the `hir` associated lifetime, so we cannot use the macro +impl<'cx> WithSearchPat for &'cx Attribute { type Context = LateContext<'cx>; fn search_pat(&self, _cx: &Self::Context) -> (Pat, Pat) { - attr_search_pat(self.0) + attr_search_pat(self) } fn span(&self) -> Span { - self.0.span + self.span } } From 70553711ae3cc3670d3921140b296a007493f8f0 Mon Sep 17 00:00:00 2001 From: Centri3 <114838443+Centri3@users.noreply.github.com> Date: Sat, 3 Jun 2023 18:34:12 -0500 Subject: [PATCH 061/310] add test for `?` desugaring --- tests/ui/allow_attributes_without_reason.rs | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/tests/ui/allow_attributes_without_reason.rs b/tests/ui/allow_attributes_without_reason.rs index 95a9fa2aa47..2b26624b424 100644 --- a/tests/ui/allow_attributes_without_reason.rs +++ b/tests/ui/allow_attributes_without_reason.rs @@ -28,3 +28,17 @@ fn main() { fn b() {} } } + +// Make sure this is not triggered on `?` desugaring + +pub fn trigger_fp_option() -> Option<()>{ + Some(())?; + None?; + Some(()) +} + +pub fn trigger_fp_result() -> Result<(), &'static str> { + Ok(())?; + Err("asdf")?; + Ok(()) +} From b469e8ce218cc48b723aa0e49f53b1690eee23d1 Mon Sep 17 00:00:00 2001 From: Centri3 <114838443+Centri3@users.noreply.github.com> Date: Sat, 3 Jun 2023 18:35:53 -0500 Subject: [PATCH 062/310] Update allow_attributes_without_reason.rs --- tests/ui/allow_attributes_without_reason.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/ui/allow_attributes_without_reason.rs b/tests/ui/allow_attributes_without_reason.rs index 2b26624b424..663c2eb2c37 100644 --- a/tests/ui/allow_attributes_without_reason.rs +++ b/tests/ui/allow_attributes_without_reason.rs @@ -31,7 +31,7 @@ fn main() { // Make sure this is not triggered on `?` desugaring -pub fn trigger_fp_option() -> Option<()>{ +pub fn trigger_fp_option() -> Option<()> { Some(())?; None?; Some(()) From 33b241dc7f0131e652ef23a20a0d25b4c72e054f Mon Sep 17 00:00:00 2001 From: Alex Macleod Date: Sun, 4 Jun 2023 18:01:56 +0000 Subject: [PATCH 063/310] Remove `CARGO_UNSTABLE_SPARSE_REGISTRY` env from ci It is now the default to use the sparse registry --- .github/workflows/clippy.yml | 1 - .github/workflows/clippy_bors.yml | 1 - .github/workflows/clippy_dev.yml | 1 - 3 files changed, 3 deletions(-) diff --git a/.github/workflows/clippy.yml b/.github/workflows/clippy.yml index a9d42159c4b..c582c28cd3c 100644 --- a/.github/workflows/clippy.yml +++ b/.github/workflows/clippy.yml @@ -25,7 +25,6 @@ env: CARGO_TARGET_DIR: '${{ github.workspace }}/target' NO_FMT_TEST: 1 CARGO_INCREMENTAL: 0 - CARGO_UNSTABLE_SPARSE_REGISTRY: true jobs: base: diff --git a/.github/workflows/clippy_bors.yml b/.github/workflows/clippy_bors.yml index 30a156c925b..d5ab313ba0e 100644 --- a/.github/workflows/clippy_bors.yml +++ b/.github/workflows/clippy_bors.yml @@ -11,7 +11,6 @@ env: CARGO_TARGET_DIR: '${{ github.workspace }}/target' NO_FMT_TEST: 1 CARGO_INCREMENTAL: 0 - CARGO_UNSTABLE_SPARSE_REGISTRY: true defaults: run: diff --git a/.github/workflows/clippy_dev.yml b/.github/workflows/clippy_dev.yml index 514706d64c8..0f0e3f2db92 100644 --- a/.github/workflows/clippy_dev.yml +++ b/.github/workflows/clippy_dev.yml @@ -16,7 +16,6 @@ on: env: RUST_BACKTRACE: 1 CARGO_INCREMENTAL: 0 - CARGO_UNSTABLE_SPARSE_REGISTRY: true jobs: clippy_dev: From e24fc9af23e8b83eb392227551a5a9e217202b19 Mon Sep 17 00:00:00 2001 From: Centri3 <114838443+Centri3@users.noreply.github.com> Date: Sun, 4 Jun 2023 21:50:51 -0500 Subject: [PATCH 064/310] Fix `missing_const_for_fn` not checking `~const Destruct` --- clippy_utils/src/qualify_min_const_fn.rs | 33 +++++++++++++++++-- .../ui/missing_const_for_fn/cant_be_const.rs | 9 +++++ 2 files changed, 39 insertions(+), 3 deletions(-) diff --git a/clippy_utils/src/qualify_min_const_fn.rs b/clippy_utils/src/qualify_min_const_fn.rs index c0d2c835d63..a38045cdcd1 100644 --- a/clippy_utils/src/qualify_min_const_fn.rs +++ b/clippy_utils/src/qualify_min_const_fn.rs @@ -52,13 +52,14 @@ pub fn is_min_const_fn<'tcx>(tcx: TyCtxt<'tcx>, body: &Body<'tcx>, msrv: &Msrv) } for local in &body.local_decls { - check_ty(tcx, local.ty, local.source_info.span)?; + check_ty(tcx, local.ty, local.source_info.span, false)?; } // impl trait is gone in MIR, so check the return type manually check_ty( tcx, tcx.fn_sig(def_id).subst_identity().output().skip_binder(), body.local_decls.iter().next().unwrap().source_info.span, + false, )?; for bb in body.basic_blocks.iter() { @@ -70,7 +71,7 @@ pub fn is_min_const_fn<'tcx>(tcx: TyCtxt<'tcx>, body: &Body<'tcx>, msrv: &Msrv) Ok(()) } -fn check_ty<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>, span: Span) -> McfResult { +fn check_ty<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>, span: Span, in_drop: bool) -> McfResult { for arg in ty.walk() { let ty = match arg.unpack() { GenericArgKind::Type(ty) => ty, @@ -80,6 +81,27 @@ fn check_ty<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>, span: Span) -> McfResult { GenericArgKind::Lifetime(_) | GenericArgKind::Const(_) => continue, }; + // Only do this check if we're in `TerminatorKind::Drop`, otherwise rustc will sometimes overflow + // its stack. This check is unnecessary outside of a `Drop` anyway so it's faster regardless + if in_drop && let ty::Adt(def, subst) = ty.kind() { + if def.has_non_const_dtor(tcx) && in_drop { + return Err(( + span, + "cannot drop locals with a non constant destructor in const fn".into(), + )); + } + + for fields in def.variants().iter().map(|v| &v.fields) { + for field in fields { + check_ty(tcx, field.ty(tcx, subst), span, in_drop)?; + } + } + + for field in def.all_fields() { + check_ty(tcx, field.ty(tcx, subst), span, in_drop)?; + } + } + match ty.kind() { ty::Ref(_, _, hir::Mutability::Mut) => { return Err((span, "mutable references in const fn are unstable".into())); @@ -306,7 +328,12 @@ fn check_terminator<'tcx>( | TerminatorKind::Terminate | TerminatorKind::Unreachable => Ok(()), - TerminatorKind::Drop { place, .. } => check_place(tcx, *place, span, body), + TerminatorKind::Drop { place, .. } => { + for local in &body.local_decls { + check_ty(tcx, local.ty, span, true)?; + } + check_place(tcx, *place, span, body) + }, TerminatorKind::SwitchInt { discr, targets: _ } => check_operand(tcx, discr, span, body), 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 5db73a7b8ea..dffc23177d1 100644 --- a/tests/ui/missing_const_for_fn/cant_be_const.rs +++ b/tests/ui/missing_const_for_fn/cant_be_const.rs @@ -126,3 +126,12 @@ with_span! { span fn dont_check_in_proc_macro() {} } + +fn a(this: String) {} + +enum A { + F(String), + N, +} + +fn b(this: A) {} From 01b105725888cab56ef240331b7c32e88ce24121 Mon Sep 17 00:00:00 2001 From: Alessio Cosenza Date: Wed, 29 Mar 2023 00:49:43 +0200 Subject: [PATCH 065/310] Add redundant type annotations lint --- CHANGELOG.md | 1 + clippy_lints/src/declared_lints.rs | 1 + clippy_lints/src/lib.rs | 2 + .../src/redundant_type_annotations.rs | 185 ++++++++++++++++++ tests/ui/redundant_type_annotations.rs | 160 +++++++++++++++ tests/ui/redundant_type_annotations.stderr | 94 +++++++++ 6 files changed, 443 insertions(+) create mode 100644 clippy_lints/src/redundant_type_annotations.rs create mode 100644 tests/ui/redundant_type_annotations.rs create mode 100644 tests/ui/redundant_type_annotations.stderr diff --git a/CHANGELOG.md b/CHANGELOG.md index 4648af231a4..a65ac4d46de 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5110,6 +5110,7 @@ Released 2018-09-13 [`redundant_pub_crate`]: https://rust-lang.github.io/rust-clippy/master/index.html#redundant_pub_crate [`redundant_slicing`]: https://rust-lang.github.io/rust-clippy/master/index.html#redundant_slicing [`redundant_static_lifetimes`]: https://rust-lang.github.io/rust-clippy/master/index.html#redundant_static_lifetimes +[`redundant_type_annotations`]: https://rust-lang.github.io/rust-clippy/master/index.html#redundant_type_annotations [`ref_binding_to_reference`]: https://rust-lang.github.io/rust-clippy/master/index.html#ref_binding_to_reference [`ref_in_deref`]: https://rust-lang.github.io/rust-clippy/master/index.html#ref_in_deref [`ref_option_ref`]: https://rust-lang.github.io/rust-clippy/master/index.html#ref_option_ref diff --git a/clippy_lints/src/declared_lints.rs b/clippy_lints/src/declared_lints.rs index 68272e1a77a..d014534cee9 100644 --- a/clippy_lints/src/declared_lints.rs +++ b/clippy_lints/src/declared_lints.rs @@ -543,6 +543,7 @@ pub(crate) static LINTS: &[&crate::LintInfo] = &[ crate::redundant_slicing::DEREF_BY_SLICING_INFO, crate::redundant_slicing::REDUNDANT_SLICING_INFO, crate::redundant_static_lifetimes::REDUNDANT_STATIC_LIFETIMES_INFO, + crate::redundant_type_annotations::REDUNDANT_TYPE_ANNOTATIONS_INFO, crate::ref_option_ref::REF_OPTION_REF_INFO, crate::ref_patterns::REF_PATTERNS_INFO, crate::reference::DEREF_ADDROF_INFO, diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index 222b0cc0921..d53c6de5451 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -267,6 +267,7 @@ mod redundant_field_names; mod redundant_pub_crate; mod redundant_slicing; mod redundant_static_lifetimes; +mod redundant_type_annotations; mod ref_option_ref; mod ref_patterns; mod reference; @@ -1012,6 +1013,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: store.register_early_pass(|| Box::new(needless_else::NeedlessElse)); store.register_late_pass(|_| Box::new(missing_fields_in_debug::MissingFieldsInDebug)); store.register_late_pass(|_| Box::new(endian_bytes::EndianBytes)); + store.register_late_pass(|_| Box::new(redundant_type_annotations::RedundantTypeAnnotations)); // add lints here, do not remove this comment, it's used in `new_lint` } diff --git a/clippy_lints/src/redundant_type_annotations.rs b/clippy_lints/src/redundant_type_annotations.rs new file mode 100644 index 00000000000..30d06a2cbc7 --- /dev/null +++ b/clippy_lints/src/redundant_type_annotations.rs @@ -0,0 +1,185 @@ +use clippy_utils::diagnostics::span_lint; +use rustc_ast::LitKind; +use rustc_hir as hir; +use rustc_lint::{LateContext, LateLintPass}; +use rustc_middle::ty::Ty; +use rustc_session::{declare_lint_pass, declare_tool_lint}; + +declare_clippy_lint! { + /// ### What it does + /// Warns about needless / redundant type annotations. + /// + /// ### Why is this bad? + /// Code without type annotations is shorter and in most cases + /// more idiomatic and easier to modify. + /// + /// ### Example + /// ```rust + /// let foo: String = String::new(); + /// ``` + /// Use instead: + /// ```rust + /// let foo = String::new(); + /// ``` + #[clippy::version = "1.70.0"] + pub REDUNDANT_TYPE_ANNOTATIONS, + pedantic, + "warns about needless / redundant type annotations." +} +declare_lint_pass!(RedundantTypeAnnotations => [REDUNDANT_TYPE_ANNOTATIONS]); + +fn is_same_type<'tcx>(cx: &LateContext<'tcx>, ty_resolved_path: hir::def::Res, func_return_type: Ty<'tcx>) -> bool { + // type annotation is primitive + if let hir::def::Res::PrimTy(primty) = ty_resolved_path + && func_return_type.is_primitive() + && let Some(func_return_type_sym) = func_return_type.primitive_symbol() + { + return primty.name() == func_return_type_sym; + } + + // type annotation is any other non generic type + if let hir::def::Res::Def(_, defid) = ty_resolved_path + && let Some(annotation_ty) = cx.tcx.type_of(defid).no_bound_vars() + { + return annotation_ty == func_return_type; + } + + false +} + +fn func_hir_id_to_func_ty<'tcx>(cx: &LateContext<'tcx>, hir_id: hir::hir_id::HirId) -> Option> { + if let Some((defkind, func_defid)) = cx.typeck_results().type_dependent_def(hir_id) + && defkind == hir::def::DefKind::AssocFn + && let Some(init_ty) = cx.tcx.type_of(func_defid).no_bound_vars() + { + Some(init_ty) + } else { + None + } +} + +fn func_ty_to_return_type<'tcx>(cx: &LateContext<'tcx>, func_ty: Ty<'tcx>) -> Option> { + if func_ty.is_fn() + && let Some(return_type) = func_ty.fn_sig(cx.tcx).output().no_bound_vars() + { + Some(return_type) + } else { + None + } +} + +/// Extracts the fn Ty, e.g. `fn() -> std::string::String {f}` +fn extract_fn_ty<'tcx>( + cx: &LateContext<'tcx>, + call: &hir::Expr<'tcx>, + func_return_path: &hir::QPath<'tcx>, +) -> Option> { + match func_return_path { + // let a: String = f(); where f: fn f() -> String + hir::QPath::Resolved(_, resolved_path) => { + if let hir::def::Res::Def(_, defid) = resolved_path.res + && let Some(middle_ty_init) = cx.tcx.type_of(defid).no_bound_vars() + { + Some(middle_ty_init) + } else { + None + } + }, + // Associated functions like + // let a: String = String::new(); + // let a: String = String::get_string(); + hir::QPath::TypeRelative(..) => func_hir_id_to_func_ty(cx, call.hir_id), + hir::QPath::LangItem(..) => None, + } +} + +fn is_redundant_in_func_call<'tcx>( + cx: &LateContext<'tcx>, + ty_resolved_path: hir::def::Res, + call: &hir::Expr<'tcx>, +) -> bool { + if let hir::ExprKind::Path(init_path) = &call.kind { + let func_type = extract_fn_ty(cx, call, init_path); + + if let Some(func_type) = func_type + && let Some(init_return_type) = func_ty_to_return_type(cx, func_type) + { + return is_same_type(cx, ty_resolved_path, init_return_type); + } + } + + false +} + +impl LateLintPass<'_> for RedundantTypeAnnotations { + fn check_local<'tcx>(&mut self, cx: &LateContext<'tcx>, local: &'tcx rustc_hir::Local<'tcx>) { + // type annotation part + if !local.span.from_expansion() + && let Some(ty) = &local.ty + + // initialization part + && let Some(init) = local.init + { + match &init.kind { + // When the initialization is a call to a function + hir::ExprKind::Call(init_call, _) => { + if let hir::TyKind::Path(ty_path) = &ty.kind + && let hir::QPath::Resolved(_, resolved_path_ty) = ty_path + + && is_redundant_in_func_call(cx, resolved_path_ty.res, init_call) { + span_lint(cx, REDUNDANT_TYPE_ANNOTATIONS, local.span, "redundant type annotation"); + } + }, + hir::ExprKind::MethodCall(_, _, _, _) => { + if let hir::TyKind::Path(ty_path) = &ty.kind + && let hir::QPath::Resolved(_, resolved_path_ty) = ty_path + + && let Some(func_ty) = func_hir_id_to_func_ty(cx, init.hir_id) + && let Some(return_type) = func_ty_to_return_type(cx, func_ty) + && is_same_type(cx, resolved_path_ty.res, return_type) + { + span_lint(cx, REDUNDANT_TYPE_ANNOTATIONS, local.span, "redundant type annotation"); + } + }, + // When the initialization is a path for example u32::MAX + hir::ExprKind::Path(init_path) => { + // TODO: check for non primty + if let hir::TyKind::Path(ty_path) = &ty.kind + && let hir::QPath::Resolved(_, resolved_path_ty) = ty_path + && let hir::def::Res::PrimTy(primty) = resolved_path_ty.res + + && let hir::QPath::TypeRelative(init_ty, _) = init_path + && let hir::TyKind::Path(init_ty_path) = &init_ty.kind + && let hir::QPath::Resolved(_, resolved_init_ty_path) = init_ty_path + && let hir::def::Res::PrimTy(primty_init) = resolved_init_ty_path.res + + && primty == primty_init + { + span_lint(cx, REDUNDANT_TYPE_ANNOTATIONS, local.span, "redundant type annotation"); + } + }, + hir::ExprKind::Lit(init_lit) => { + match init_lit.node { + // In these cases the annotation is redundant + LitKind::Str(..) + | LitKind::ByteStr(..) + | LitKind::Byte(..) + | LitKind::Char(..) + | LitKind::Bool(..) + | LitKind::CStr(..) => { + span_lint(cx, REDUNDANT_TYPE_ANNOTATIONS, local.span, "redundant type annotation"); + }, + LitKind::Int(..) | LitKind::Float(..) => { + // If the initialization value is a suffixed literal we lint + if init_lit.node.is_suffixed() { + span_lint(cx, REDUNDANT_TYPE_ANNOTATIONS, local.span, "redundant type annotation"); + } + }, + LitKind::Err => (), + } + } + _ => () + } + }; + } +} diff --git a/tests/ui/redundant_type_annotations.rs b/tests/ui/redundant_type_annotations.rs new file mode 100644 index 00000000000..5722621e83a --- /dev/null +++ b/tests/ui/redundant_type_annotations.rs @@ -0,0 +1,160 @@ +#![allow(unused)] +#![warn(clippy::redundant_type_annotations)] + +#[derive(Debug, Default)] +struct Cake { + _data: T, +} + +fn make_something() -> T { + T::default() +} + +fn make_cake() -> Cake { + Cake::::default() +} + +fn plus_one>(val: T) -> T { + val + 1 +} + +struct Pie { + inner: u32, +} + +enum Pizza { + One, + Two, +} + +fn return_a_string() -> String { + String::new() +} + +fn return_a_struct() -> Pie { + Pie { inner: 5 } +} + +fn return_an_enum() -> Pizza { + Pizza::One +} + +fn return_an_int() -> u32 { + 5 +} + +impl Pie { + fn return_an_int(&self) -> u32 { + self.inner + } + + fn associated_return_an_int() -> u32 { + 5 + } + + fn new() -> Self { + Self { inner: 5 } + } + + fn associated_return_a_string() -> String { + String::from("") + } + + fn test_method_call(&self) { + let v: u32 = self.return_an_int(); // Should lint + } +} + +fn test_generics() { + // The type annotation is needed to determine T + let _c: Cake = make_something(); + + // The type annotation is needed to determine the topic + let _c: Cake = make_cake(); + + // This should lint (doesn't) + let _c: Cake = make_cake::(); + + // This should lint (doesn't) + let _c: u8 = make_something::(); + + // This should lint (doesn't) + let _c: u8 = plus_one(5_u8); + + // Annotation needed otherwise T is i32 + let _c: u8 = plus_one(5); +} + +fn test_non_locals() { + // This shouldn't lint + fn _arg(x: u32) -> u32 { + x + } + + // This could lint, but probably shouldn't + let _closure_arg = |x: u32| x; +} + +fn test_complex_types() { + // Shouldn't lint, since the literal will be i32 otherwise + let _u8: u8 = 128; + + // Should lint (doesn't) + let _tuple_i32: (i32, i32) = (12, 13); + + // Shouldn't lint, since the tuple will be i32 otherwise + let _tuple_u32: (u32, u32) = (1, 2); + + // Should lint, since the type is determined by the init value (doesn't) + let _tuple_u32: (u32, u32) = (3_u32, 4_u32); + + // Should lint (doesn't) + let _array: [i32; 3] = [5, 6, 7]; + + // Shouldn't lint + let _array: [u32; 2] = [8, 9]; +} + +fn test_functions() { + // Everything here should lint + + let _return: String = return_a_string(); + + let _return: Pie = return_a_struct(); + + let _return: Pizza = return_an_enum(); + + let _return: u32 = return_an_int(); + + let _return: String = String::new(); + + let new_pie: Pie = Pie::new(); + + let _return: u32 = new_pie.return_an_int(); + + let _return: String = String::from("test"); + + let _return: u32 = Pie::associated_return_an_int(); + + let _return: String = Pie::associated_return_a_string(); +} + +fn test_simple_types() { + let _var: u32 = u32::MAX; + + // Should lint + let _var: u32 = 5_u32; + + // Should lint + let _var: &str = "test"; + + // Should lint + let _var: &[u8] = b"test"; + + // Should lint + let _var: bool = false; +} + +fn main() {} + +// TODO: test refs diff --git a/tests/ui/redundant_type_annotations.stderr b/tests/ui/redundant_type_annotations.stderr new file mode 100644 index 00000000000..3356f480860 --- /dev/null +++ b/tests/ui/redundant_type_annotations.stderr @@ -0,0 +1,94 @@ +error: redundant type annotation + --> $DIR/redundant_type_annotations.rs:64:9 + | +LL | let v: u32 = self.return_an_int(); // Should lint + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: `-D clippy::redundant-type-annotations` implied by `-D warnings` + +error: redundant type annotation + --> $DIR/redundant_type_annotations.rs:121:5 + | +LL | let _return: String = return_a_string(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: redundant type annotation + --> $DIR/redundant_type_annotations.rs:123:5 + | +LL | let _return: Pie = return_a_struct(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: redundant type annotation + --> $DIR/redundant_type_annotations.rs:125:5 + | +LL | let _return: Pizza = return_an_enum(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: redundant type annotation + --> $DIR/redundant_type_annotations.rs:127:5 + | +LL | let _return: u32 = return_an_int(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: redundant type annotation + --> $DIR/redundant_type_annotations.rs:129:5 + | +LL | let _return: String = String::new(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: redundant type annotation + --> $DIR/redundant_type_annotations.rs:131:5 + | +LL | let new_pie: Pie = Pie::new(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: redundant type annotation + --> $DIR/redundant_type_annotations.rs:133:5 + | +LL | let _return: u32 = new_pie.return_an_int(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: redundant type annotation + --> $DIR/redundant_type_annotations.rs:137:5 + | +LL | let _return: u32 = Pie::associated_return_an_int(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: redundant type annotation + --> $DIR/redundant_type_annotations.rs:139:5 + | +LL | let _return: String = Pie::associated_return_a_string(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: redundant type annotation + --> $DIR/redundant_type_annotations.rs:143:5 + | +LL | let _var: u32 = u32::MAX; + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: redundant type annotation + --> $DIR/redundant_type_annotations.rs:146:5 + | +LL | let _var: u32 = 5_u32; + | ^^^^^^^^^^^^^^^^^^^^^^ + +error: redundant type annotation + --> $DIR/redundant_type_annotations.rs:149:5 + | +LL | let _var: &str = "test"; + | ^^^^^^^^^^^^^^^^^^^^^^^^ + +error: redundant type annotation + --> $DIR/redundant_type_annotations.rs:152:5 + | +LL | let _var: &[u8] = b"test"; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: redundant type annotation + --> $DIR/redundant_type_annotations.rs:155:5 + | +LL | let _var: bool = false; + | ^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 15 previous errors + From 6776608f21a14fdc9ca3751cdac6ade48b3f0346 Mon Sep 17 00:00:00 2001 From: Alessio Cosenza Date: Tue, 25 Apr 2023 00:28:17 +0200 Subject: [PATCH 066/310] Move `redundant_type_annotations` to restriction --- clippy_lints/src/redundant_type_annotations.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clippy_lints/src/redundant_type_annotations.rs b/clippy_lints/src/redundant_type_annotations.rs index 30d06a2cbc7..f277adfa94d 100644 --- a/clippy_lints/src/redundant_type_annotations.rs +++ b/clippy_lints/src/redundant_type_annotations.rs @@ -23,7 +23,7 @@ declare_clippy_lint! { /// ``` #[clippy::version = "1.70.0"] pub REDUNDANT_TYPE_ANNOTATIONS, - pedantic, + restriction, "warns about needless / redundant type annotations." } declare_lint_pass!(RedundantTypeAnnotations => [REDUNDANT_TYPE_ANNOTATIONS]); From 6f26df1c9a2ca1e4d161c49733c460fd32fddb02 Mon Sep 17 00:00:00 2001 From: Alessio Cosenza Date: Fri, 19 May 2023 17:45:49 +0200 Subject: [PATCH 067/310] Extract common logic to function --- .../src/redundant_type_annotations.rs | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/clippy_lints/src/redundant_type_annotations.rs b/clippy_lints/src/redundant_type_annotations.rs index f277adfa94d..da139cdde92 100644 --- a/clippy_lints/src/redundant_type_annotations.rs +++ b/clippy_lints/src/redundant_type_annotations.rs @@ -111,6 +111,17 @@ fn is_redundant_in_func_call<'tcx>( false } +fn extract_primty<'tcx>(ty_kind: &hir::TyKind<'tcx>) -> Option { + if let hir::TyKind::Path(ty_path) = ty_kind + && let hir::QPath::Resolved(_, resolved_path_ty) = ty_path + && let hir::def::Res::PrimTy(primty) = resolved_path_ty.res + { + Some(primty) + } else { + None + } +} + impl LateLintPass<'_> for RedundantTypeAnnotations { fn check_local<'tcx>(&mut self, cx: &LateContext<'tcx>, local: &'tcx rustc_hir::Local<'tcx>) { // type annotation part @@ -144,14 +155,10 @@ impl LateLintPass<'_> for RedundantTypeAnnotations { // When the initialization is a path for example u32::MAX hir::ExprKind::Path(init_path) => { // TODO: check for non primty - if let hir::TyKind::Path(ty_path) = &ty.kind - && let hir::QPath::Resolved(_, resolved_path_ty) = ty_path - && let hir::def::Res::PrimTy(primty) = resolved_path_ty.res + if let Some(primty) = extract_primty(&ty.kind) && let hir::QPath::TypeRelative(init_ty, _) = init_path - && let hir::TyKind::Path(init_ty_path) = &init_ty.kind - && let hir::QPath::Resolved(_, resolved_init_ty_path) = init_ty_path - && let hir::def::Res::PrimTy(primty_init) = resolved_init_ty_path.res + && let Some(primty_init) = extract_primty(&init_ty.kind) && primty == primty_init { From 29ab954a2b8e9b89215f5cd7159931d283818da6 Mon Sep 17 00:00:00 2001 From: Alessio Cosenza Date: Fri, 19 May 2023 17:46:32 +0200 Subject: [PATCH 068/310] Add support to returned refs from `MethodCall` --- .../src/redundant_type_annotations.rs | 26 +++++--- tests/ui/redundant_type_annotations.rs | 60 ++++++++++++------- tests/ui/redundant_type_annotations.stderr | 46 ++++++++------ 3 files changed, 85 insertions(+), 47 deletions(-) diff --git a/clippy_lints/src/redundant_type_annotations.rs b/clippy_lints/src/redundant_type_annotations.rs index da139cdde92..18647891ac6 100644 --- a/clippy_lints/src/redundant_type_annotations.rs +++ b/clippy_lints/src/redundant_type_annotations.rs @@ -59,10 +59,8 @@ fn func_hir_id_to_func_ty<'tcx>(cx: &LateContext<'tcx>, hir_id: hir::hir_id::Hir } fn func_ty_to_return_type<'tcx>(cx: &LateContext<'tcx>, func_ty: Ty<'tcx>) -> Option> { - if func_ty.is_fn() - && let Some(return_type) = func_ty.fn_sig(cx.tcx).output().no_bound_vars() - { - Some(return_type) + if func_ty.is_fn() { + Some(func_ty.fn_sig(cx.tcx).output().skip_binder()) } else { None } @@ -111,7 +109,7 @@ fn is_redundant_in_func_call<'tcx>( false } -fn extract_primty<'tcx>(ty_kind: &hir::TyKind<'tcx>) -> Option { +fn extract_primty(ty_kind: &hir::TyKind<'_>) -> Option { if let hir::TyKind::Path(ty_path) = ty_kind && let hir::QPath::Resolved(_, resolved_path_ty) = ty_path && let hir::def::Res::PrimTy(primty) = resolved_path_ty.res @@ -142,12 +140,24 @@ impl LateLintPass<'_> for RedundantTypeAnnotations { } }, hir::ExprKind::MethodCall(_, _, _, _) => { - if let hir::TyKind::Path(ty_path) = &ty.kind - && let hir::QPath::Resolved(_, resolved_path_ty) = ty_path + let mut is_ref = false; + let mut ty_kind = &ty.kind; + // If the annotation is a ref we "peel" it + if let hir::TyKind::Ref(_, mut_ty) = &ty.kind { + is_ref = true; + ty_kind = &mut_ty.ty.kind; + } + + if let hir::TyKind::Path(ty_path) = ty_kind + && let hir::QPath::Resolved(_, resolved_path_ty) = ty_path && let Some(func_ty) = func_hir_id_to_func_ty(cx, init.hir_id) && let Some(return_type) = func_ty_to_return_type(cx, func_ty) - && is_same_type(cx, resolved_path_ty.res, return_type) + && is_same_type(cx, resolved_path_ty.res, if is_ref { + return_type.peel_refs() + } else { + return_type + }) { span_lint(cx, REDUNDANT_TYPE_ANNOTATIONS, local.span, "redundant type annotation"); } diff --git a/tests/ui/redundant_type_annotations.rs b/tests/ui/redundant_type_annotations.rs index 5722621e83a..cc507b8d658 100644 --- a/tests/ui/redundant_type_annotations.rs +++ b/tests/ui/redundant_type_annotations.rs @@ -18,8 +18,15 @@ fn plus_one>(val: T) -> T { val + 1 } +#[derive(Default)] +struct Slice { + inner: u32, +} + +#[derive(Default)] struct Pie { inner: u32, + inner_struct: Slice, } enum Pizza { @@ -32,7 +39,7 @@ fn return_a_string() -> String { } fn return_a_struct() -> Pie { - Pie { inner: 5 } + Pie::default() } fn return_an_enum() -> Pizza { @@ -48,12 +55,20 @@ impl Pie { self.inner } + fn return_a_ref(&self) -> &u32 { + &self.inner + } + + fn return_a_ref_to_struct(&self) -> &Slice { + &self.inner_struct + } + fn associated_return_an_int() -> u32 { 5 } fn new() -> Self { - Self { inner: 5 } + Self::default() } fn associated_return_a_string() -> String { @@ -61,7 +76,11 @@ impl Pie { } fn test_method_call(&self) { - let v: u32 = self.return_an_int(); // Should lint + // Everything here should be lint + + let v: u32 = self.return_an_int(); + let v: &u32 = self.return_a_ref(); + let v: &Slice = self.return_a_ref_to_struct(); } } @@ -72,21 +91,24 @@ fn test_generics() { // The type annotation is needed to determine the topic let _c: Cake = make_cake(); - // This should lint (doesn't) + // This could be lint, but currently doesn't let _c: Cake = make_cake::(); - // This should lint (doesn't) + // This could be lint, but currently doesn't let _c: u8 = make_something::(); - // This should lint (doesn't) + // This could be lint, but currently doesn't let _c: u8 = plus_one(5_u8); // Annotation needed otherwise T is i32 let _c: u8 = plus_one(5); + + // This could be lint, but currently doesn't + let _return: String = String::from("test"); } fn test_non_locals() { - // This shouldn't lint + // This shouldn't be lint fn _arg(x: u32) -> u32 { x } @@ -96,27 +118,27 @@ fn test_non_locals() { } fn test_complex_types() { - // Shouldn't lint, since the literal will be i32 otherwise + // Shouldn't be lint, since the literal will be i32 otherwise let _u8: u8 = 128; - // Should lint (doesn't) + // This could be lint, but currently doesn't let _tuple_i32: (i32, i32) = (12, 13); - // Shouldn't lint, since the tuple will be i32 otherwise + // Shouldn't be lint, since the tuple will be i32 otherwise let _tuple_u32: (u32, u32) = (1, 2); - // Should lint, since the type is determined by the init value (doesn't) + // Should be lint, since the type is determined by the init value, but currently doesn't let _tuple_u32: (u32, u32) = (3_u32, 4_u32); - // Should lint (doesn't) + // This could be lint, but currently doesn't let _array: [i32; 3] = [5, 6, 7]; - // Shouldn't lint + // Shouldn't be lint let _array: [u32; 2] = [8, 9]; } fn test_functions() { - // Everything here should lint + // Everything here should be lint let _return: String = return_a_string(); @@ -132,29 +154,23 @@ fn test_functions() { let _return: u32 = new_pie.return_an_int(); - let _return: String = String::from("test"); - let _return: u32 = Pie::associated_return_an_int(); let _return: String = Pie::associated_return_a_string(); } fn test_simple_types() { + // Everything here should be lint + let _var: u32 = u32::MAX; - // Should lint let _var: u32 = 5_u32; - // Should lint let _var: &str = "test"; - // Should lint let _var: &[u8] = b"test"; - // Should lint let _var: bool = false; } fn main() {} - -// TODO: test refs diff --git a/tests/ui/redundant_type_annotations.stderr b/tests/ui/redundant_type_annotations.stderr index 3356f480860..e8b2fe5c384 100644 --- a/tests/ui/redundant_type_annotations.stderr +++ b/tests/ui/redundant_type_annotations.stderr @@ -1,94 +1,106 @@ error: redundant type annotation - --> $DIR/redundant_type_annotations.rs:64:9 + --> $DIR/redundant_type_annotations.rs:81:9 | -LL | let v: u32 = self.return_an_int(); // Should lint +LL | let v: u32 = self.return_an_int(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: `-D clippy::redundant-type-annotations` implied by `-D warnings` error: redundant type annotation - --> $DIR/redundant_type_annotations.rs:121:5 + --> $DIR/redundant_type_annotations.rs:82:9 + | +LL | let v: &u32 = self.return_a_ref(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: redundant type annotation + --> $DIR/redundant_type_annotations.rs:83:9 + | +LL | let v: &Slice = self.return_a_ref_to_struct(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: redundant type annotation + --> $DIR/redundant_type_annotations.rs:143:5 | LL | let _return: String = return_a_string(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: redundant type annotation - --> $DIR/redundant_type_annotations.rs:123:5 + --> $DIR/redundant_type_annotations.rs:145:5 | LL | let _return: Pie = return_a_struct(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: redundant type annotation - --> $DIR/redundant_type_annotations.rs:125:5 + --> $DIR/redundant_type_annotations.rs:147:5 | LL | let _return: Pizza = return_an_enum(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: redundant type annotation - --> $DIR/redundant_type_annotations.rs:127:5 + --> $DIR/redundant_type_annotations.rs:149:5 | LL | let _return: u32 = return_an_int(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: redundant type annotation - --> $DIR/redundant_type_annotations.rs:129:5 + --> $DIR/redundant_type_annotations.rs:151:5 | LL | let _return: String = String::new(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: redundant type annotation - --> $DIR/redundant_type_annotations.rs:131:5 + --> $DIR/redundant_type_annotations.rs:153:5 | LL | let new_pie: Pie = Pie::new(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: redundant type annotation - --> $DIR/redundant_type_annotations.rs:133:5 + --> $DIR/redundant_type_annotations.rs:155:5 | LL | let _return: u32 = new_pie.return_an_int(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: redundant type annotation - --> $DIR/redundant_type_annotations.rs:137:5 + --> $DIR/redundant_type_annotations.rs:157:5 | LL | let _return: u32 = Pie::associated_return_an_int(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: redundant type annotation - --> $DIR/redundant_type_annotations.rs:139:5 + --> $DIR/redundant_type_annotations.rs:159:5 | LL | let _return: String = Pie::associated_return_a_string(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: redundant type annotation - --> $DIR/redundant_type_annotations.rs:143:5 + --> $DIR/redundant_type_annotations.rs:165:5 | LL | let _var: u32 = u32::MAX; | ^^^^^^^^^^^^^^^^^^^^^^^^^ error: redundant type annotation - --> $DIR/redundant_type_annotations.rs:146:5 + --> $DIR/redundant_type_annotations.rs:167:5 | LL | let _var: u32 = 5_u32; | ^^^^^^^^^^^^^^^^^^^^^^ error: redundant type annotation - --> $DIR/redundant_type_annotations.rs:149:5 + --> $DIR/redundant_type_annotations.rs:169:5 | LL | let _var: &str = "test"; | ^^^^^^^^^^^^^^^^^^^^^^^^ error: redundant type annotation - --> $DIR/redundant_type_annotations.rs:152:5 + --> $DIR/redundant_type_annotations.rs:171:5 | LL | let _var: &[u8] = b"test"; | ^^^^^^^^^^^^^^^^^^^^^^^^^^ error: redundant type annotation - --> $DIR/redundant_type_annotations.rs:155:5 + --> $DIR/redundant_type_annotations.rs:173:5 | LL | let _var: bool = false; | ^^^^^^^^^^^^^^^^^^^^^^^ -error: aborting due to 15 previous errors +error: aborting due to 17 previous errors From a9b468f2b51a251d0d718059299d0ccd0e561389 Mon Sep 17 00:00:00 2001 From: Alessio Cosenza Date: Mon, 29 May 2023 11:24:36 +0200 Subject: [PATCH 069/310] Add `Limitations` section --- clippy_lints/src/redundant_type_annotations.rs | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/clippy_lints/src/redundant_type_annotations.rs b/clippy_lints/src/redundant_type_annotations.rs index 18647891ac6..8e9234bba3c 100644 --- a/clippy_lints/src/redundant_type_annotations.rs +++ b/clippy_lints/src/redundant_type_annotations.rs @@ -13,6 +13,14 @@ declare_clippy_lint! { /// Code without type annotations is shorter and in most cases /// more idiomatic and easier to modify. /// + /// ### Limitations + /// This lint doesn't support: + /// + /// - Generics + /// - Refs returned from anything else than a `MethodCall` + /// - Complex types (tuples, arrays, etc...) + /// - `Path` to anything else than a primitive type. + /// /// ### Example /// ```rust /// let foo: String = String::new(); From 6f2497703e7e3b7c4c0c007371ed6870c984769a Mon Sep 17 00:00:00 2001 From: MarcusGrass <34198073+MarcusGrass@users.noreply.github.com> Date: Mon, 5 Jun 2023 15:48:57 +0200 Subject: [PATCH 070/310] Compact issue link Co-authored-by: Takayuki Nakata --- clippy_lints/src/returns.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clippy_lints/src/returns.rs b/clippy_lints/src/returns.rs index 92913ddc4aa..b5686e390ad 100644 --- a/clippy_lints/src/returns.rs +++ b/clippy_lints/src/returns.rs @@ -27,7 +27,7 @@ declare_clippy_lint! { /// /// ### Known problems /// In the case of some temporaries, e.g. locks, eliding the variable binding could lead - /// to deadlocks. See [rust-lang issue 37612](https://github.com/rust-lang/rust/issues/37612). + /// to deadlocks. See [this issue](https://github.com/rust-lang/rust/issues/37612). /// This could become relevant if the code is later changed to use the code that would have been /// bound without first assigning it to a let-binding. /// From 6ea7cd8ec700c4fbf1397eeef65fad5478965564 Mon Sep 17 00:00:00 2001 From: Centri3 <114838443+Centri3@users.noreply.github.com> Date: Mon, 5 Jun 2023 14:38:38 -0500 Subject: [PATCH 071/310] Fix #10504, don't lint on derived code --- clippy_lints/src/trait_bounds.rs | 3 +++ tests/ui/type_repetition_in_bounds.rs | 15 +++++++++++++++ tests/ui/type_repetition_in_bounds.stderr | 8 ++++---- 3 files changed, 22 insertions(+), 4 deletions(-) diff --git a/clippy_lints/src/trait_bounds.rs b/clippy_lints/src/trait_bounds.rs index 4ccda15068b..913ef7644aa 100644 --- a/clippy_lints/src/trait_bounds.rs +++ b/clippy_lints/src/trait_bounds.rs @@ -260,6 +260,9 @@ impl TraitBounds { SpanlessTy { ty: p.bounded_ty, cx }, p.bounds.iter().collect::>() ); + if let TyKind::Path(qpath) = p.bounded_ty.kind; + if format!("{}:", rustc_hir_pretty::qpath_to_string(&qpath)) + == format!("{}:", snippet(cx, p.bounded_ty.span, "_")); then { let trait_bounds = v diff --git a/tests/ui/type_repetition_in_bounds.rs b/tests/ui/type_repetition_in_bounds.rs index 8b4613b3f6e..1d36f4b3c7b 100644 --- a/tests/ui/type_repetition_in_bounds.rs +++ b/tests/ui/type_repetition_in_bounds.rs @@ -1,6 +1,7 @@ #![deny(clippy::type_repetition_in_bounds)] #![allow(clippy::extra_unused_type_parameters)] +use serde::Deserialize; use std::ops::{Add, AddAssign, Div, DivAssign, Mul, MulAssign, Sub, SubAssign}; pub fn foo(_t: T) @@ -70,6 +71,20 @@ mod issue4326 { } } +// Extern macros shouldn't lint, again (see #10504) +mod issue10504 { + use serde::{Deserialize, Serialize}; + use std::fmt::Debug; + use std::hash::Hash; + + #[derive(Debug, Serialize, Deserialize)] + #[serde(bound( + serialize = "T: Serialize + Hash + Eq", + deserialize = "Box: serde::de::DeserializeOwned + Hash + Eq" + ))] + struct OpaqueParams(std::marker::PhantomData); +} + // Issue #7360 struct Foo where diff --git a/tests/ui/type_repetition_in_bounds.stderr b/tests/ui/type_repetition_in_bounds.stderr index a90df03c04f..56867f75b07 100644 --- a/tests/ui/type_repetition_in_bounds.stderr +++ b/tests/ui/type_repetition_in_bounds.stderr @@ -1,5 +1,5 @@ error: this type has already been used as a bound predicate - --> $DIR/type_repetition_in_bounds.rs:9:5 + --> $DIR/type_repetition_in_bounds.rs:10:5 | LL | T: Clone, | ^^^^^^^^ @@ -12,7 +12,7 @@ LL | #![deny(clippy::type_repetition_in_bounds)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: this type has already been used as a bound predicate - --> $DIR/type_repetition_in_bounds.rs:26:5 + --> $DIR/type_repetition_in_bounds.rs:27:5 | LL | Self: Copy + Default + Ord, | ^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -20,7 +20,7 @@ LL | Self: Copy + Default + Ord, = help: consider combining the bounds: `Self: Clone + Copy + Default + Ord` error: this type has already been used as a bound predicate - --> $DIR/type_repetition_in_bounds.rs:86:5 + --> $DIR/type_repetition_in_bounds.rs:101:5 | LL | T: Clone, | ^^^^^^^^ @@ -28,7 +28,7 @@ LL | T: Clone, = help: consider combining the bounds: `T: ?Sized + Clone` error: this type has already been used as a bound predicate - --> $DIR/type_repetition_in_bounds.rs:91:5 + --> $DIR/type_repetition_in_bounds.rs:106:5 | LL | T: ?Sized, | ^^^^^^^^^ From 0250c518449f535a4d38bf17f5b0ba5ecda3f3c9 Mon Sep 17 00:00:00 2001 From: Centri3 <114838443+Centri3@users.noreply.github.com> Date: Mon, 5 Jun 2023 14:46:47 -0500 Subject: [PATCH 072/310] refactor --- clippy_lints/src/trait_bounds.rs | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/clippy_lints/src/trait_bounds.rs b/clippy_lints/src/trait_bounds.rs index 913ef7644aa..90c6429ff38 100644 --- a/clippy_lints/src/trait_bounds.rs +++ b/clippy_lints/src/trait_bounds.rs @@ -260,9 +260,9 @@ impl TraitBounds { SpanlessTy { ty: p.bounded_ty, cx }, p.bounds.iter().collect::>() ); + let bounded_ty = snippet(cx, p.bounded_ty.span, "_"); if let TyKind::Path(qpath) = p.bounded_ty.kind; - if format!("{}:", rustc_hir_pretty::qpath_to_string(&qpath)) - == format!("{}:", snippet(cx, p.bounded_ty.span, "_")); + if format!("{}:", rustc_hir_pretty::qpath_to_string(&qpath)) == format!("{}:", bounded_ty); then { let trait_bounds = v @@ -272,10 +272,7 @@ impl TraitBounds { .filter_map(get_trait_info_from_bound) .map(|(_, _, span)| snippet_with_applicability(cx, span, "..", &mut applicability)) .join(" + "); - let hint_string = format!( - "consider combining the bounds: `{}: {trait_bounds}`", - snippet(cx, p.bounded_ty.span, "_"), - ); + let hint_string = format!("consider combining the bounds: `{}: {trait_bounds}`", bounded_ty); span_lint_and_help( cx, TYPE_REPETITION_IN_BOUNDS, @@ -345,7 +342,7 @@ fn check_trait_bound_duplication(cx: &LateContext<'_>, gen: &'_ Generics<'_>) { "this trait bound is already specified in the where clause", None, "consider removing this trait bound", - ); + ); } } } From f68ee79864fb51232fb186fda6bf218be50c7e4a Mon Sep 17 00:00:00 2001 From: Centri3 <114838443+Centri3@users.noreply.github.com> Date: Mon, 5 Jun 2023 14:53:22 -0500 Subject: [PATCH 073/310] Update trait_bounds.rs --- clippy_lints/src/trait_bounds.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/clippy_lints/src/trait_bounds.rs b/clippy_lints/src/trait_bounds.rs index 90c6429ff38..2e6108d6b24 100644 --- a/clippy_lints/src/trait_bounds.rs +++ b/clippy_lints/src/trait_bounds.rs @@ -262,7 +262,7 @@ impl TraitBounds { ); let bounded_ty = snippet(cx, p.bounded_ty.span, "_"); if let TyKind::Path(qpath) = p.bounded_ty.kind; - if format!("{}:", rustc_hir_pretty::qpath_to_string(&qpath)) == format!("{}:", bounded_ty); + if format!("{}:", rustc_hir_pretty::qpath_to_string(&qpath)) == format!("{bounded_ty}:"); then { let trait_bounds = v @@ -272,7 +272,7 @@ impl TraitBounds { .filter_map(get_trait_info_from_bound) .map(|(_, _, span)| snippet_with_applicability(cx, span, "..", &mut applicability)) .join(" + "); - let hint_string = format!("consider combining the bounds: `{}: {trait_bounds}`", bounded_ty); + let hint_string = format!("consider combining the bounds: `{bounded_ty}: {trait_bounds}`"); span_lint_and_help( cx, TYPE_REPETITION_IN_BOUNDS, From e70dd55fd63ca0378ce143efd72c0c3b01914b15 Mon Sep 17 00:00:00 2001 From: y21 <30553356+y21@users.noreply.github.com> Date: Mon, 5 Jun 2023 23:45:18 +0200 Subject: [PATCH 074/310] account for autoderef in eager_or_lazy --- clippy_utils/src/eager_or_lazy.rs | 15 +++++ tests/ui/unnecessary_lazy_eval.fixed | 7 +++ tests/ui/unnecessary_lazy_eval.rs | 7 +++ tests/ui/unnecessary_lazy_eval.stderr | 88 ++++++++++++++++----------- 4 files changed, 81 insertions(+), 36 deletions(-) diff --git a/clippy_utils/src/eager_or_lazy.rs b/clippy_utils/src/eager_or_lazy.rs index e05b88e4cd0..addd3619a84 100644 --- a/clippy_utils/src/eager_or_lazy.rs +++ b/clippy_utils/src/eager_or_lazy.rs @@ -15,6 +15,7 @@ use rustc_hir::def::{DefKind, Res}; use rustc_hir::intravisit::{walk_expr, Visitor}; use rustc_hir::{def_id::DefId, Block, Expr, ExprKind, QPath, UnOp}; use rustc_lint::LateContext; +use rustc_middle::ty::adjustment::Adjust; use rustc_middle::ty::{self, PredicateKind}; use rustc_span::{sym, Symbol}; use std::cmp; @@ -114,6 +115,20 @@ fn expr_eagerness<'tcx>(cx: &LateContext<'tcx>, e: &'tcx Expr<'_>) -> EagernessS if self.eagerness == ForceNoChange { return; } + + // Autoderef through a user-defined `Deref` impl can have side-effects, + // so don't suggest changing it. + if self + .cx + .typeck_results() + .expr_adjustments(e) + .iter() + .any(|adj| matches!(adj.kind, Adjust::Deref(Some(_)))) + { + self.eagerness |= NoChange; + return; + } + match e.kind { ExprKind::Call( &Expr { diff --git a/tests/ui/unnecessary_lazy_eval.fixed b/tests/ui/unnecessary_lazy_eval.fixed index f8d4c0bd912..565bd96cf30 100644 --- a/tests/ui/unnecessary_lazy_eval.fixed +++ b/tests/ui/unnecessary_lazy_eval.fixed @@ -4,6 +4,7 @@ #![allow(clippy::redundant_closure)] #![allow(clippy::bind_instead_of_map)] #![allow(clippy::map_identity)] +#![allow(clippy::needless_borrow)] use std::ops::Deref; @@ -81,6 +82,9 @@ fn main() { let _ = Some(1).unwrap_or(*r); let b = Box::new(1); let _ = Some(1).unwrap_or(*b); + // Should lint - Builtin deref through autoderef + let _ = Some(1).as_ref().unwrap_or(&r); + let _ = Some(1).as_ref().unwrap_or(&b); // Cases when unwrap is not called on a simple variable let _ = Some(10).unwrap_or(2); @@ -113,6 +117,9 @@ fn main() { let _ = Some(1).unwrap_or_else(|| *Issue10437); // Issue10437 has a deref impl let _ = Some(1).unwrap_or(*Issue10437); + let _ = Some(1).as_ref().unwrap_or_else(|| &Issue10437); + let _ = Some(1).as_ref().unwrap_or(&Issue10437); + // Should not lint - bool let _ = (0 == 1).then(|| Issue9427(0)); // Issue9427 has a significant drop let _ = false.then(|| Issue9427FollowUp); // Issue9427FollowUp has a significant drop diff --git a/tests/ui/unnecessary_lazy_eval.rs b/tests/ui/unnecessary_lazy_eval.rs index b968894f870..3627076b2af 100644 --- a/tests/ui/unnecessary_lazy_eval.rs +++ b/tests/ui/unnecessary_lazy_eval.rs @@ -4,6 +4,7 @@ #![allow(clippy::redundant_closure)] #![allow(clippy::bind_instead_of_map)] #![allow(clippy::map_identity)] +#![allow(clippy::needless_borrow)] use std::ops::Deref; @@ -81,6 +82,9 @@ fn main() { let _ = Some(1).unwrap_or_else(|| *r); let b = Box::new(1); let _ = Some(1).unwrap_or_else(|| *b); + // Should lint - Builtin deref through autoderef + let _ = Some(1).as_ref().unwrap_or_else(|| &r); + let _ = Some(1).as_ref().unwrap_or_else(|| &b); // Cases when unwrap is not called on a simple variable let _ = Some(10).unwrap_or_else(|| 2); @@ -113,6 +117,9 @@ fn main() { let _ = Some(1).unwrap_or_else(|| *Issue10437); // Issue10437 has a deref impl let _ = Some(1).unwrap_or(*Issue10437); + let _ = Some(1).as_ref().unwrap_or_else(|| &Issue10437); + let _ = Some(1).as_ref().unwrap_or(&Issue10437); + // Should not lint - bool let _ = (0 == 1).then(|| Issue9427(0)); // Issue9427 has a significant drop let _ = false.then(|| Issue9427FollowUp); // Issue9427FollowUp has a significant drop diff --git a/tests/ui/unnecessary_lazy_eval.stderr b/tests/ui/unnecessary_lazy_eval.stderr index c3d106cd109..2850a632fc7 100644 --- a/tests/ui/unnecessary_lazy_eval.stderr +++ b/tests/ui/unnecessary_lazy_eval.stderr @@ -1,5 +1,5 @@ error: unnecessary closure used to substitute value for `Option::None` - --> $DIR/unnecessary_lazy_eval.rs:67:13 + --> $DIR/unnecessary_lazy_eval.rs:68:13 | LL | let _ = opt.unwrap_or_else(|| 2); | ^^^^-------------------- @@ -9,7 +9,7 @@ LL | let _ = opt.unwrap_or_else(|| 2); = note: `-D clippy::unnecessary-lazy-evaluations` implied by `-D warnings` error: unnecessary closure used to substitute value for `Option::None` - --> $DIR/unnecessary_lazy_eval.rs:68:13 + --> $DIR/unnecessary_lazy_eval.rs:69:13 | LL | let _ = opt.unwrap_or_else(|| astronomers_pi); | ^^^^--------------------------------- @@ -17,7 +17,7 @@ LL | let _ = opt.unwrap_or_else(|| astronomers_pi); | help: use `unwrap_or(..)` instead: `unwrap_or(astronomers_pi)` error: unnecessary closure used to substitute value for `Option::None` - --> $DIR/unnecessary_lazy_eval.rs:69:13 + --> $DIR/unnecessary_lazy_eval.rs:70:13 | LL | let _ = opt.unwrap_or_else(|| ext_str.some_field); | ^^^^------------------------------------- @@ -25,7 +25,7 @@ LL | let _ = opt.unwrap_or_else(|| ext_str.some_field); | help: use `unwrap_or(..)` instead: `unwrap_or(ext_str.some_field)` error: unnecessary closure used to substitute value for `Option::None` - --> $DIR/unnecessary_lazy_eval.rs:71:13 + --> $DIR/unnecessary_lazy_eval.rs:72:13 | LL | let _ = opt.and_then(|_| ext_opt); | ^^^^--------------------- @@ -33,7 +33,7 @@ LL | let _ = opt.and_then(|_| ext_opt); | help: use `and(..)` instead: `and(ext_opt)` error: unnecessary closure used to substitute value for `Option::None` - --> $DIR/unnecessary_lazy_eval.rs:72:13 + --> $DIR/unnecessary_lazy_eval.rs:73:13 | LL | let _ = opt.or_else(|| ext_opt); | ^^^^------------------- @@ -41,7 +41,7 @@ LL | let _ = opt.or_else(|| ext_opt); | help: use `or(..)` instead: `or(ext_opt)` error: unnecessary closure used to substitute value for `Option::None` - --> $DIR/unnecessary_lazy_eval.rs:73:13 + --> $DIR/unnecessary_lazy_eval.rs:74:13 | LL | let _ = opt.or_else(|| None); | ^^^^---------------- @@ -49,7 +49,7 @@ LL | let _ = opt.or_else(|| None); | help: use `or(..)` instead: `or(None)` error: unnecessary closure used to substitute value for `Option::None` - --> $DIR/unnecessary_lazy_eval.rs:74:13 + --> $DIR/unnecessary_lazy_eval.rs:75:13 | LL | let _ = opt.get_or_insert_with(|| 2); | ^^^^------------------------ @@ -57,7 +57,7 @@ LL | let _ = opt.get_or_insert_with(|| 2); | help: use `get_or_insert(..)` instead: `get_or_insert(2)` error: unnecessary closure used to substitute value for `Option::None` - --> $DIR/unnecessary_lazy_eval.rs:75:13 + --> $DIR/unnecessary_lazy_eval.rs:76:13 | LL | let _ = opt.ok_or_else(|| 2); | ^^^^---------------- @@ -65,7 +65,7 @@ LL | let _ = opt.ok_or_else(|| 2); | help: use `ok_or(..)` instead: `ok_or(2)` error: unnecessary closure used to substitute value for `Option::None` - --> $DIR/unnecessary_lazy_eval.rs:76:13 + --> $DIR/unnecessary_lazy_eval.rs:77:13 | LL | let _ = nested_tuple_opt.unwrap_or_else(|| Some((1, 2))); | ^^^^^^^^^^^^^^^^^------------------------------- @@ -73,7 +73,7 @@ LL | let _ = nested_tuple_opt.unwrap_or_else(|| Some((1, 2))); | help: use `unwrap_or(..)` instead: `unwrap_or(Some((1, 2)))` error: unnecessary closure used with `bool::then` - --> $DIR/unnecessary_lazy_eval.rs:77:13 + --> $DIR/unnecessary_lazy_eval.rs:78:13 | LL | let _ = cond.then(|| astronomers_pi); | ^^^^^----------------------- @@ -81,7 +81,7 @@ LL | let _ = cond.then(|| astronomers_pi); | help: use `then_some(..)` instead: `then_some(astronomers_pi)` error: unnecessary closure used to substitute value for `Option::None` - --> $DIR/unnecessary_lazy_eval.rs:81:13 + --> $DIR/unnecessary_lazy_eval.rs:82:13 | LL | let _ = Some(1).unwrap_or_else(|| *r); | ^^^^^^^^--------------------- @@ -89,7 +89,7 @@ LL | let _ = Some(1).unwrap_or_else(|| *r); | help: use `unwrap_or(..)` instead: `unwrap_or(*r)` error: unnecessary closure used to substitute value for `Option::None` - --> $DIR/unnecessary_lazy_eval.rs:83:13 + --> $DIR/unnecessary_lazy_eval.rs:84:13 | LL | let _ = Some(1).unwrap_or_else(|| *b); | ^^^^^^^^--------------------- @@ -99,13 +99,29 @@ LL | let _ = Some(1).unwrap_or_else(|| *b); error: unnecessary closure used to substitute value for `Option::None` --> $DIR/unnecessary_lazy_eval.rs:86:13 | +LL | let _ = Some(1).as_ref().unwrap_or_else(|| &r); + | ^^^^^^^^^^^^^^^^^--------------------- + | | + | help: use `unwrap_or(..)` instead: `unwrap_or(&r)` + +error: unnecessary closure used to substitute value for `Option::None` + --> $DIR/unnecessary_lazy_eval.rs:87:13 + | +LL | let _ = Some(1).as_ref().unwrap_or_else(|| &b); + | ^^^^^^^^^^^^^^^^^--------------------- + | | + | help: use `unwrap_or(..)` instead: `unwrap_or(&b)` + +error: unnecessary closure used to substitute value for `Option::None` + --> $DIR/unnecessary_lazy_eval.rs:90:13 + | LL | let _ = Some(10).unwrap_or_else(|| 2); | ^^^^^^^^^-------------------- | | | help: use `unwrap_or(..)` instead: `unwrap_or(2)` error: unnecessary closure used to substitute value for `Option::None` - --> $DIR/unnecessary_lazy_eval.rs:87:13 + --> $DIR/unnecessary_lazy_eval.rs:91:13 | LL | let _ = Some(10).and_then(|_| ext_opt); | ^^^^^^^^^--------------------- @@ -113,7 +129,7 @@ LL | let _ = Some(10).and_then(|_| ext_opt); | help: use `and(..)` instead: `and(ext_opt)` error: unnecessary closure used to substitute value for `Option::None` - --> $DIR/unnecessary_lazy_eval.rs:88:28 + --> $DIR/unnecessary_lazy_eval.rs:92:28 | LL | let _: Option = None.or_else(|| ext_opt); | ^^^^^------------------- @@ -121,7 +137,7 @@ LL | let _: Option = None.or_else(|| ext_opt); | help: use `or(..)` instead: `or(ext_opt)` error: unnecessary closure used to substitute value for `Option::None` - --> $DIR/unnecessary_lazy_eval.rs:89:13 + --> $DIR/unnecessary_lazy_eval.rs:93:13 | LL | let _ = None.get_or_insert_with(|| 2); | ^^^^^------------------------ @@ -129,7 +145,7 @@ LL | let _ = None.get_or_insert_with(|| 2); | help: use `get_or_insert(..)` instead: `get_or_insert(2)` error: unnecessary closure used to substitute value for `Option::None` - --> $DIR/unnecessary_lazy_eval.rs:90:35 + --> $DIR/unnecessary_lazy_eval.rs:94:35 | LL | let _: Result = None.ok_or_else(|| 2); | ^^^^^---------------- @@ -137,7 +153,7 @@ LL | let _: Result = None.ok_or_else(|| 2); | help: use `ok_or(..)` instead: `ok_or(2)` error: unnecessary closure used to substitute value for `Option::None` - --> $DIR/unnecessary_lazy_eval.rs:91:28 + --> $DIR/unnecessary_lazy_eval.rs:95:28 | LL | let _: Option = None.or_else(|| None); | ^^^^^---------------- @@ -145,7 +161,7 @@ LL | let _: Option = None.or_else(|| None); | help: use `or(..)` instead: `or(None)` error: unnecessary closure used to substitute value for `Option::None` - --> $DIR/unnecessary_lazy_eval.rs:94:13 + --> $DIR/unnecessary_lazy_eval.rs:98:13 | LL | let _ = deep.0.unwrap_or_else(|| 2); | ^^^^^^^-------------------- @@ -153,7 +169,7 @@ LL | let _ = deep.0.unwrap_or_else(|| 2); | help: use `unwrap_or(..)` instead: `unwrap_or(2)` error: unnecessary closure used to substitute value for `Option::None` - --> $DIR/unnecessary_lazy_eval.rs:95:13 + --> $DIR/unnecessary_lazy_eval.rs:99:13 | LL | let _ = deep.0.and_then(|_| ext_opt); | ^^^^^^^--------------------- @@ -161,7 +177,7 @@ LL | let _ = deep.0.and_then(|_| ext_opt); | help: use `and(..)` instead: `and(ext_opt)` error: unnecessary closure used to substitute value for `Option::None` - --> $DIR/unnecessary_lazy_eval.rs:96:13 + --> $DIR/unnecessary_lazy_eval.rs:100:13 | LL | let _ = deep.0.or_else(|| None); | ^^^^^^^---------------- @@ -169,7 +185,7 @@ LL | let _ = deep.0.or_else(|| None); | help: use `or(..)` instead: `or(None)` error: unnecessary closure used to substitute value for `Option::None` - --> $DIR/unnecessary_lazy_eval.rs:97:13 + --> $DIR/unnecessary_lazy_eval.rs:101:13 | LL | let _ = deep.0.get_or_insert_with(|| 2); | ^^^^^^^------------------------ @@ -177,7 +193,7 @@ LL | let _ = deep.0.get_or_insert_with(|| 2); | help: use `get_or_insert(..)` instead: `get_or_insert(2)` error: unnecessary closure used to substitute value for `Option::None` - --> $DIR/unnecessary_lazy_eval.rs:98:13 + --> $DIR/unnecessary_lazy_eval.rs:102:13 | LL | let _ = deep.0.ok_or_else(|| 2); | ^^^^^^^---------------- @@ -185,7 +201,7 @@ LL | let _ = deep.0.ok_or_else(|| 2); | help: use `ok_or(..)` instead: `ok_or(2)` error: unnecessary closure used to substitute value for `Option::None` - --> $DIR/unnecessary_lazy_eval.rs:125:28 + --> $DIR/unnecessary_lazy_eval.rs:132:28 | LL | let _: Option = None.or_else(|| Some(3)); | ^^^^^------------------- @@ -193,7 +209,7 @@ LL | let _: Option = None.or_else(|| Some(3)); | help: use `or(..)` instead: `or(Some(3))` error: unnecessary closure used to substitute value for `Option::None` - --> $DIR/unnecessary_lazy_eval.rs:126:13 + --> $DIR/unnecessary_lazy_eval.rs:133:13 | LL | let _ = deep.0.or_else(|| Some(3)); | ^^^^^^^------------------- @@ -201,7 +217,7 @@ LL | let _ = deep.0.or_else(|| Some(3)); | help: use `or(..)` instead: `or(Some(3))` error: unnecessary closure used to substitute value for `Option::None` - --> $DIR/unnecessary_lazy_eval.rs:127:13 + --> $DIR/unnecessary_lazy_eval.rs:134:13 | LL | let _ = opt.or_else(|| Some(3)); | ^^^^------------------- @@ -209,7 +225,7 @@ LL | let _ = opt.or_else(|| Some(3)); | help: use `or(..)` instead: `or(Some(3))` error: unnecessary closure used to substitute value for `Result::Err` - --> $DIR/unnecessary_lazy_eval.rs:133:13 + --> $DIR/unnecessary_lazy_eval.rs:140:13 | LL | let _ = res2.unwrap_or_else(|_| 2); | ^^^^^--------------------- @@ -217,7 +233,7 @@ LL | let _ = res2.unwrap_or_else(|_| 2); | help: use `unwrap_or(..)` instead: `unwrap_or(2)` error: unnecessary closure used to substitute value for `Result::Err` - --> $DIR/unnecessary_lazy_eval.rs:134:13 + --> $DIR/unnecessary_lazy_eval.rs:141:13 | LL | let _ = res2.unwrap_or_else(|_| astronomers_pi); | ^^^^^---------------------------------- @@ -225,7 +241,7 @@ LL | let _ = res2.unwrap_or_else(|_| astronomers_pi); | help: use `unwrap_or(..)` instead: `unwrap_or(astronomers_pi)` error: unnecessary closure used to substitute value for `Result::Err` - --> $DIR/unnecessary_lazy_eval.rs:135:13 + --> $DIR/unnecessary_lazy_eval.rs:142:13 | LL | let _ = res2.unwrap_or_else(|_| ext_str.some_field); | ^^^^^-------------------------------------- @@ -233,7 +249,7 @@ LL | let _ = res2.unwrap_or_else(|_| ext_str.some_field); | help: use `unwrap_or(..)` instead: `unwrap_or(ext_str.some_field)` error: unnecessary closure used to substitute value for `Result::Err` - --> $DIR/unnecessary_lazy_eval.rs:157:35 + --> $DIR/unnecessary_lazy_eval.rs:164:35 | LL | let _: Result = res.and_then(|_| Err(2)); | ^^^^-------------------- @@ -241,7 +257,7 @@ LL | let _: Result = res.and_then(|_| Err(2)); | help: use `and(..)` instead: `and(Err(2))` error: unnecessary closure used to substitute value for `Result::Err` - --> $DIR/unnecessary_lazy_eval.rs:158:35 + --> $DIR/unnecessary_lazy_eval.rs:165:35 | LL | let _: Result = res.and_then(|_| Err(astronomers_pi)); | ^^^^--------------------------------- @@ -249,7 +265,7 @@ LL | let _: Result = res.and_then(|_| Err(astronomers_pi)); | help: use `and(..)` instead: `and(Err(astronomers_pi))` error: unnecessary closure used to substitute value for `Result::Err` - --> $DIR/unnecessary_lazy_eval.rs:159:35 + --> $DIR/unnecessary_lazy_eval.rs:166:35 | LL | let _: Result = res.and_then(|_| Err(ext_str.some_field)); | ^^^^------------------------------------- @@ -257,7 +273,7 @@ LL | let _: Result = res.and_then(|_| Err(ext_str.some_field)) | help: use `and(..)` instead: `and(Err(ext_str.some_field))` error: unnecessary closure used to substitute value for `Result::Err` - --> $DIR/unnecessary_lazy_eval.rs:161:35 + --> $DIR/unnecessary_lazy_eval.rs:168:35 | LL | let _: Result = res.or_else(|_| Ok(2)); | ^^^^------------------ @@ -265,7 +281,7 @@ LL | let _: Result = res.or_else(|_| Ok(2)); | help: use `or(..)` instead: `or(Ok(2))` error: unnecessary closure used to substitute value for `Result::Err` - --> $DIR/unnecessary_lazy_eval.rs:162:35 + --> $DIR/unnecessary_lazy_eval.rs:169:35 | LL | let _: Result = res.or_else(|_| Ok(astronomers_pi)); | ^^^^------------------------------- @@ -273,7 +289,7 @@ LL | let _: Result = res.or_else(|_| Ok(astronomers_pi)); | help: use `or(..)` instead: `or(Ok(astronomers_pi))` error: unnecessary closure used to substitute value for `Result::Err` - --> $DIR/unnecessary_lazy_eval.rs:163:35 + --> $DIR/unnecessary_lazy_eval.rs:170:35 | LL | let _: Result = res.or_else(|_| Ok(ext_str.some_field)); | ^^^^----------------------------------- @@ -281,7 +297,7 @@ LL | let _: Result = res.or_else(|_| Ok(ext_str.some_field)); | help: use `or(..)` instead: `or(Ok(ext_str.some_field))` error: unnecessary closure used to substitute value for `Result::Err` - --> $DIR/unnecessary_lazy_eval.rs:164:35 + --> $DIR/unnecessary_lazy_eval.rs:171:35 | LL | let _: Result = res. | ___________________________________^ @@ -295,5 +311,5 @@ LL | | or_else(|_| Ok(ext_str.some_field)); | | | help: use `or(..)` instead: `or(Ok(ext_str.some_field))` -error: aborting due to 36 previous errors +error: aborting due to 38 previous errors From 1cf95a9d50b0ca8be1687e03db4202cf033d4a74 Mon Sep 17 00:00:00 2001 From: y21 <30553356+y21@users.noreply.github.com> Date: Tue, 6 Jun 2023 01:23:42 +0200 Subject: [PATCH 075/310] don't call `type_of` on generic params --- clippy_lints/src/missing_fields_in_debug.rs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/clippy_lints/src/missing_fields_in_debug.rs b/clippy_lints/src/missing_fields_in_debug.rs index b6f0de7e504..1138d1163a4 100644 --- a/clippy_lints/src/missing_fields_in_debug.rs +++ b/clippy_lints/src/missing_fields_in_debug.rs @@ -207,6 +207,11 @@ impl<'tcx> LateLintPass<'tcx> for MissingFieldsInDebug { if let ItemKind::Impl(Impl { of_trait: Some(trait_ref), self_ty, items, .. }) = item.kind && let Res::Def(DefKind::Trait, trait_def_id) = trait_ref.path.res && let TyKind::Path(QPath::Resolved(_, self_path)) = &self_ty.kind + // don't trigger if self is a generic parameter, e.g. `impl Debug for T` + // this can only happen in core itself, where the trait is defined, + // but it caused ICEs in the past: + // https://github.com/rust-lang/rust-clippy/issues/10887 + && !matches!(self_path.res, Res::Def(DefKind::TyParam, _)) && cx.match_def_path(trait_def_id, &[sym::core, sym::fmt, sym::Debug]) // don't trigger if this impl was derived && !cx.tcx.has_attr(item.owner_id, sym::automatically_derived) From 7cd0ec58aa22bf84b7e452aa682d3694542a3399 Mon Sep 17 00:00:00 2001 From: asquared31415 <34665709+asquared31415@users.noreply.github.com> Date: Tue, 6 Jun 2023 14:58:54 -0400 Subject: [PATCH 076/310] add more info link --- clippy_lints/src/casts/cast_possible_wrap.rs | 14 +++++++++++--- tests/ui/cast.stderr | 6 ++++++ 2 files changed, 17 insertions(+), 3 deletions(-) diff --git a/clippy_lints/src/casts/cast_possible_wrap.rs b/clippy_lints/src/casts/cast_possible_wrap.rs index e872d190c82..f77d7821539 100644 --- a/clippy_lints/src/casts/cast_possible_wrap.rs +++ b/clippy_lints/src/casts/cast_possible_wrap.rs @@ -1,6 +1,5 @@ -use clippy_utils::diagnostics::span_lint; use rustc_hir::Expr; -use rustc_lint::LateContext; +use rustc_lint::{LateContext, LintContext}; use rustc_middle::ty::Ty; use super::{utils, CAST_POSSIBLE_WRAP}; @@ -9,6 +8,7 @@ use super::{utils, CAST_POSSIBLE_WRAP}; const ALLOWED_POINTER_SIZES: [u64; 3] = [16, 32, 64]; // whether the lint should be emitted, and the required pointer size, if it matters +#[derive(Copy, Clone, Debug, PartialEq, Eq)] enum EmitState { NoLint, LintAlways, @@ -77,5 +77,13 @@ pub(super) fn check(cx: &LateContext<'_>, expr: &Expr<'_>, cast_from: Ty<'_>, ca ), }; - span_lint(cx, CAST_POSSIBLE_WRAP, expr.span, message.as_str()); + cx.struct_span_lint(CAST_POSSIBLE_WRAP, expr.span, message, |diag| { + if let EmitState::LintOnPtrSize(16) = should_lint { + diag + .note("`usize` and `isize` may be as small as 16 bits on some platforms") + .note("for more information see https://doc.rust-lang.org/reference/types/numeric.html#machine-dependent-integer-types") + } else { + diag + } + }); } diff --git a/tests/ui/cast.stderr b/tests/ui/cast.stderr index a7d78a95d59..de29af78ef3 100644 --- a/tests/ui/cast.stderr +++ b/tests/ui/cast.stderr @@ -244,6 +244,9 @@ error: casting `usize` to `i16` may wrap around the value on targets with 16-bit | LL | 1usize as i16; // wraps on 16 bit ptr size | ^^^^^^^^^^^^^ + | + = note: `usize` and `isize` may be as small as 16 bits on some platforms + = note: for more information see https://doc.rust-lang.org/reference/types/numeric.html#machine-dependent-integer-types error: casting `usize` to `i32` may truncate the value on targets with 64-bit wide pointers --> $DIR/cast.rs:46:5 @@ -274,6 +277,9 @@ error: casting `u16` to `isize` may wrap around the value on targets with 16-bit | LL | 1u16 as isize; // wraps on 16 bit ptr size | ^^^^^^^^^^^^^ + | + = note: `usize` and `isize` may be as small as 16 bits on some platforms + = note: for more information see https://doc.rust-lang.org/reference/types/numeric.html#machine-dependent-integer-types error: casting `u32` to `isize` may wrap around the value on targets with 32-bit wide pointers --> $DIR/cast.rs:50:5 From 566a365d4f7dc865ee1942a49c23617ce5ea6f69 Mon Sep 17 00:00:00 2001 From: y21 <30553356+y21@users.noreply.github.com> Date: Tue, 6 Jun 2023 22:29:13 +0200 Subject: [PATCH 077/310] make `useless_vec` smarter --- clippy_lints/src/vec.rs | 111 +++++++++++++++++++++++++++++++++++----- 1 file changed, 97 insertions(+), 14 deletions(-) diff --git a/clippy_lints/src/vec.rs b/clippy_lints/src/vec.rs index 7329e508106..ec21f3bb54f 100644 --- a/clippy_lints/src/vec.rs +++ b/clippy_lints/src/vec.rs @@ -1,16 +1,21 @@ +use std::ops::ControlFlow; + use clippy_utils::consts::{constant, Constant}; use clippy_utils::diagnostics::span_lint_and_sugg; -use clippy_utils::higher; use clippy_utils::source::snippet_with_applicability; use clippy_utils::ty::is_copy; +use clippy_utils::visitors::for_each_local_use_after_expr; +use clippy_utils::{get_parent_expr, higher, is_trait_method}; use if_chain::if_chain; +use rustc_ast::BindingAnnotation; use rustc_errors::Applicability; -use rustc_hir::{BorrowKind, Expr, ExprKind, Mutability}; +use rustc_hir::{BorrowKind, Expr, ExprKind, Mutability, Node, PatKind}; use rustc_lint::{LateContext, LateLintPass}; use rustc_middle::ty::layout::LayoutOf; use rustc_middle::ty::{self, Ty}; use rustc_session::{declare_tool_lint, impl_lint_pass}; use rustc_span::source_map::Span; +use rustc_span::sym; #[expect(clippy::module_name_repetitions)] #[derive(Copy, Clone)] @@ -20,7 +25,7 @@ pub struct UselessVec { declare_clippy_lint! { /// ### What it does - /// Checks for usage of `&vec![..]` when using `&[..]` would + /// Checks for usage of `vec![..]` when using `[..]` would /// be possible. /// /// ### Why is this bad? @@ -46,16 +51,70 @@ declare_clippy_lint! { impl_lint_pass!(UselessVec => [USELESS_VEC]); +fn adjusts_to_slice(cx: &LateContext<'_>, e: &Expr<'_>) -> bool { + if let ty::Ref(_, ty, _) = cx.typeck_results().expr_ty_adjusted(e).kind() { + ty.is_slice() + } else { + false + } +} + +/// Checks if the given expression is a method call to a `Vec` method +/// that also exists on slices. If this returns true, it means that +/// this expression does not actually require a `Vec` and could just work with an array. +fn is_allowed_vec_method(cx: &LateContext<'_>, e: &Expr<'_>) -> bool { + const ALLOWED_METHOD_NAMES: &[&str] = &["len", "as_ptr", "as_slice", "is_empty"]; + + if let ExprKind::MethodCall(path, ..) = e.kind { + ALLOWED_METHOD_NAMES.contains(&path.ident.name.as_str()) + } else { + is_trait_method(cx, e, sym::IntoIterator) + } +} + impl<'tcx> LateLintPass<'tcx> for UselessVec { fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) { // search for `&vec![_]` expressions where the adjusted type is `&[_]` if_chain! { - if let ty::Ref(_, ty, _) = cx.typeck_results().expr_ty_adjusted(expr).kind(); - if let ty::Slice(..) = ty.kind(); + if adjusts_to_slice(cx, expr); if let ExprKind::AddrOf(BorrowKind::Ref, mutability, addressee) = expr.kind; if let Some(vec_args) = higher::VecArgs::hir(cx, addressee); then { - self.check_vec_macro(cx, &vec_args, mutability, expr.span); + self.check_vec_macro(cx, &vec_args, mutability, expr.span, SuggestSlice::Yes); + } + } + + // search for `let foo = vec![_]` expressions where all uses of `foo` + // adjust to slices or call a method that exist on slices (e.g. len) + if let Some(vec_args) = higher::VecArgs::hir(cx, expr) + && let Node::Local(local) = cx.tcx.hir().get_parent(expr.hir_id) + // for now ignore locals with type annotations. + // this is to avoid compile errors when doing the suggestion here: let _: Vec<_> = vec![..]; + && local.ty.is_none() + && let PatKind::Binding(BindingAnnotation(_, mutbl), id, ..) = local.pat.kind + && is_copy(cx, vec_type(cx.typeck_results().expr_ty_adjusted(expr))) + { + let only_slice_uses = for_each_local_use_after_expr(cx, id, expr.hir_id, |expr| { + // allow indexing into a vec and some set of allowed method calls that exist on slices, too + if let Some(parent) = get_parent_expr(cx, expr) + && (adjusts_to_slice(cx, expr) + || matches!(parent.kind, ExprKind::Index(..)) + || is_allowed_vec_method(cx, parent)) + { + ControlFlow::Continue(()) + } else { + ControlFlow::Break(()) + } + }).is_continue(); + + if only_slice_uses { + self.check_vec_macro( + cx, + &vec_args, + mutbl, + expr.span.ctxt().outer_expn_data().call_site, + SuggestSlice::No + ); } } @@ -67,12 +126,20 @@ impl<'tcx> LateLintPass<'tcx> for UselessVec { then { // report the error around the `vec!` not inside `:` let span = arg.span.ctxt().outer_expn_data().call_site; - self.check_vec_macro(cx, &vec_args, Mutability::Not, span); + self.check_vec_macro(cx, &vec_args, Mutability::Not, span, SuggestSlice::Yes); } } } } +#[derive(Copy, Clone)] +enum SuggestSlice { + /// Suggest using a slice `&[..]` / `&mut [..]` + Yes, + /// Suggest using an array: `[..]` + No, +} + impl UselessVec { fn check_vec_macro<'tcx>( self, @@ -80,8 +147,15 @@ impl UselessVec { vec_args: &higher::VecArgs<'tcx>, mutability: Mutability, span: Span, + suggest_slice: SuggestSlice, ) { let mut applicability = Applicability::MachineApplicable; + + let (borrow_prefix_mut, borrow_prefix) = match suggest_slice { + SuggestSlice::Yes => ("&mut ", "&"), + SuggestSlice::No => ("", ""), + }; + let snippet = match *vec_args { higher::VecArgs::Repeat(elem, len) => { if let Some(Constant::Int(len_constant)) = constant(cx, cx.typeck_results(), len) { @@ -93,14 +167,14 @@ impl UselessVec { match mutability { Mutability::Mut => { format!( - "&mut [{}; {}]", + "{borrow_prefix_mut}[{}; {}]", snippet_with_applicability(cx, elem.span, "elem", &mut applicability), snippet_with_applicability(cx, len.span, "len", &mut applicability) ) }, Mutability::Not => { format!( - "&[{}; {}]", + "{borrow_prefix}[{}; {}]", snippet_with_applicability(cx, elem.span, "elem", &mut applicability), snippet_with_applicability(cx, len.span, "len", &mut applicability) ) @@ -120,18 +194,21 @@ impl UselessVec { match mutability { Mutability::Mut => { format!( - "&mut [{}]", + "{borrow_prefix_mut}[{}]", snippet_with_applicability(cx, span, "..", &mut applicability) ) }, Mutability::Not => { - format!("&[{}]", snippet_with_applicability(cx, span, "..", &mut applicability)) + format!( + "{borrow_prefix}[{}]", + snippet_with_applicability(cx, span, "..", &mut applicability) + ) }, } } else { match mutability { - Mutability::Mut => "&mut []".into(), - Mutability::Not => "&[]".into(), + Mutability::Mut => format!("{borrow_prefix_mut}[]"), + Mutability::Not => format!("{borrow_prefix}[]"), } } }, @@ -142,7 +219,13 @@ impl UselessVec { USELESS_VEC, span, "useless use of `vec!`", - "you can use a slice directly", + &format!( + "you can use {} directly", + match suggest_slice { + SuggestSlice::Yes => "a slice", + SuggestSlice::No => "an array", + } + ), snippet, applicability, ); From 05f78e530a78ad4391dd39bb8e78978913de175e Mon Sep 17 00:00:00 2001 From: y21 <30553356+y21@users.noreply.github.com> Date: Tue, 6 Jun 2023 22:56:57 +0200 Subject: [PATCH 078/310] allow the lint in a bunch of tests --- tests/ui-toml/suppress_lint_in_const/test.rs | 7 ++- .../suppress_lint_in_const/test.stderr | 18 +++--- .../conf_disallowed_methods.rs | 1 + .../conf_disallowed_methods.stderr | 28 ++++----- tests/ui-toml/unwrap_used/unwrap_used.rs | 7 ++- tests/ui-toml/unwrap_used/unwrap_used.stderr | 58 +++++++++--------- tests/ui/assign_ops.fixed | 2 +- tests/ui/assign_ops.rs | 2 +- tests/ui/bytecount.rs | 2 +- tests/ui/collection_is_never_read.rs | 2 +- tests/ui/comparison_to_empty.fixed | 1 + tests/ui/comparison_to_empty.rs | 1 + tests/ui/comparison_to_empty.stderr | 8 +-- tests/ui/deref_addrof.fixed | 2 +- tests/ui/deref_addrof.rs | 2 +- tests/ui/eq_op_macros.rs | 1 + tests/ui/eq_op_macros.stderr | 24 ++++---- tests/ui/excessive_precision.fixed | 2 +- tests/ui/excessive_precision.rs | 2 +- tests/ui/explicit_counter_loop.rs | 2 +- tests/ui/find_map.rs | 1 + tests/ui/for_loop_fixable.fixed | 2 +- tests/ui/for_loop_fixable.rs | 2 +- tests/ui/for_loop_unfixable.rs | 7 ++- tests/ui/for_loop_unfixable.stderr | 2 +- tests/ui/format.fixed | 3 +- tests/ui/format.rs | 3 +- tests/ui/format.stderr | 30 +++++----- tests/ui/get_first.fixed | 1 + tests/ui/get_first.rs | 1 + tests/ui/get_first.stderr | 6 +- tests/ui/get_last_with_len.fixed | 2 +- tests/ui/get_last_with_len.rs | 2 +- tests/ui/get_unwrap.fixed | 7 ++- tests/ui/get_unwrap.rs | 7 ++- tests/ui/get_unwrap.stderr | 54 ++++++++--------- tests/ui/indexing_slicing_index.rs | 7 ++- tests/ui/indexing_slicing_index.stderr | 26 ++++---- tests/ui/indexing_slicing_slice.rs | 2 +- tests/ui/iter_count.fixed | 3 +- tests/ui/iter_count.rs | 3 +- tests/ui/iter_count.stderr | 50 ++++++++-------- tests/ui/iter_next_slice.fixed | 1 + tests/ui/iter_next_slice.rs | 1 + tests/ui/iter_next_slice.stderr | 8 +-- tests/ui/iter_nth.rs | 1 + tests/ui/iter_nth.stderr | 14 ++--- tests/ui/iter_overeager_cloned.fixed | 2 +- tests/ui/iter_overeager_cloned.rs | 2 +- tests/ui/iter_skip_next.fixed | 1 + tests/ui/iter_skip_next.rs | 1 + tests/ui/iter_skip_next.stderr | 14 ++--- tests/ui/iterator_step_by_zero.rs | 1 + tests/ui/iterator_step_by_zero.stderr | 14 ++--- tests/ui/manual_assert.edition2018.fixed | 2 +- tests/ui/manual_assert.edition2021.fixed | 2 +- tests/ui/manual_assert.rs | 2 +- tests/ui/manual_filter.fixed | 2 +- tests/ui/manual_filter.rs | 2 +- tests/ui/manual_filter_map.fixed | 1 + tests/ui/manual_filter_map.rs | 1 + tests/ui/manual_filter_map.stderr | 54 ++++++++--------- tests/ui/manual_find_map.fixed | 1 + tests/ui/manual_find_map.rs | 1 + tests/ui/manual_find_map.stderr | 60 +++++++++---------- .../ui/manual_memcpy/without_loop_counters.rs | 1 + .../without_loop_counters.stderr | 26 ++++---- tests/ui/map_clone.fixed | 3 +- tests/ui/map_clone.rs | 3 +- tests/ui/map_clone.stderr | 12 ++-- tests/ui/match_on_vec_items.rs | 1 + tests/ui/match_on_vec_items.stderr | 16 ++--- tests/ui/match_single_binding.fixed | 3 +- tests/ui/match_single_binding.rs | 3 +- tests/ui/match_single_binding.stderr | 48 +++++++-------- tests/ui/methods.rs | 1 + tests/ui/methods.stderr | 4 +- tests/ui/methods_fixable.fixed | 1 + tests/ui/methods_fixable.rs | 1 + tests/ui/methods_fixable.stderr | 2 +- tests/ui/needless_collect_indirect.rs | 2 +- tests/ui/needless_late_init.fixed | 3 +- tests/ui/needless_late_init.rs | 3 +- tests/ui/needless_late_init.stderr | 32 +++++----- tests/ui/needless_option_as_deref.fixed | 1 + tests/ui/needless_option_as_deref.rs | 1 + tests/ui/needless_option_as_deref.stderr | 6 +- tests/ui/needless_range_loop.rs | 2 +- tests/ui/needless_range_loop2.rs | 1 + tests/ui/needless_range_loop2.stderr | 16 ++--- tests/ui/no_effect.rs | 3 +- tests/ui/no_effect.stderr | 58 +++++++++--------- tests/ui/nonminimal_bool.rs | 1 + tests/ui/nonminimal_bool.stderr | 26 ++++---- tests/ui/option_as_ref_deref.fixed | 2 +- tests/ui/option_as_ref_deref.rs | 2 +- tests/ui/or_fun_call.fixed | 7 ++- tests/ui/or_fun_call.rs | 7 ++- tests/ui/or_fun_call.stderr | 56 ++++++++--------- tests/ui/ptr_offset_with_cast.fixed | 2 +- tests/ui/ptr_offset_with_cast.rs | 2 +- tests/ui/range.rs | 1 + tests/ui/range.stderr | 2 +- tests/ui/rc_clone_in_vec_init/arc.rs | 1 + tests/ui/rc_clone_in_vec_init/arc.stderr | 8 +-- tests/ui/rc_clone_in_vec_init/rc.rs | 1 + tests/ui/rc_clone_in_vec_init/rc.stderr | 8 +-- tests/ui/rc_clone_in_vec_init/weak.rs | 1 + tests/ui/rc_clone_in_vec_init/weak.stderr | 16 ++--- tests/ui/search_is_some.rs | 1 + tests/ui/search_is_some.stderr | 16 ++--- 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/self_assignment.rs | 1 + tests/ui/self_assignment.stderr | 22 +++---- tests/ui/skip_while_next.rs | 2 +- tests/ui/stable_sort_primitive.fixed | 1 + tests/ui/stable_sort_primitive.rs | 1 + tests/ui/stable_sort_primitive.stderr | 14 ++--- tests/ui/swap.fixed | 3 +- tests/ui/swap.rs | 3 +- tests/ui/swap.stderr | 34 +++++------ tests/ui/toplevel_ref_arg.fixed | 2 +- tests/ui/toplevel_ref_arg.rs | 2 +- tests/ui/type_complexity.rs | 2 +- tests/ui/unit_return_expecting_ord.rs | 1 + tests/ui/unit_return_expecting_ord.stderr | 12 ++-- tests/ui/unnecessary_join.fixed | 2 +- tests/ui/unnecessary_join.rs | 2 +- tests/ui/unnecessary_sort_by.fixed | 2 +- tests/ui/unnecessary_sort_by.rs | 2 +- tests/ui/vec.fixed | 46 ++++++++++++++ tests/ui/vec.rs | 46 ++++++++++++++ tests/ui/vec.stderr | 42 +++++++++---- tests/ui/while_let_on_iterator.fixed | 3 +- tests/ui/while_let_on_iterator.rs | 3 +- tests/ui/while_let_on_iterator.stderr | 52 ++++++++-------- 139 files changed, 751 insertions(+), 551 deletions(-) diff --git a/tests/ui-toml/suppress_lint_in_const/test.rs b/tests/ui-toml/suppress_lint_in_const/test.rs index 5a2df9f6c5d..068b47bd09d 100644 --- a/tests/ui-toml/suppress_lint_in_const/test.rs +++ b/tests/ui-toml/suppress_lint_in_const/test.rs @@ -3,7 +3,12 @@ // We also check the out_of_bounds_indexing lint here, because it lints similar things and // we want to avoid false positives. #![warn(clippy::out_of_bounds_indexing)] -#![allow(unconditional_panic, clippy::no_effect, clippy::unnecessary_operation)] +#![allow( + unconditional_panic, + clippy::no_effect, + clippy::unnecessary_operation, + clippy::useless_vec +)] const ARR: [i32; 2] = [1, 2]; const REF: &i32 = &ARR[idx()]; // Ok, should not produce stderr, since `suppress-restriction-lint-in-const` is set true. diff --git a/tests/ui-toml/suppress_lint_in_const/test.stderr b/tests/ui-toml/suppress_lint_in_const/test.stderr index bc178b7e131..db88b1cbecb 100644 --- a/tests/ui-toml/suppress_lint_in_const/test.stderr +++ b/tests/ui-toml/suppress_lint_in_const/test.stderr @@ -1,17 +1,17 @@ error[E0080]: evaluation of `main::{constant#3}` failed - --> $DIR/test.rs:31:14 + --> $DIR/test.rs:36:14 | LL | const { &ARR[idx4()] }; // Ok, should not produce stderr, since `suppress-restriction-lint-in-const` is set true. | ^^^^^^^^^^^ index out of bounds: the length is 2 but the index is 4 note: erroneous constant used - --> $DIR/test.rs:31:5 + --> $DIR/test.rs:36:5 | LL | const { &ARR[idx4()] }; // Ok, should not produce stderr, since `suppress-restriction-lint-in-const` is set true. | ^^^^^^^^^^^^^^^^^^^^^^ error: indexing may panic - --> $DIR/test.rs:22:5 + --> $DIR/test.rs:27:5 | LL | x[index]; | ^^^^^^^^ @@ -20,7 +20,7 @@ LL | x[index]; = note: `-D clippy::indexing-slicing` implied by `-D warnings` error: indexing may panic - --> $DIR/test.rs:38:5 + --> $DIR/test.rs:43:5 | LL | v[0]; | ^^^^ @@ -28,7 +28,7 @@ LL | v[0]; = help: consider using `.get(n)` or `.get_mut(n)` instead error: indexing may panic - --> $DIR/test.rs:39:5 + --> $DIR/test.rs:44:5 | LL | v[10]; | ^^^^^ @@ -36,7 +36,7 @@ LL | v[10]; = help: consider using `.get(n)` or `.get_mut(n)` instead error: indexing may panic - --> $DIR/test.rs:40:5 + --> $DIR/test.rs:45:5 | LL | v[1 << 3]; | ^^^^^^^^^ @@ -44,7 +44,7 @@ LL | v[1 << 3]; = help: consider using `.get(n)` or `.get_mut(n)` instead error: indexing may panic - --> $DIR/test.rs:46:5 + --> $DIR/test.rs:51:5 | LL | v[N]; | ^^^^ @@ -52,7 +52,7 @@ LL | v[N]; = help: consider using `.get(n)` or `.get_mut(n)` instead error: indexing may panic - --> $DIR/test.rs:47:5 + --> $DIR/test.rs:52:5 | LL | v[M]; | ^^^^ @@ -60,7 +60,7 @@ LL | v[M]; = help: consider using `.get(n)` or `.get_mut(n)` instead error[E0080]: evaluation of constant value failed - --> $DIR/test.rs:10:24 + --> $DIR/test.rs:15:24 | LL | const REF_ERR: &i32 = &ARR[idx4()]; // Ok, let rustc handle const contexts. | ^^^^^^^^^^^ index out of bounds: the length is 2 but the index is 4 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 8e1a1710a6c..ebbc7fea328 100644 --- a/tests/ui-toml/toml_disallowed_methods/conf_disallowed_methods.rs +++ b/tests/ui-toml/toml_disallowed_methods/conf_disallowed_methods.rs @@ -1,6 +1,7 @@ //@compile-flags: --crate-name conf_disallowed_methods #![warn(clippy::disallowed_methods)] +#![allow(clippy::useless_vec)] extern crate futures; extern crate regex; diff --git a/tests/ui-toml/toml_disallowed_methods/conf_disallowed_methods.stderr b/tests/ui-toml/toml_disallowed_methods/conf_disallowed_methods.stderr index 148d1cae51f..3dc83a40780 100644 --- a/tests/ui-toml/toml_disallowed_methods/conf_disallowed_methods.stderr +++ b/tests/ui-toml/toml_disallowed_methods/conf_disallowed_methods.stderr @@ -1,5 +1,5 @@ error: use of a disallowed method `regex::Regex::new` - --> $DIR/conf_disallowed_methods.rs:33:14 + --> $DIR/conf_disallowed_methods.rs:34:14 | LL | let re = Regex::new(r"ab.*c").unwrap(); | ^^^^^^^^^^^^^^^^^^^^ @@ -7,7 +7,7 @@ LL | let re = Regex::new(r"ab.*c").unwrap(); = note: `-D clippy::disallowed-methods` implied by `-D warnings` error: use of a disallowed method `regex::Regex::is_match` - --> $DIR/conf_disallowed_methods.rs:34:5 + --> $DIR/conf_disallowed_methods.rs:35:5 | LL | re.is_match("abc"); | ^^^^^^^^^^^^^^^^^^ @@ -15,73 +15,73 @@ LL | re.is_match("abc"); = note: no matching allowed (from clippy.toml) error: use of a disallowed method `std::iter::Iterator::sum` - --> $DIR/conf_disallowed_methods.rs:37:5 + --> $DIR/conf_disallowed_methods.rs:38:5 | LL | a.iter().sum::(); | ^^^^^^^^^^^^^^^^^^^^^ error: use of a disallowed method `slice::sort_unstable` - --> $DIR/conf_disallowed_methods.rs:39:5 + --> $DIR/conf_disallowed_methods.rs:40:5 | LL | a.sort_unstable(); | ^^^^^^^^^^^^^^^^^ error: use of a disallowed method `f32::clamp` - --> $DIR/conf_disallowed_methods.rs:41:13 + --> $DIR/conf_disallowed_methods.rs:42:13 | LL | let _ = 2.0f32.clamp(3.0f32, 4.0f32); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: use of a disallowed method `regex::Regex::new` - --> $DIR/conf_disallowed_methods.rs:44:61 + --> $DIR/conf_disallowed_methods.rs:45:61 | LL | let indirect: fn(&str) -> Result = Regex::new; | ^^^^^^^^^^ error: use of a disallowed method `f32::clamp` - --> $DIR/conf_disallowed_methods.rs:47:28 + --> $DIR/conf_disallowed_methods.rs:48:28 | LL | let in_call = Box::new(f32::clamp); | ^^^^^^^^^^ error: use of a disallowed method `regex::Regex::new` - --> $DIR/conf_disallowed_methods.rs:48:53 + --> $DIR/conf_disallowed_methods.rs:49:53 | LL | let in_method_call = ["^", "$"].into_iter().map(Regex::new); | ^^^^^^^^^^ error: use of a disallowed method `futures::stream::select_all` - --> $DIR/conf_disallowed_methods.rs:51:31 + --> $DIR/conf_disallowed_methods.rs:52:31 | LL | let same_name_as_module = select_all(vec![empty::<()>()]); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: use of a disallowed method `conf_disallowed_methods::local_fn` - --> $DIR/conf_disallowed_methods.rs:53:5 + --> $DIR/conf_disallowed_methods.rs:54:5 | LL | local_fn(); | ^^^^^^^^^^ error: use of a disallowed method `conf_disallowed_methods::local_mod::f` - --> $DIR/conf_disallowed_methods.rs:54:5 + --> $DIR/conf_disallowed_methods.rs:55:5 | LL | local_mod::f(); | ^^^^^^^^^^^^^^ error: use of a disallowed method `conf_disallowed_methods::Struct::method` - --> $DIR/conf_disallowed_methods.rs:56:5 + --> $DIR/conf_disallowed_methods.rs:57:5 | LL | s.method(); | ^^^^^^^^^^ error: use of a disallowed method `conf_disallowed_methods::Trait::provided_method` - --> $DIR/conf_disallowed_methods.rs:57:5 + --> $DIR/conf_disallowed_methods.rs:58:5 | LL | s.provided_method(); | ^^^^^^^^^^^^^^^^^^^ error: use of a disallowed method `conf_disallowed_methods::Trait::implemented_method` - --> $DIR/conf_disallowed_methods.rs:58:5 + --> $DIR/conf_disallowed_methods.rs:59:5 | LL | s.implemented_method(); | ^^^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui-toml/unwrap_used/unwrap_used.rs b/tests/ui-toml/unwrap_used/unwrap_used.rs index 5d3e800cadd..9f4d0ef1bf9 100644 --- a/tests/ui-toml/unwrap_used/unwrap_used.rs +++ b/tests/ui-toml/unwrap_used/unwrap_used.rs @@ -1,6 +1,11 @@ //@compile-flags: --test -#![allow(unused_mut, clippy::get_first, clippy::from_iter_instead_of_collect)] +#![allow( + unused_mut, + clippy::get_first, + clippy::from_iter_instead_of_collect, + clippy::useless_vec +)] #![warn(clippy::unwrap_used)] #![deny(clippy::get_unwrap)] diff --git a/tests/ui-toml/unwrap_used/unwrap_used.stderr b/tests/ui-toml/unwrap_used/unwrap_used.stderr index 8a32750e3c9..706f9a89cbb 100644 --- a/tests/ui-toml/unwrap_used/unwrap_used.stderr +++ b/tests/ui-toml/unwrap_used/unwrap_used.stderr @@ -1,17 +1,17 @@ error: called `.get().unwrap()` on a slice. Using `[]` is more clear and more concise - --> $DIR/unwrap_used.rs:35:17 + --> $DIR/unwrap_used.rs:40:17 | LL | let _ = boxed_slice.get(1).unwrap(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `&boxed_slice[1]` | note: the lint level is defined here - --> $DIR/unwrap_used.rs:5:9 + --> $DIR/unwrap_used.rs:10:9 | LL | #![deny(clippy::get_unwrap)] | ^^^^^^^^^^^^^^^^^^ error: used `unwrap()` on an `Option` value - --> $DIR/unwrap_used.rs:35:17 + --> $DIR/unwrap_used.rs:40:17 | LL | let _ = boxed_slice.get(1).unwrap(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -20,13 +20,13 @@ LL | let _ = boxed_slice.get(1).unwrap(); = note: `-D clippy::unwrap-used` implied by `-D warnings` error: called `.get().unwrap()` on a slice. Using `[]` is more clear and more concise - --> $DIR/unwrap_used.rs:36:17 + --> $DIR/unwrap_used.rs:41:17 | LL | let _ = some_slice.get(0).unwrap(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `&some_slice[0]` error: used `unwrap()` on an `Option` value - --> $DIR/unwrap_used.rs:36:17 + --> $DIR/unwrap_used.rs:41:17 | LL | let _ = some_slice.get(0).unwrap(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -34,13 +34,13 @@ LL | let _ = some_slice.get(0).unwrap(); = help: if you don't want to handle the `None` case gracefully, consider using `expect()` to provide a better panic message error: called `.get().unwrap()` on a Vec. Using `[]` is more clear and more concise - --> $DIR/unwrap_used.rs:37:17 + --> $DIR/unwrap_used.rs:42:17 | LL | let _ = some_vec.get(0).unwrap(); | ^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `&some_vec[0]` error: used `unwrap()` on an `Option` value - --> $DIR/unwrap_used.rs:37:17 + --> $DIR/unwrap_used.rs:42:17 | LL | let _ = some_vec.get(0).unwrap(); | ^^^^^^^^^^^^^^^^^^^^^^^^ @@ -48,13 +48,13 @@ LL | let _ = some_vec.get(0).unwrap(); = help: if you don't want to handle the `None` case gracefully, consider using `expect()` to provide a better panic message error: called `.get().unwrap()` on a VecDeque. Using `[]` is more clear and more concise - --> $DIR/unwrap_used.rs:38:17 + --> $DIR/unwrap_used.rs:43:17 | LL | let _ = some_vecdeque.get(0).unwrap(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `&some_vecdeque[0]` error: used `unwrap()` on an `Option` value - --> $DIR/unwrap_used.rs:38:17 + --> $DIR/unwrap_used.rs:43:17 | LL | let _ = some_vecdeque.get(0).unwrap(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -62,13 +62,13 @@ LL | let _ = some_vecdeque.get(0).unwrap(); = help: if you don't want to handle the `None` case gracefully, consider using `expect()` to provide a better panic message error: called `.get().unwrap()` on a HashMap. Using `[]` is more clear and more concise - --> $DIR/unwrap_used.rs:39:17 + --> $DIR/unwrap_used.rs:44:17 | LL | let _ = some_hashmap.get(&1).unwrap(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `&some_hashmap[&1]` error: used `unwrap()` on an `Option` value - --> $DIR/unwrap_used.rs:39:17 + --> $DIR/unwrap_used.rs:44:17 | LL | let _ = some_hashmap.get(&1).unwrap(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -76,13 +76,13 @@ LL | let _ = some_hashmap.get(&1).unwrap(); = help: if you don't want to handle the `None` case gracefully, consider using `expect()` to provide a better panic message error: called `.get().unwrap()` on a BTreeMap. Using `[]` is more clear and more concise - --> $DIR/unwrap_used.rs:40:17 + --> $DIR/unwrap_used.rs:45:17 | LL | let _ = some_btreemap.get(&1).unwrap(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `&some_btreemap[&1]` error: used `unwrap()` on an `Option` value - --> $DIR/unwrap_used.rs:40:17 + --> $DIR/unwrap_used.rs:45:17 | LL | let _ = some_btreemap.get(&1).unwrap(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -90,13 +90,13 @@ LL | let _ = some_btreemap.get(&1).unwrap(); = help: if you don't want to handle the `None` case gracefully, consider using `expect()` to provide a better panic message error: called `.get().unwrap()` on a slice. Using `[]` is more clear and more concise - --> $DIR/unwrap_used.rs:44:21 + --> $DIR/unwrap_used.rs:49:21 | LL | let _: u8 = *boxed_slice.get(1).unwrap(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `boxed_slice[1]` error: used `unwrap()` on an `Option` value - --> $DIR/unwrap_used.rs:44:22 + --> $DIR/unwrap_used.rs:49:22 | LL | let _: u8 = *boxed_slice.get(1).unwrap(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -104,13 +104,13 @@ LL | let _: u8 = *boxed_slice.get(1).unwrap(); = help: if you don't want to handle the `None` case gracefully, consider using `expect()` to provide a better panic message error: called `.get_mut().unwrap()` on a slice. Using `[]` is more clear and more concise - --> $DIR/unwrap_used.rs:49:9 + --> $DIR/unwrap_used.rs:54:9 | LL | *boxed_slice.get_mut(0).unwrap() = 1; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `boxed_slice[0]` error: used `unwrap()` on an `Option` value - --> $DIR/unwrap_used.rs:49:10 + --> $DIR/unwrap_used.rs:54:10 | LL | *boxed_slice.get_mut(0).unwrap() = 1; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -118,13 +118,13 @@ LL | *boxed_slice.get_mut(0).unwrap() = 1; = help: if you don't want to handle the `None` case gracefully, consider using `expect()` to provide a better panic message error: called `.get_mut().unwrap()` on a slice. Using `[]` is more clear and more concise - --> $DIR/unwrap_used.rs:50:9 + --> $DIR/unwrap_used.rs:55:9 | LL | *some_slice.get_mut(0).unwrap() = 1; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `some_slice[0]` error: used `unwrap()` on an `Option` value - --> $DIR/unwrap_used.rs:50:10 + --> $DIR/unwrap_used.rs:55:10 | LL | *some_slice.get_mut(0).unwrap() = 1; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -132,13 +132,13 @@ LL | *some_slice.get_mut(0).unwrap() = 1; = help: if you don't want to handle the `None` case gracefully, consider using `expect()` to provide a better panic message error: called `.get_mut().unwrap()` on a Vec. Using `[]` is more clear and more concise - --> $DIR/unwrap_used.rs:51:9 + --> $DIR/unwrap_used.rs:56:9 | LL | *some_vec.get_mut(0).unwrap() = 1; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `some_vec[0]` error: used `unwrap()` on an `Option` value - --> $DIR/unwrap_used.rs:51:10 + --> $DIR/unwrap_used.rs:56:10 | LL | *some_vec.get_mut(0).unwrap() = 1; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -146,13 +146,13 @@ LL | *some_vec.get_mut(0).unwrap() = 1; = help: if you don't want to handle the `None` case gracefully, consider using `expect()` to provide a better panic message error: called `.get_mut().unwrap()` on a VecDeque. Using `[]` is more clear and more concise - --> $DIR/unwrap_used.rs:52:9 + --> $DIR/unwrap_used.rs:57:9 | LL | *some_vecdeque.get_mut(0).unwrap() = 1; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `some_vecdeque[0]` error: used `unwrap()` on an `Option` value - --> $DIR/unwrap_used.rs:52:10 + --> $DIR/unwrap_used.rs:57:10 | LL | *some_vecdeque.get_mut(0).unwrap() = 1; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -160,13 +160,13 @@ LL | *some_vecdeque.get_mut(0).unwrap() = 1; = help: if you don't want to handle the `None` case gracefully, consider using `expect()` to provide a better panic message error: called `.get().unwrap()` on a Vec. Using `[]` is more clear and more concise - --> $DIR/unwrap_used.rs:64:17 + --> $DIR/unwrap_used.rs:69:17 | LL | let _ = some_vec.get(0..1).unwrap().to_vec(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `some_vec[0..1]` error: used `unwrap()` on an `Option` value - --> $DIR/unwrap_used.rs:64:17 + --> $DIR/unwrap_used.rs:69:17 | LL | let _ = some_vec.get(0..1).unwrap().to_vec(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -174,13 +174,13 @@ LL | let _ = some_vec.get(0..1).unwrap().to_vec(); = help: if you don't want to handle the `None` case gracefully, consider using `expect()` to provide a better panic message error: called `.get_mut().unwrap()` on a Vec. Using `[]` is more clear and more concise - --> $DIR/unwrap_used.rs:65:17 + --> $DIR/unwrap_used.rs:70:17 | LL | let _ = some_vec.get_mut(0..1).unwrap().to_vec(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `some_vec[0..1]` error: used `unwrap()` on an `Option` value - --> $DIR/unwrap_used.rs:65:17 + --> $DIR/unwrap_used.rs:70:17 | LL | let _ = some_vec.get_mut(0..1).unwrap().to_vec(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -188,13 +188,13 @@ LL | let _ = some_vec.get_mut(0..1).unwrap().to_vec(); = help: if you don't want to handle the `None` case gracefully, consider using `expect()` to provide a better panic message error: called `.get().unwrap()` on a slice. Using `[]` is more clear and more concise - --> $DIR/unwrap_used.rs:72:13 + --> $DIR/unwrap_used.rs:77:13 | LL | let _ = boxed_slice.get(1).unwrap(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `&boxed_slice[1]` error: called `.get().unwrap()` on a slice. Using `[]` is more clear and more concise - --> $DIR/unwrap_used.rs:90:17 + --> $DIR/unwrap_used.rs:95:17 | LL | let _ = Box::new([0]).get(1).unwrap(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `&Box::new([0])[1]` diff --git a/tests/ui/assign_ops.fixed b/tests/ui/assign_ops.fixed index b50682ea00c..ef45e97d1de 100644 --- a/tests/ui/assign_ops.fixed +++ b/tests/ui/assign_ops.fixed @@ -2,7 +2,7 @@ use core::num::Wrapping; -#[allow(dead_code, unused_assignments)] +#[allow(dead_code, unused_assignments, clippy::useless_vec)] #[warn(clippy::assign_op_pattern)] fn main() { let mut a = 5; diff --git a/tests/ui/assign_ops.rs b/tests/ui/assign_ops.rs index 780d2d040f1..ae87afc485e 100644 --- a/tests/ui/assign_ops.rs +++ b/tests/ui/assign_ops.rs @@ -2,7 +2,7 @@ use core::num::Wrapping; -#[allow(dead_code, unused_assignments)] +#[allow(dead_code, unused_assignments, clippy::useless_vec)] #[warn(clippy::assign_op_pattern)] fn main() { let mut a = 5; diff --git a/tests/ui/bytecount.rs b/tests/ui/bytecount.rs index d3ad26921bf..4d168bfeab9 100644 --- a/tests/ui/bytecount.rs +++ b/tests/ui/bytecount.rs @@ -1,4 +1,4 @@ -#![allow(clippy::needless_borrow)] +#![allow(clippy::needless_borrow, clippy::useless_vec)] #[deny(clippy::naive_bytecount)] fn main() { diff --git a/tests/ui/collection_is_never_read.rs b/tests/ui/collection_is_never_read.rs index 2c1a42a72c1..e02c1c57230 100644 --- a/tests/ui/collection_is_never_read.rs +++ b/tests/ui/collection_is_never_read.rs @@ -1,4 +1,4 @@ -#![allow(unused)] +#![allow(unused, clippy::useless_vec)] #![warn(clippy::collection_is_never_read)] use std::collections::{HashMap, HashSet}; diff --git a/tests/ui/comparison_to_empty.fixed b/tests/ui/comparison_to_empty.fixed index dd2615ab25c..c92dd509ebb 100644 --- a/tests/ui/comparison_to_empty.fixed +++ b/tests/ui/comparison_to_empty.fixed @@ -1,6 +1,7 @@ //@run-rustfix #![warn(clippy::comparison_to_empty)] +#![allow(clippy::useless_vec)] fn main() { // Disallow comparisons to empty diff --git a/tests/ui/comparison_to_empty.rs b/tests/ui/comparison_to_empty.rs index 5462784c6ac..b3489714380 100644 --- a/tests/ui/comparison_to_empty.rs +++ b/tests/ui/comparison_to_empty.rs @@ -1,6 +1,7 @@ //@run-rustfix #![warn(clippy::comparison_to_empty)] +#![allow(clippy::useless_vec)] fn main() { // Disallow comparisons to empty diff --git a/tests/ui/comparison_to_empty.stderr b/tests/ui/comparison_to_empty.stderr index f69d6bd5255..cc09b17eb89 100644 --- a/tests/ui/comparison_to_empty.stderr +++ b/tests/ui/comparison_to_empty.stderr @@ -1,5 +1,5 @@ error: comparison to empty slice - --> $DIR/comparison_to_empty.rs:8:13 + --> $DIR/comparison_to_empty.rs:9:13 | LL | let _ = s == ""; | ^^^^^^^ help: using `is_empty` is clearer and more explicit: `s.is_empty()` @@ -7,19 +7,19 @@ LL | let _ = s == ""; = note: `-D clippy::comparison-to-empty` implied by `-D warnings` error: comparison to empty slice - --> $DIR/comparison_to_empty.rs:9:13 + --> $DIR/comparison_to_empty.rs:10:13 | LL | let _ = s != ""; | ^^^^^^^ help: using `!is_empty` is clearer and more explicit: `!s.is_empty()` error: comparison to empty slice - --> $DIR/comparison_to_empty.rs:12:13 + --> $DIR/comparison_to_empty.rs:13:13 | LL | let _ = v == []; | ^^^^^^^ help: using `is_empty` is clearer and more explicit: `v.is_empty()` error: comparison to empty slice - --> $DIR/comparison_to_empty.rs:13:13 + --> $DIR/comparison_to_empty.rs:14:13 | LL | let _ = v != []; | ^^^^^^^ help: using `!is_empty` is clearer and more explicit: `!v.is_empty()` diff --git a/tests/ui/deref_addrof.fixed b/tests/ui/deref_addrof.fixed index b27d3bc1002..0bf739fe2d1 100644 --- a/tests/ui/deref_addrof.fixed +++ b/tests/ui/deref_addrof.fixed @@ -1,7 +1,7 @@ //@run-rustfix //@aux-build:proc_macros.rs -#![allow(clippy::return_self_not_must_use)] +#![allow(clippy::return_self_not_must_use, clippy::useless_vec)] #![warn(clippy::deref_addrof)] extern crate proc_macros; diff --git a/tests/ui/deref_addrof.rs b/tests/ui/deref_addrof.rs index 825090c7c12..2d796a24fec 100644 --- a/tests/ui/deref_addrof.rs +++ b/tests/ui/deref_addrof.rs @@ -1,7 +1,7 @@ //@run-rustfix //@aux-build:proc_macros.rs -#![allow(clippy::return_self_not_must_use)] +#![allow(clippy::return_self_not_must_use, clippy::useless_vec)] #![warn(clippy::deref_addrof)] extern crate proc_macros; diff --git a/tests/ui/eq_op_macros.rs b/tests/ui/eq_op_macros.rs index 6b5b31a1a2e..48240677228 100644 --- a/tests/ui/eq_op_macros.rs +++ b/tests/ui/eq_op_macros.rs @@ -1,4 +1,5 @@ #![warn(clippy::eq_op)] +#![allow(clippy::useless_vec)] // lint also in macro definition macro_rules! assert_in_macro_def { diff --git a/tests/ui/eq_op_macros.stderr b/tests/ui/eq_op_macros.stderr index cd9f1826e59..cb9b0c01862 100644 --- a/tests/ui/eq_op_macros.stderr +++ b/tests/ui/eq_op_macros.stderr @@ -1,5 +1,5 @@ error: identical args used in this `assert_eq!` macro call - --> $DIR/eq_op_macros.rs:7:20 + --> $DIR/eq_op_macros.rs:8:20 | LL | assert_eq!(a, a); | ^^^^ @@ -11,7 +11,7 @@ LL | assert_in_macro_def!(); = note: this error originates in the macro `assert_in_macro_def` (in Nightly builds, run with -Z macro-backtrace for more info) error: identical args used in this `assert_ne!` macro call - --> $DIR/eq_op_macros.rs:8:20 + --> $DIR/eq_op_macros.rs:9:20 | LL | assert_ne!(a, a); | ^^^^ @@ -22,7 +22,7 @@ LL | assert_in_macro_def!(); = note: this error originates in the macro `assert_in_macro_def` (in Nightly builds, run with -Z macro-backtrace for more info) error: identical args used in this `debug_assert_eq!` macro call - --> $DIR/eq_op_macros.rs:9:26 + --> $DIR/eq_op_macros.rs:10:26 | LL | debug_assert_eq!(a, a); | ^^^^ @@ -33,7 +33,7 @@ LL | assert_in_macro_def!(); = note: this error originates in the macro `assert_in_macro_def` (in Nightly builds, run with -Z macro-backtrace for more info) error: identical args used in this `debug_assert_ne!` macro call - --> $DIR/eq_op_macros.rs:10:26 + --> $DIR/eq_op_macros.rs:11:26 | LL | debug_assert_ne!(a, a); | ^^^^ @@ -44,49 +44,49 @@ LL | assert_in_macro_def!(); = note: this error originates in the macro `assert_in_macro_def` (in Nightly builds, run with -Z macro-backtrace for more info) error: identical args used in this `assert_eq!` macro call - --> $DIR/eq_op_macros.rs:22:16 + --> $DIR/eq_op_macros.rs:23:16 | LL | assert_eq!(a, a); | ^^^^ error: identical args used in this `assert_eq!` macro call - --> $DIR/eq_op_macros.rs:23:16 + --> $DIR/eq_op_macros.rs:24:16 | LL | assert_eq!(a + 1, a + 1); | ^^^^^^^^^^^^ error: identical args used in this `assert_ne!` macro call - --> $DIR/eq_op_macros.rs:30:16 + --> $DIR/eq_op_macros.rs:31:16 | LL | assert_ne!(a, a); | ^^^^ error: identical args used in this `assert_ne!` macro call - --> $DIR/eq_op_macros.rs:31:16 + --> $DIR/eq_op_macros.rs:32:16 | LL | assert_ne!(a + 1, a + 1); | ^^^^^^^^^^^^ error: identical args used in this `debug_assert_eq!` macro call - --> $DIR/eq_op_macros.rs:38:22 + --> $DIR/eq_op_macros.rs:39:22 | LL | debug_assert_eq!(a, a); | ^^^^ error: identical args used in this `debug_assert_eq!` macro call - --> $DIR/eq_op_macros.rs:39:22 + --> $DIR/eq_op_macros.rs:40:22 | LL | debug_assert_eq!(a + 1, a + 1); | ^^^^^^^^^^^^ error: identical args used in this `debug_assert_ne!` macro call - --> $DIR/eq_op_macros.rs:46:22 + --> $DIR/eq_op_macros.rs:47:22 | LL | debug_assert_ne!(a, a); | ^^^^ error: identical args used in this `debug_assert_ne!` macro call - --> $DIR/eq_op_macros.rs:47:22 + --> $DIR/eq_op_macros.rs:48:22 | LL | debug_assert_ne!(a + 1, a + 1); | ^^^^^^^^^^^^ diff --git a/tests/ui/excessive_precision.fixed b/tests/ui/excessive_precision.fixed index 0a07957386c..1bcaa33a049 100644 --- a/tests/ui/excessive_precision.fixed +++ b/tests/ui/excessive_precision.fixed @@ -1,6 +1,6 @@ //@run-rustfix #![warn(clippy::excessive_precision)] -#![allow(dead_code, unused_variables, clippy::print_literal)] +#![allow(dead_code, unused_variables, clippy::print_literal, clippy::useless_vec)] fn main() { // Consts diff --git a/tests/ui/excessive_precision.rs b/tests/ui/excessive_precision.rs index 62a832caa67..cee937e07e1 100644 --- a/tests/ui/excessive_precision.rs +++ b/tests/ui/excessive_precision.rs @@ -1,6 +1,6 @@ //@run-rustfix #![warn(clippy::excessive_precision)] -#![allow(dead_code, unused_variables, clippy::print_literal)] +#![allow(dead_code, unused_variables, clippy::print_literal, clippy::useless_vec)] fn main() { // Consts diff --git a/tests/ui/explicit_counter_loop.rs b/tests/ui/explicit_counter_loop.rs index 46565a97f00..08e6de5dc19 100644 --- a/tests/ui/explicit_counter_loop.rs +++ b/tests/ui/explicit_counter_loop.rs @@ -1,5 +1,5 @@ #![warn(clippy::explicit_counter_loop)] -#![allow(clippy::uninlined_format_args)] +#![allow(clippy::uninlined_format_args, clippy::useless_vec)] fn main() { let mut vec = vec![1, 2, 3, 4]; diff --git a/tests/ui/find_map.rs b/tests/ui/find_map.rs index 88d3b0e7490..bbd395d50ef 100644 --- a/tests/ui/find_map.rs +++ b/tests/ui/find_map.rs @@ -1,4 +1,5 @@ #![warn(clippy::all, clippy::pedantic)] +#![allow(clippy::useless_vec)] #[derive(Debug, Copy, Clone)] enum Flavor { diff --git a/tests/ui/for_loop_fixable.fixed b/tests/ui/for_loop_fixable.fixed index f578c98da15..3e74e2a02d0 100644 --- a/tests/ui/for_loop_fixable.fixed +++ b/tests/ui/for_loop_fixable.fixed @@ -1,6 +1,6 @@ //@run-rustfix #![allow(dead_code, unused)] -#![allow(clippy::uninlined_format_args)] +#![allow(clippy::uninlined_format_args, clippy::useless_vec)] use std::collections::*; diff --git a/tests/ui/for_loop_fixable.rs b/tests/ui/for_loop_fixable.rs index 42bc6de0c7d..45c6760f89e 100644 --- a/tests/ui/for_loop_fixable.rs +++ b/tests/ui/for_loop_fixable.rs @@ -1,6 +1,6 @@ //@run-rustfix #![allow(dead_code, unused)] -#![allow(clippy::uninlined_format_args)] +#![allow(clippy::uninlined_format_args, clippy::useless_vec)] use std::collections::*; diff --git a/tests/ui/for_loop_unfixable.rs b/tests/ui/for_loop_unfixable.rs index 55fb3788a8b..8e3fb99bc7c 100644 --- a/tests/ui/for_loop_unfixable.rs +++ b/tests/ui/for_loop_unfixable.rs @@ -7,7 +7,12 @@ clippy::iter_next_loop, clippy::for_kv_map )] -#[allow(clippy::linkedlist, clippy::unnecessary_mut_passed, clippy::similar_names)] +#[allow( + clippy::linkedlist, + clippy::unnecessary_mut_passed, + clippy::similar_names, + clippy::useless_vec +)] #[allow(for_loops_over_fallibles)] fn main() { let vec = vec![1, 2, 3, 4]; diff --git a/tests/ui/for_loop_unfixable.stderr b/tests/ui/for_loop_unfixable.stderr index 50a86eaa68f..8b163a142a5 100644 --- a/tests/ui/for_loop_unfixable.stderr +++ b/tests/ui/for_loop_unfixable.stderr @@ -1,5 +1,5 @@ error: you are iterating over `Iterator::next()` which is an Option; this will compile but is probably not what you want - --> $DIR/for_loop_unfixable.rs:15:15 + --> $DIR/for_loop_unfixable.rs:20:15 | LL | for _v in vec.iter().next() {} | ^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/format.fixed b/tests/ui/format.fixed index 9288956f513..f214cabef67 100644 --- a/tests/ui/format.fixed +++ b/tests/ui/format.fixed @@ -6,7 +6,8 @@ clippy::redundant_clone, clippy::to_string_in_format_args, clippy::needless_borrow, - clippy::uninlined_format_args + clippy::uninlined_format_args, + clippy::useless_vec )] struct Foo(pub String); diff --git a/tests/ui/format.rs b/tests/ui/format.rs index b2b817e0f4c..d9b28a4f7c0 100644 --- a/tests/ui/format.rs +++ b/tests/ui/format.rs @@ -6,7 +6,8 @@ clippy::redundant_clone, clippy::to_string_in_format_args, clippy::needless_borrow, - clippy::uninlined_format_args + clippy::uninlined_format_args, + clippy::useless_vec )] struct Foo(pub String); diff --git a/tests/ui/format.stderr b/tests/ui/format.stderr index 0ef0ac655d3..f456c11924e 100644 --- a/tests/ui/format.stderr +++ b/tests/ui/format.stderr @@ -1,5 +1,5 @@ error: useless use of `format!` - --> $DIR/format.rs:19:5 + --> $DIR/format.rs:20:5 | LL | format!("foo"); | ^^^^^^^^^^^^^^ help: consider using `.to_string()`: `"foo".to_string()` @@ -7,19 +7,19 @@ LL | format!("foo"); = note: `-D clippy::useless-format` implied by `-D warnings` error: useless use of `format!` - --> $DIR/format.rs:20:5 + --> $DIR/format.rs:21:5 | LL | format!("{{}}"); | ^^^^^^^^^^^^^^^ help: consider using `.to_string()`: `"{}".to_string()` error: useless use of `format!` - --> $DIR/format.rs:21:5 + --> $DIR/format.rs:22:5 | LL | format!("{{}} abc {{}}"); | ^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `.to_string()`: `"{} abc {}".to_string()` error: useless use of `format!` - --> $DIR/format.rs:22:5 + --> $DIR/format.rs:23:5 | LL | / format!( LL | | r##"foo {{}} @@ -34,67 +34,67 @@ LL ~ " bar"##.to_string(); | error: useless use of `format!` - --> $DIR/format.rs:27:13 + --> $DIR/format.rs:28:13 | LL | let _ = format!(""); | ^^^^^^^^^^^ help: consider using `String::new()`: `String::new()` error: useless use of `format!` - --> $DIR/format.rs:29:5 + --> $DIR/format.rs:30:5 | LL | format!("{}", "foo"); | ^^^^^^^^^^^^^^^^^^^^ help: consider using `.to_string()`: `"foo".to_string()` error: useless use of `format!` - --> $DIR/format.rs:37:5 + --> $DIR/format.rs:38:5 | LL | format!("{}", arg); | ^^^^^^^^^^^^^^^^^^ help: consider using `.to_string()`: `arg.to_string()` error: useless use of `format!` - --> $DIR/format.rs:67:5 + --> $DIR/format.rs:68:5 | LL | format!("{}", 42.to_string()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `.to_string()`: `42.to_string()` error: useless use of `format!` - --> $DIR/format.rs:69:5 + --> $DIR/format.rs:70:5 | LL | format!("{}", x.display().to_string()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `.to_string()`: `x.display().to_string()` error: useless use of `format!` - --> $DIR/format.rs:73:18 + --> $DIR/format.rs:74:18 | LL | let _ = Some(format!("{}", a + "bar")); | ^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `.to_string()`: `a + "bar"` error: useless use of `format!` - --> $DIR/format.rs:77:22 + --> $DIR/format.rs:78:22 | LL | let _s: String = format!("{}", &*v.join("/n")); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `.to_string()`: `(&*v.join("/n")).to_string()` error: useless use of `format!` - --> $DIR/format.rs:83:13 + --> $DIR/format.rs:84:13 | LL | let _ = format!("{x}"); | ^^^^^^^^^^^^^^ help: consider using `.to_string()`: `x.to_string()` error: useless use of `format!` - --> $DIR/format.rs:85:13 + --> $DIR/format.rs:86:13 | LL | let _ = format!("{y}", y = x); | ^^^^^^^^^^^^^^^^^^^^^ help: consider using `.to_string()`: `x.to_string()` error: useless use of `format!` - --> $DIR/format.rs:89:13 + --> $DIR/format.rs:90:13 | LL | let _ = format!("{abc}"); | ^^^^^^^^^^^^^^^^ help: consider using `.to_string()`: `abc.to_string()` error: useless use of `format!` - --> $DIR/format.rs:91:13 + --> $DIR/format.rs:92:13 | LL | let _ = format!("{xx}"); | ^^^^^^^^^^^^^^^ help: consider using `.to_string()`: `xx.to_string()` diff --git a/tests/ui/get_first.fixed b/tests/ui/get_first.fixed index ef132b79611..a29c0918a6d 100644 --- a/tests/ui/get_first.fixed +++ b/tests/ui/get_first.fixed @@ -1,5 +1,6 @@ //@run-rustfix #![warn(clippy::get_first)] +#![allow(clippy::useless_vec)] use std::collections::BTreeMap; use std::collections::HashMap; use std::collections::VecDeque; diff --git a/tests/ui/get_first.rs b/tests/ui/get_first.rs index 4d872235614..2062f3ec23a 100644 --- a/tests/ui/get_first.rs +++ b/tests/ui/get_first.rs @@ -1,5 +1,6 @@ //@run-rustfix #![warn(clippy::get_first)] +#![allow(clippy::useless_vec)] use std::collections::BTreeMap; use std::collections::HashMap; use std::collections::VecDeque; diff --git a/tests/ui/get_first.stderr b/tests/ui/get_first.stderr index 466beff9c92..4e267ba9a3b 100644 --- a/tests/ui/get_first.stderr +++ b/tests/ui/get_first.stderr @@ -1,5 +1,5 @@ error: accessing first element with `x.get(0)` - --> $DIR/get_first.rs:19:13 + --> $DIR/get_first.rs:20:13 | LL | let _ = x.get(0); // Use x.first() | ^^^^^^^^ help: try: `x.first()` @@ -7,13 +7,13 @@ LL | let _ = x.get(0); // Use x.first() = note: `-D clippy::get-first` implied by `-D warnings` error: accessing first element with `y.get(0)` - --> $DIR/get_first.rs:24:13 + --> $DIR/get_first.rs:25:13 | LL | let _ = y.get(0); // Use y.first() | ^^^^^^^^ help: try: `y.first()` error: accessing first element with `z.get(0)` - --> $DIR/get_first.rs:29:13 + --> $DIR/get_first.rs:30:13 | LL | let _ = z.get(0); // Use z.first() | ^^^^^^^^ help: try: `z.first()` diff --git a/tests/ui/get_last_with_len.fixed b/tests/ui/get_last_with_len.fixed index a58dfda7988..01a83e5bf34 100644 --- a/tests/ui/get_last_with_len.fixed +++ b/tests/ui/get_last_with_len.fixed @@ -1,7 +1,7 @@ //@run-rustfix #![warn(clippy::get_last_with_len)] -#![allow(unused)] +#![allow(unused, clippy::useless_vec)] use std::collections::VecDeque; diff --git a/tests/ui/get_last_with_len.rs b/tests/ui/get_last_with_len.rs index d626656c78f..d82484b46d3 100644 --- a/tests/ui/get_last_with_len.rs +++ b/tests/ui/get_last_with_len.rs @@ -1,7 +1,7 @@ //@run-rustfix #![warn(clippy::get_last_with_len)] -#![allow(unused)] +#![allow(unused, clippy::useless_vec)] use std::collections::VecDeque; diff --git a/tests/ui/get_unwrap.fixed b/tests/ui/get_unwrap.fixed index 4950c47ddeb..9061c9aa404 100644 --- a/tests/ui/get_unwrap.fixed +++ b/tests/ui/get_unwrap.fixed @@ -1,6 +1,11 @@ //@run-rustfix -#![allow(unused_mut, clippy::from_iter_instead_of_collect, clippy::get_first)] +#![allow( + unused_mut, + clippy::from_iter_instead_of_collect, + clippy::get_first, + clippy::useless_vec +)] #![warn(clippy::unwrap_used)] #![deny(clippy::get_unwrap)] diff --git a/tests/ui/get_unwrap.rs b/tests/ui/get_unwrap.rs index 6b1e8edb7bd..b5e4e472037 100644 --- a/tests/ui/get_unwrap.rs +++ b/tests/ui/get_unwrap.rs @@ -1,6 +1,11 @@ //@run-rustfix -#![allow(unused_mut, clippy::from_iter_instead_of_collect, clippy::get_first)] +#![allow( + unused_mut, + clippy::from_iter_instead_of_collect, + clippy::get_first, + clippy::useless_vec +)] #![warn(clippy::unwrap_used)] #![deny(clippy::get_unwrap)] diff --git a/tests/ui/get_unwrap.stderr b/tests/ui/get_unwrap.stderr index 6dee4d5b4b6..a6a34620e92 100644 --- a/tests/ui/get_unwrap.stderr +++ b/tests/ui/get_unwrap.stderr @@ -1,17 +1,17 @@ error: called `.get().unwrap()` on a slice. Using `[]` is more clear and more concise - --> $DIR/get_unwrap.rs:35:17 + --> $DIR/get_unwrap.rs:40:17 | LL | let _ = boxed_slice.get(1).unwrap(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `&boxed_slice[1]` | note: the lint level is defined here - --> $DIR/get_unwrap.rs:5:9 + --> $DIR/get_unwrap.rs:10:9 | LL | #![deny(clippy::get_unwrap)] | ^^^^^^^^^^^^^^^^^^ error: used `unwrap()` on an `Option` value - --> $DIR/get_unwrap.rs:35:17 + --> $DIR/get_unwrap.rs:40:17 | LL | let _ = boxed_slice.get(1).unwrap(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -20,13 +20,13 @@ LL | let _ = boxed_slice.get(1).unwrap(); = note: `-D clippy::unwrap-used` implied by `-D warnings` error: called `.get().unwrap()` on a slice. Using `[]` is more clear and more concise - --> $DIR/get_unwrap.rs:36:17 + --> $DIR/get_unwrap.rs:41:17 | LL | let _ = some_slice.get(0).unwrap(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `&some_slice[0]` error: used `unwrap()` on an `Option` value - --> $DIR/get_unwrap.rs:36:17 + --> $DIR/get_unwrap.rs:41:17 | LL | let _ = some_slice.get(0).unwrap(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -34,13 +34,13 @@ LL | let _ = some_slice.get(0).unwrap(); = help: if you don't want to handle the `None` case gracefully, consider using `expect()` to provide a better panic message error: called `.get().unwrap()` on a Vec. Using `[]` is more clear and more concise - --> $DIR/get_unwrap.rs:37:17 + --> $DIR/get_unwrap.rs:42:17 | LL | let _ = some_vec.get(0).unwrap(); | ^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `&some_vec[0]` error: used `unwrap()` on an `Option` value - --> $DIR/get_unwrap.rs:37:17 + --> $DIR/get_unwrap.rs:42:17 | LL | let _ = some_vec.get(0).unwrap(); | ^^^^^^^^^^^^^^^^^^^^^^^^ @@ -48,13 +48,13 @@ LL | let _ = some_vec.get(0).unwrap(); = help: if you don't want to handle the `None` case gracefully, consider using `expect()` to provide a better panic message error: called `.get().unwrap()` on a VecDeque. Using `[]` is more clear and more concise - --> $DIR/get_unwrap.rs:38:17 + --> $DIR/get_unwrap.rs:43:17 | LL | let _ = some_vecdeque.get(0).unwrap(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `&some_vecdeque[0]` error: used `unwrap()` on an `Option` value - --> $DIR/get_unwrap.rs:38:17 + --> $DIR/get_unwrap.rs:43:17 | LL | let _ = some_vecdeque.get(0).unwrap(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -62,13 +62,13 @@ LL | let _ = some_vecdeque.get(0).unwrap(); = help: if you don't want to handle the `None` case gracefully, consider using `expect()` to provide a better panic message error: called `.get().unwrap()` on a HashMap. Using `[]` is more clear and more concise - --> $DIR/get_unwrap.rs:39:17 + --> $DIR/get_unwrap.rs:44:17 | LL | let _ = some_hashmap.get(&1).unwrap(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `&some_hashmap[&1]` error: used `unwrap()` on an `Option` value - --> $DIR/get_unwrap.rs:39:17 + --> $DIR/get_unwrap.rs:44:17 | LL | let _ = some_hashmap.get(&1).unwrap(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -76,13 +76,13 @@ LL | let _ = some_hashmap.get(&1).unwrap(); = help: if you don't want to handle the `None` case gracefully, consider using `expect()` to provide a better panic message error: called `.get().unwrap()` on a BTreeMap. Using `[]` is more clear and more concise - --> $DIR/get_unwrap.rs:40:17 + --> $DIR/get_unwrap.rs:45:17 | LL | let _ = some_btreemap.get(&1).unwrap(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `&some_btreemap[&1]` error: used `unwrap()` on an `Option` value - --> $DIR/get_unwrap.rs:40:17 + --> $DIR/get_unwrap.rs:45:17 | LL | let _ = some_btreemap.get(&1).unwrap(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -90,13 +90,13 @@ LL | let _ = some_btreemap.get(&1).unwrap(); = help: if you don't want to handle the `None` case gracefully, consider using `expect()` to provide a better panic message error: called `.get().unwrap()` on a slice. Using `[]` is more clear and more concise - --> $DIR/get_unwrap.rs:44:21 + --> $DIR/get_unwrap.rs:49:21 | LL | let _: u8 = *boxed_slice.get(1).unwrap(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `boxed_slice[1]` error: used `unwrap()` on an `Option` value - --> $DIR/get_unwrap.rs:44:22 + --> $DIR/get_unwrap.rs:49:22 | LL | let _: u8 = *boxed_slice.get(1).unwrap(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -104,13 +104,13 @@ LL | let _: u8 = *boxed_slice.get(1).unwrap(); = help: if you don't want to handle the `None` case gracefully, consider using `expect()` to provide a better panic message error: called `.get_mut().unwrap()` on a slice. Using `[]` is more clear and more concise - --> $DIR/get_unwrap.rs:49:9 + --> $DIR/get_unwrap.rs:54:9 | LL | *boxed_slice.get_mut(0).unwrap() = 1; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `boxed_slice[0]` error: used `unwrap()` on an `Option` value - --> $DIR/get_unwrap.rs:49:10 + --> $DIR/get_unwrap.rs:54:10 | LL | *boxed_slice.get_mut(0).unwrap() = 1; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -118,13 +118,13 @@ LL | *boxed_slice.get_mut(0).unwrap() = 1; = help: if you don't want to handle the `None` case gracefully, consider using `expect()` to provide a better panic message error: called `.get_mut().unwrap()` on a slice. Using `[]` is more clear and more concise - --> $DIR/get_unwrap.rs:50:9 + --> $DIR/get_unwrap.rs:55:9 | LL | *some_slice.get_mut(0).unwrap() = 1; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `some_slice[0]` error: used `unwrap()` on an `Option` value - --> $DIR/get_unwrap.rs:50:10 + --> $DIR/get_unwrap.rs:55:10 | LL | *some_slice.get_mut(0).unwrap() = 1; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -132,13 +132,13 @@ LL | *some_slice.get_mut(0).unwrap() = 1; = help: if you don't want to handle the `None` case gracefully, consider using `expect()` to provide a better panic message error: called `.get_mut().unwrap()` on a Vec. Using `[]` is more clear and more concise - --> $DIR/get_unwrap.rs:51:9 + --> $DIR/get_unwrap.rs:56:9 | LL | *some_vec.get_mut(0).unwrap() = 1; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `some_vec[0]` error: used `unwrap()` on an `Option` value - --> $DIR/get_unwrap.rs:51:10 + --> $DIR/get_unwrap.rs:56:10 | LL | *some_vec.get_mut(0).unwrap() = 1; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -146,13 +146,13 @@ LL | *some_vec.get_mut(0).unwrap() = 1; = help: if you don't want to handle the `None` case gracefully, consider using `expect()` to provide a better panic message error: called `.get_mut().unwrap()` on a VecDeque. Using `[]` is more clear and more concise - --> $DIR/get_unwrap.rs:52:9 + --> $DIR/get_unwrap.rs:57:9 | LL | *some_vecdeque.get_mut(0).unwrap() = 1; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `some_vecdeque[0]` error: used `unwrap()` on an `Option` value - --> $DIR/get_unwrap.rs:52:10 + --> $DIR/get_unwrap.rs:57:10 | LL | *some_vecdeque.get_mut(0).unwrap() = 1; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -160,13 +160,13 @@ LL | *some_vecdeque.get_mut(0).unwrap() = 1; = help: if you don't want to handle the `None` case gracefully, consider using `expect()` to provide a better panic message error: called `.get().unwrap()` on a Vec. Using `[]` is more clear and more concise - --> $DIR/get_unwrap.rs:64:17 + --> $DIR/get_unwrap.rs:69:17 | LL | let _ = some_vec.get(0..1).unwrap().to_vec(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `some_vec[0..1]` error: used `unwrap()` on an `Option` value - --> $DIR/get_unwrap.rs:64:17 + --> $DIR/get_unwrap.rs:69:17 | LL | let _ = some_vec.get(0..1).unwrap().to_vec(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -174,13 +174,13 @@ LL | let _ = some_vec.get(0..1).unwrap().to_vec(); = help: if you don't want to handle the `None` case gracefully, consider using `expect()` to provide a better panic message error: called `.get_mut().unwrap()` on a Vec. Using `[]` is more clear and more concise - --> $DIR/get_unwrap.rs:65:17 + --> $DIR/get_unwrap.rs:70:17 | LL | let _ = some_vec.get_mut(0..1).unwrap().to_vec(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `some_vec[0..1]` error: used `unwrap()` on an `Option` value - --> $DIR/get_unwrap.rs:65:17 + --> $DIR/get_unwrap.rs:70:17 | LL | let _ = some_vec.get_mut(0..1).unwrap().to_vec(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/indexing_slicing_index.rs b/tests/ui/indexing_slicing_index.rs index 26abc9edb5e..16f9e47e853 100644 --- a/tests/ui/indexing_slicing_index.rs +++ b/tests/ui/indexing_slicing_index.rs @@ -3,7 +3,12 @@ // We also check the out_of_bounds_indexing lint here, because it lints similar things and // we want to avoid false positives. #![warn(clippy::out_of_bounds_indexing)] -#![allow(unconditional_panic, clippy::no_effect, clippy::unnecessary_operation)] +#![allow( + unconditional_panic, + clippy::no_effect, + clippy::unnecessary_operation, + clippy::useless_vec +)] const ARR: [i32; 2] = [1, 2]; const REF: &i32 = &ARR[idx()]; // This should be linted, since `suppress-restriction-lint-in-const` default is false. diff --git a/tests/ui/indexing_slicing_index.stderr b/tests/ui/indexing_slicing_index.stderr index 8fd77913a3f..f4357c1d592 100644 --- a/tests/ui/indexing_slicing_index.stderr +++ b/tests/ui/indexing_slicing_index.stderr @@ -1,5 +1,5 @@ error: indexing may panic - --> $DIR/indexing_slicing_index.rs:9:20 + --> $DIR/indexing_slicing_index.rs:14:20 | LL | const REF: &i32 = &ARR[idx()]; // This should be linted, since `suppress-restriction-lint-in-const` default is false. | ^^^^^^^^^^ @@ -9,7 +9,7 @@ LL | const REF: &i32 = &ARR[idx()]; // This should be linted, since `suppress-re = note: `-D clippy::indexing-slicing` implied by `-D warnings` error: indexing may panic - --> $DIR/indexing_slicing_index.rs:10:24 + --> $DIR/indexing_slicing_index.rs:15:24 | LL | const REF_ERR: &i32 = &ARR[idx4()]; // Ok, let rustc handle const contexts. | ^^^^^^^^^^^ @@ -18,19 +18,19 @@ LL | const REF_ERR: &i32 = &ARR[idx4()]; // Ok, let rustc handle const contexts. = note: the suggestion might not be applicable in constant blocks error[E0080]: evaluation of `main::{constant#3}` failed - --> $DIR/indexing_slicing_index.rs:31:14 + --> $DIR/indexing_slicing_index.rs:36:14 | LL | const { &ARR[idx4()] }; // This should be linted, since `suppress-restriction-lint-in-const` default is false. | ^^^^^^^^^^^ index out of bounds: the length is 2 but the index is 4 note: erroneous constant used - --> $DIR/indexing_slicing_index.rs:31:5 + --> $DIR/indexing_slicing_index.rs:36:5 | LL | const { &ARR[idx4()] }; // This should be linted, since `suppress-restriction-lint-in-const` default is false. | ^^^^^^^^^^^^^^^^^^^^^^ error: indexing may panic - --> $DIR/indexing_slicing_index.rs:22:5 + --> $DIR/indexing_slicing_index.rs:27:5 | LL | x[index]; | ^^^^^^^^ @@ -38,7 +38,7 @@ LL | x[index]; = help: consider using `.get(n)` or `.get_mut(n)` instead error: indexing may panic - --> $DIR/indexing_slicing_index.rs:30:14 + --> $DIR/indexing_slicing_index.rs:35:14 | LL | const { &ARR[idx()] }; // This should be linted, since `suppress-restriction-lint-in-const` default is false. | ^^^^^^^^^^ @@ -47,7 +47,7 @@ LL | const { &ARR[idx()] }; // This should be linted, since `suppress-restri = note: the suggestion might not be applicable in constant blocks error: indexing may panic - --> $DIR/indexing_slicing_index.rs:31:14 + --> $DIR/indexing_slicing_index.rs:36:14 | LL | const { &ARR[idx4()] }; // This should be linted, since `suppress-restriction-lint-in-const` default is false. | ^^^^^^^^^^^ @@ -56,7 +56,7 @@ LL | const { &ARR[idx4()] }; // This should be linted, since `suppress-restr = note: the suggestion might not be applicable in constant blocks error: indexing may panic - --> $DIR/indexing_slicing_index.rs:38:5 + --> $DIR/indexing_slicing_index.rs:43:5 | LL | v[0]; | ^^^^ @@ -64,7 +64,7 @@ LL | v[0]; = help: consider using `.get(n)` or `.get_mut(n)` instead error: indexing may panic - --> $DIR/indexing_slicing_index.rs:39:5 + --> $DIR/indexing_slicing_index.rs:44:5 | LL | v[10]; | ^^^^^ @@ -72,7 +72,7 @@ LL | v[10]; = help: consider using `.get(n)` or `.get_mut(n)` instead error: indexing may panic - --> $DIR/indexing_slicing_index.rs:40:5 + --> $DIR/indexing_slicing_index.rs:45:5 | LL | v[1 << 3]; | ^^^^^^^^^ @@ -80,7 +80,7 @@ LL | v[1 << 3]; = help: consider using `.get(n)` or `.get_mut(n)` instead error: indexing may panic - --> $DIR/indexing_slicing_index.rs:46:5 + --> $DIR/indexing_slicing_index.rs:51:5 | LL | v[N]; | ^^^^ @@ -88,7 +88,7 @@ LL | v[N]; = help: consider using `.get(n)` or `.get_mut(n)` instead error: indexing may panic - --> $DIR/indexing_slicing_index.rs:47:5 + --> $DIR/indexing_slicing_index.rs:52:5 | LL | v[M]; | ^^^^ @@ -96,7 +96,7 @@ LL | v[M]; = help: consider using `.get(n)` or `.get_mut(n)` instead error[E0080]: evaluation of constant value failed - --> $DIR/indexing_slicing_index.rs:10:24 + --> $DIR/indexing_slicing_index.rs:15:24 | LL | const REF_ERR: &i32 = &ARR[idx4()]; // Ok, let rustc handle const contexts. | ^^^^^^^^^^^ index out of bounds: the length is 2 but the index is 4 diff --git a/tests/ui/indexing_slicing_slice.rs b/tests/ui/indexing_slicing_slice.rs index 7b107db39f0..939b6ac36bd 100644 --- a/tests/ui/indexing_slicing_slice.rs +++ b/tests/ui/indexing_slicing_slice.rs @@ -2,7 +2,7 @@ // We also check the out_of_bounds_indexing lint here, because it lints similar things and // we want to avoid false positives. #![warn(clippy::out_of_bounds_indexing)] -#![allow(clippy::no_effect, clippy::unnecessary_operation)] +#![allow(clippy::no_effect, clippy::unnecessary_operation, clippy::useless_vec)] fn main() { let x = [1, 2, 3, 4]; diff --git a/tests/ui/iter_count.fixed b/tests/ui/iter_count.fixed index 4367a12f820..b6208201409 100644 --- a/tests/ui/iter_count.fixed +++ b/tests/ui/iter_count.fixed @@ -7,7 +7,8 @@ array_into_iter, unused_mut, clippy::into_iter_on_ref, - clippy::unnecessary_operation + clippy::unnecessary_operation, + clippy::useless_vec )] extern crate option_helpers; diff --git a/tests/ui/iter_count.rs b/tests/ui/iter_count.rs index 8c7543cf03b..fb216131209 100644 --- a/tests/ui/iter_count.rs +++ b/tests/ui/iter_count.rs @@ -7,7 +7,8 @@ array_into_iter, unused_mut, clippy::into_iter_on_ref, - clippy::unnecessary_operation + clippy::unnecessary_operation, + clippy::useless_vec )] extern crate option_helpers; diff --git a/tests/ui/iter_count.stderr b/tests/ui/iter_count.stderr index 2e3d7fc35de..f9aee0b7846 100644 --- a/tests/ui/iter_count.stderr +++ b/tests/ui/iter_count.stderr @@ -1,5 +1,5 @@ error: called `.iter().count()` on a `slice` - --> $DIR/iter_count.rs:54:6 + --> $DIR/iter_count.rs:55:6 | LL | &vec[..].iter().count(); | ^^^^^^^^^^^^^^^^^^^^^^ help: try: `vec[..].len()` @@ -7,145 +7,145 @@ LL | &vec[..].iter().count(); = note: `-D clippy::iter-count` implied by `-D warnings` error: called `.iter().count()` on a `Vec` - --> $DIR/iter_count.rs:55:5 + --> $DIR/iter_count.rs:56:5 | LL | vec.iter().count(); | ^^^^^^^^^^^^^^^^^^ help: try: `vec.len()` error: called `.iter().count()` on a `slice` - --> $DIR/iter_count.rs:56:5 + --> $DIR/iter_count.rs:57:5 | LL | boxed_slice.iter().count(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `boxed_slice.len()` error: called `.iter().count()` on a `VecDeque` - --> $DIR/iter_count.rs:57:5 + --> $DIR/iter_count.rs:58:5 | LL | vec_deque.iter().count(); | ^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `vec_deque.len()` error: called `.iter().count()` on a `HashSet` - --> $DIR/iter_count.rs:58:5 + --> $DIR/iter_count.rs:59:5 | LL | hash_set.iter().count(); | ^^^^^^^^^^^^^^^^^^^^^^^ help: try: `hash_set.len()` error: called `.iter().count()` on a `HashMap` - --> $DIR/iter_count.rs:59:5 + --> $DIR/iter_count.rs:60:5 | LL | hash_map.iter().count(); | ^^^^^^^^^^^^^^^^^^^^^^^ help: try: `hash_map.len()` error: called `.iter().count()` on a `BTreeMap` - --> $DIR/iter_count.rs:60:5 + --> $DIR/iter_count.rs:61:5 | LL | b_tree_map.iter().count(); | ^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `b_tree_map.len()` error: called `.iter().count()` on a `BTreeSet` - --> $DIR/iter_count.rs:61:5 + --> $DIR/iter_count.rs:62:5 | LL | b_tree_set.iter().count(); | ^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `b_tree_set.len()` error: called `.iter().count()` on a `LinkedList` - --> $DIR/iter_count.rs:62:5 + --> $DIR/iter_count.rs:63:5 | LL | linked_list.iter().count(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `linked_list.len()` error: called `.iter().count()` on a `BinaryHeap` - --> $DIR/iter_count.rs:63:5 + --> $DIR/iter_count.rs:64:5 | LL | binary_heap.iter().count(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `binary_heap.len()` error: called `.iter_mut().count()` on a `Vec` - --> $DIR/iter_count.rs:65:5 + --> $DIR/iter_count.rs:66:5 | LL | vec.iter_mut().count(); | ^^^^^^^^^^^^^^^^^^^^^^ help: try: `vec.len()` error: called `.iter_mut().count()` on a `slice` - --> $DIR/iter_count.rs:66:6 + --> $DIR/iter_count.rs:67:6 | LL | &vec[..].iter_mut().count(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `vec[..].len()` error: called `.iter_mut().count()` on a `VecDeque` - --> $DIR/iter_count.rs:67:5 + --> $DIR/iter_count.rs:68:5 | LL | vec_deque.iter_mut().count(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `vec_deque.len()` error: called `.iter_mut().count()` on a `HashMap` - --> $DIR/iter_count.rs:68:5 + --> $DIR/iter_count.rs:69:5 | LL | hash_map.iter_mut().count(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `hash_map.len()` error: called `.iter_mut().count()` on a `BTreeMap` - --> $DIR/iter_count.rs:69:5 + --> $DIR/iter_count.rs:70:5 | LL | b_tree_map.iter_mut().count(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `b_tree_map.len()` error: called `.iter_mut().count()` on a `LinkedList` - --> $DIR/iter_count.rs:70:5 + --> $DIR/iter_count.rs:71:5 | LL | linked_list.iter_mut().count(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `linked_list.len()` error: called `.into_iter().count()` on a `slice` - --> $DIR/iter_count.rs:72:6 + --> $DIR/iter_count.rs:73:6 | LL | &vec[..].into_iter().count(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `vec[..].len()` error: called `.into_iter().count()` on a `Vec` - --> $DIR/iter_count.rs:73:5 + --> $DIR/iter_count.rs:74:5 | LL | vec.into_iter().count(); | ^^^^^^^^^^^^^^^^^^^^^^^ help: try: `vec.len()` error: called `.into_iter().count()` on a `VecDeque` - --> $DIR/iter_count.rs:74:5 + --> $DIR/iter_count.rs:75:5 | LL | vec_deque.into_iter().count(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `vec_deque.len()` error: called `.into_iter().count()` on a `HashSet` - --> $DIR/iter_count.rs:75:5 + --> $DIR/iter_count.rs:76:5 | LL | hash_set.into_iter().count(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `hash_set.len()` error: called `.into_iter().count()` on a `HashMap` - --> $DIR/iter_count.rs:76:5 + --> $DIR/iter_count.rs:77:5 | LL | hash_map.into_iter().count(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `hash_map.len()` error: called `.into_iter().count()` on a `BTreeMap` - --> $DIR/iter_count.rs:77:5 + --> $DIR/iter_count.rs:78:5 | LL | b_tree_map.into_iter().count(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `b_tree_map.len()` error: called `.into_iter().count()` on a `BTreeSet` - --> $DIR/iter_count.rs:78:5 + --> $DIR/iter_count.rs:79:5 | LL | b_tree_set.into_iter().count(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `b_tree_set.len()` error: called `.into_iter().count()` on a `LinkedList` - --> $DIR/iter_count.rs:79:5 + --> $DIR/iter_count.rs:80:5 | LL | linked_list.into_iter().count(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `linked_list.len()` error: called `.into_iter().count()` on a `BinaryHeap` - --> $DIR/iter_count.rs:80:5 + --> $DIR/iter_count.rs:81:5 | LL | binary_heap.into_iter().count(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `binary_heap.len()` diff --git a/tests/ui/iter_next_slice.fixed b/tests/ui/iter_next_slice.fixed index d862abc34e0..702edccdbad 100644 --- a/tests/ui/iter_next_slice.fixed +++ b/tests/ui/iter_next_slice.fixed @@ -1,5 +1,6 @@ //@run-rustfix #![warn(clippy::iter_next_slice)] +#![allow(clippy::useless_vec)] fn main() { // test code goes here diff --git a/tests/ui/iter_next_slice.rs b/tests/ui/iter_next_slice.rs index da6fc46e428..30bfc72de17 100644 --- a/tests/ui/iter_next_slice.rs +++ b/tests/ui/iter_next_slice.rs @@ -1,5 +1,6 @@ //@run-rustfix #![warn(clippy::iter_next_slice)] +#![allow(clippy::useless_vec)] fn main() { // test code goes here diff --git a/tests/ui/iter_next_slice.stderr b/tests/ui/iter_next_slice.stderr index d8b89061ff8..0db8201a132 100644 --- a/tests/ui/iter_next_slice.stderr +++ b/tests/ui/iter_next_slice.stderr @@ -1,5 +1,5 @@ error: using `.iter().next()` on an array - --> $DIR/iter_next_slice.rs:9:13 + --> $DIR/iter_next_slice.rs:10:13 | LL | let _ = s.iter().next(); | ^^^^^^^^^^^^^^^ help: try calling: `s.first()` @@ -7,19 +7,19 @@ LL | let _ = s.iter().next(); = note: `-D clippy::iter-next-slice` implied by `-D warnings` error: using `.iter().next()` on a Slice without end index - --> $DIR/iter_next_slice.rs:12:13 + --> $DIR/iter_next_slice.rs:13:13 | LL | let _ = s[2..].iter().next(); | ^^^^^^^^^^^^^^^^^^^^ help: try calling: `s.get(2)` error: using `.iter().next()` on a Slice without end index - --> $DIR/iter_next_slice.rs:15:13 + --> $DIR/iter_next_slice.rs:16:13 | LL | let _ = v[5..].iter().next(); | ^^^^^^^^^^^^^^^^^^^^ help: try calling: `v.get(5)` error: using `.iter().next()` on an array - --> $DIR/iter_next_slice.rs:18:13 + --> $DIR/iter_next_slice.rs:19:13 | LL | let _ = v.iter().next(); | ^^^^^^^^^^^^^^^ help: try calling: `v.first()` diff --git a/tests/ui/iter_nth.rs b/tests/ui/iter_nth.rs index e7fb97d4fbc..7c567bb81d8 100644 --- a/tests/ui/iter_nth.rs +++ b/tests/ui/iter_nth.rs @@ -1,6 +1,7 @@ //@aux-build:option_helpers.rs #![warn(clippy::iter_nth)] +#![allow(clippy::useless_vec)] #[macro_use] extern crate option_helpers; diff --git a/tests/ui/iter_nth.stderr b/tests/ui/iter_nth.stderr index a0fe353bcf7..975a5a62ad5 100644 --- a/tests/ui/iter_nth.stderr +++ b/tests/ui/iter_nth.stderr @@ -1,5 +1,5 @@ error: called `.iter().nth()` on a Vec - --> $DIR/iter_nth.rs:33:23 + --> $DIR/iter_nth.rs:34:23 | LL | let bad_vec = some_vec.iter().nth(3); | ^^^^^^^^^^^^^^^^^^^^^^ @@ -8,7 +8,7 @@ LL | let bad_vec = some_vec.iter().nth(3); = note: `-D clippy::iter-nth` implied by `-D warnings` error: called `.iter().nth()` on a slice - --> $DIR/iter_nth.rs:34:26 + --> $DIR/iter_nth.rs:35:26 | LL | let bad_slice = &some_vec[..].iter().nth(3); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -16,7 +16,7 @@ LL | let bad_slice = &some_vec[..].iter().nth(3); = help: calling `.get()` is both faster and more readable error: called `.iter().nth()` on a slice - --> $DIR/iter_nth.rs:35:31 + --> $DIR/iter_nth.rs:36:31 | LL | let bad_boxed_slice = boxed_slice.iter().nth(3); | ^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -24,7 +24,7 @@ LL | let bad_boxed_slice = boxed_slice.iter().nth(3); = help: calling `.get()` is both faster and more readable error: called `.iter().nth()` on a VecDeque - --> $DIR/iter_nth.rs:36:29 + --> $DIR/iter_nth.rs:37:29 | LL | let bad_vec_deque = some_vec_deque.iter().nth(3); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -32,7 +32,7 @@ LL | let bad_vec_deque = some_vec_deque.iter().nth(3); = help: calling `.get()` is both faster and more readable error: called `.iter_mut().nth()` on a Vec - --> $DIR/iter_nth.rs:41:23 + --> $DIR/iter_nth.rs:42:23 | LL | let bad_vec = some_vec.iter_mut().nth(3); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -40,7 +40,7 @@ LL | let bad_vec = some_vec.iter_mut().nth(3); = help: calling `.get_mut()` is both faster and more readable error: called `.iter_mut().nth()` on a slice - --> $DIR/iter_nth.rs:44:26 + --> $DIR/iter_nth.rs:45:26 | LL | let bad_slice = &some_vec[..].iter_mut().nth(3); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -48,7 +48,7 @@ LL | let bad_slice = &some_vec[..].iter_mut().nth(3); = help: calling `.get_mut()` is both faster and more readable error: called `.iter_mut().nth()` on a VecDeque - --> $DIR/iter_nth.rs:47:29 + --> $DIR/iter_nth.rs:48:29 | LL | let bad_vec_deque = some_vec_deque.iter_mut().nth(3); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/iter_overeager_cloned.fixed b/tests/ui/iter_overeager_cloned.fixed index bf576e9cbfb..2874513c049 100644 --- a/tests/ui/iter_overeager_cloned.fixed +++ b/tests/ui/iter_overeager_cloned.fixed @@ -1,6 +1,6 @@ //@run-rustfix #![warn(clippy::iter_overeager_cloned, clippy::redundant_clone, clippy::filter_next)] -#![allow(dead_code, clippy::let_unit_value)] +#![allow(dead_code, clippy::let_unit_value, clippy::useless_vec)] fn main() { let vec = vec!["1".to_string(), "2".to_string(), "3".to_string()]; diff --git a/tests/ui/iter_overeager_cloned.rs b/tests/ui/iter_overeager_cloned.rs index df42d88eff0..26f39734a51 100644 --- a/tests/ui/iter_overeager_cloned.rs +++ b/tests/ui/iter_overeager_cloned.rs @@ -1,6 +1,6 @@ //@run-rustfix #![warn(clippy::iter_overeager_cloned, clippy::redundant_clone, clippy::filter_next)] -#![allow(dead_code, clippy::let_unit_value)] +#![allow(dead_code, clippy::let_unit_value, clippy::useless_vec)] fn main() { let vec = vec!["1".to_string(), "2".to_string(), "3".to_string()]; diff --git a/tests/ui/iter_skip_next.fixed b/tests/ui/iter_skip_next.fixed index 8f2cefc4304..b888d965e8d 100644 --- a/tests/ui/iter_skip_next.fixed +++ b/tests/ui/iter_skip_next.fixed @@ -4,6 +4,7 @@ #![warn(clippy::iter_skip_next)] #![allow(clippy::disallowed_names)] #![allow(clippy::iter_nth)] +#![allow(clippy::useless_vec)] #![allow(unused_mut, dead_code)] extern crate option_helpers; diff --git a/tests/ui/iter_skip_next.rs b/tests/ui/iter_skip_next.rs index 71d83384f3a..e44efdebc47 100644 --- a/tests/ui/iter_skip_next.rs +++ b/tests/ui/iter_skip_next.rs @@ -4,6 +4,7 @@ #![warn(clippy::iter_skip_next)] #![allow(clippy::disallowed_names)] #![allow(clippy::iter_nth)] +#![allow(clippy::useless_vec)] #![allow(unused_mut, dead_code)] extern crate option_helpers; diff --git a/tests/ui/iter_skip_next.stderr b/tests/ui/iter_skip_next.stderr index ca6970b27f1..4ee26e088ce 100644 --- a/tests/ui/iter_skip_next.stderr +++ b/tests/ui/iter_skip_next.stderr @@ -1,5 +1,5 @@ error: called `skip(..).next()` on an iterator - --> $DIR/iter_skip_next.rs:16:28 + --> $DIR/iter_skip_next.rs:17:28 | LL | let _ = some_vec.iter().skip(42).next(); | ^^^^^^^^^^^^^^^^ help: use `nth` instead: `.nth(42)` @@ -7,37 +7,37 @@ LL | let _ = some_vec.iter().skip(42).next(); = note: `-D clippy::iter-skip-next` implied by `-D warnings` error: called `skip(..).next()` on an iterator - --> $DIR/iter_skip_next.rs:17:36 + --> $DIR/iter_skip_next.rs:18:36 | LL | let _ = some_vec.iter().cycle().skip(42).next(); | ^^^^^^^^^^^^^^^^ help: use `nth` instead: `.nth(42)` error: called `skip(..).next()` on an iterator - --> $DIR/iter_skip_next.rs:18:20 + --> $DIR/iter_skip_next.rs:19:20 | LL | let _ = (1..10).skip(10).next(); | ^^^^^^^^^^^^^^^^ help: use `nth` instead: `.nth(10)` error: called `skip(..).next()` on an iterator - --> $DIR/iter_skip_next.rs:19:33 + --> $DIR/iter_skip_next.rs:20:33 | LL | let _ = &some_vec[..].iter().skip(3).next(); | ^^^^^^^^^^^^^^^ help: use `nth` instead: `.nth(3)` error: called `skip(..).next()` on an iterator - --> $DIR/iter_skip_next.rs:27:26 + --> $DIR/iter_skip_next.rs:28:26 | LL | let _: Vec<&str> = sp.skip(1).next().unwrap().split(' ').collect(); | ^^^^^^^^^^^^^^^ help: use `nth` instead: `.nth(1)` error: called `skip(..).next()` on an iterator - --> $DIR/iter_skip_next.rs:29:29 + --> $DIR/iter_skip_next.rs:30:29 | LL | let _: Vec<&str> = s.skip(1).next().unwrap().split(' ').collect(); | ^^^^^^^^^^^^^^^ help: use `nth` instead: `.nth(1)` error: called `skip(..).next()` on an iterator - --> $DIR/iter_skip_next.rs:35:29 + --> $DIR/iter_skip_next.rs:36:29 | LL | let _: Vec<&str> = s.skip(1).next().unwrap().split(' ').collect(); | ^^^^^^^^^^^^^^^ help: use `nth` instead: `.nth(1)` diff --git a/tests/ui/iterator_step_by_zero.rs b/tests/ui/iterator_step_by_zero.rs index 13d1cfd4281..33ec78e9a41 100644 --- a/tests/ui/iterator_step_by_zero.rs +++ b/tests/ui/iterator_step_by_zero.rs @@ -1,3 +1,4 @@ +#![allow(clippy::useless_vec)] #[warn(clippy::iterator_step_by_zero)] fn main() { let _ = vec!["A", "B", "B"].iter().step_by(0); diff --git a/tests/ui/iterator_step_by_zero.stderr b/tests/ui/iterator_step_by_zero.stderr index d792aea11df..b470e2ed2ea 100644 --- a/tests/ui/iterator_step_by_zero.stderr +++ b/tests/ui/iterator_step_by_zero.stderr @@ -1,5 +1,5 @@ error: `Iterator::step_by(0)` will panic at runtime - --> $DIR/iterator_step_by_zero.rs:3:13 + --> $DIR/iterator_step_by_zero.rs:4:13 | LL | let _ = vec!["A", "B", "B"].iter().step_by(0); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -7,37 +7,37 @@ LL | let _ = vec!["A", "B", "B"].iter().step_by(0); = note: `-D clippy::iterator-step-by-zero` implied by `-D warnings` error: `Iterator::step_by(0)` will panic at runtime - --> $DIR/iterator_step_by_zero.rs:4:13 + --> $DIR/iterator_step_by_zero.rs:5:13 | LL | let _ = "XXX".chars().step_by(0); | ^^^^^^^^^^^^^^^^^^^^^^^^ error: `Iterator::step_by(0)` will panic at runtime - --> $DIR/iterator_step_by_zero.rs:5:13 + --> $DIR/iterator_step_by_zero.rs:6:13 | LL | let _ = (0..1).step_by(0); | ^^^^^^^^^^^^^^^^^ error: `Iterator::step_by(0)` will panic at runtime - --> $DIR/iterator_step_by_zero.rs:14:13 + --> $DIR/iterator_step_by_zero.rs:15:13 | LL | let _ = (1..).step_by(0); | ^^^^^^^^^^^^^^^^ error: `Iterator::step_by(0)` will panic at runtime - --> $DIR/iterator_step_by_zero.rs:15:13 + --> $DIR/iterator_step_by_zero.rs:16:13 | LL | let _ = (1..=2).step_by(0); | ^^^^^^^^^^^^^^^^^^ error: `Iterator::step_by(0)` will panic at runtime - --> $DIR/iterator_step_by_zero.rs:18:13 + --> $DIR/iterator_step_by_zero.rs:19:13 | LL | let _ = x.step_by(0); | ^^^^^^^^^^^^ error: `Iterator::step_by(0)` will panic at runtime - --> $DIR/iterator_step_by_zero.rs:22:13 + --> $DIR/iterator_step_by_zero.rs:23:13 | LL | let _ = v1.iter().step_by(2 / 3); | ^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/manual_assert.edition2018.fixed b/tests/ui/manual_assert.edition2018.fixed index ab9b375dc03..d8dde0236ea 100644 --- a/tests/ui/manual_assert.edition2018.fixed +++ b/tests/ui/manual_assert.edition2018.fixed @@ -5,7 +5,7 @@ #![warn(clippy::manual_assert)] #![allow(dead_code, unused_doc_comments)] -#![allow(clippy::nonminimal_bool, clippy::uninlined_format_args)] +#![allow(clippy::nonminimal_bool, clippy::uninlined_format_args, clippy::useless_vec)] macro_rules! one { () => { diff --git a/tests/ui/manual_assert.edition2021.fixed b/tests/ui/manual_assert.edition2021.fixed index ab9b375dc03..d8dde0236ea 100644 --- a/tests/ui/manual_assert.edition2021.fixed +++ b/tests/ui/manual_assert.edition2021.fixed @@ -5,7 +5,7 @@ #![warn(clippy::manual_assert)] #![allow(dead_code, unused_doc_comments)] -#![allow(clippy::nonminimal_bool, clippy::uninlined_format_args)] +#![allow(clippy::nonminimal_bool, clippy::uninlined_format_args, clippy::useless_vec)] macro_rules! one { () => { diff --git a/tests/ui/manual_assert.rs b/tests/ui/manual_assert.rs index eac52d1b5de..0f87d6e2d2c 100644 --- a/tests/ui/manual_assert.rs +++ b/tests/ui/manual_assert.rs @@ -5,7 +5,7 @@ #![warn(clippy::manual_assert)] #![allow(dead_code, unused_doc_comments)] -#![allow(clippy::nonminimal_bool, clippy::uninlined_format_args)] +#![allow(clippy::nonminimal_bool, clippy::uninlined_format_args, clippy::useless_vec)] macro_rules! one { () => { diff --git a/tests/ui/manual_filter.fixed b/tests/ui/manual_filter.fixed index 755caa664d5..5e3b12e510b 100644 --- a/tests/ui/manual_filter.fixed +++ b/tests/ui/manual_filter.fixed @@ -1,7 +1,7 @@ //@run-rustfix #![warn(clippy::manual_filter)] -#![allow(unused_variables, dead_code)] +#![allow(unused_variables, dead_code, clippy::useless_vec)] fn main() { Some(0).filter(|&x| x <= 0); diff --git a/tests/ui/manual_filter.rs b/tests/ui/manual_filter.rs index faccfe9db12..b81604b0372 100644 --- a/tests/ui/manual_filter.rs +++ b/tests/ui/manual_filter.rs @@ -1,7 +1,7 @@ //@run-rustfix #![warn(clippy::manual_filter)] -#![allow(unused_variables, dead_code)] +#![allow(unused_variables, dead_code, clippy::useless_vec)] fn main() { match Some(0) { diff --git a/tests/ui/manual_filter_map.fixed b/tests/ui/manual_filter_map.fixed index 831323089e7..9dd376df2b4 100644 --- a/tests/ui/manual_filter_map.fixed +++ b/tests/ui/manual_filter_map.fixed @@ -2,6 +2,7 @@ #![allow(dead_code)] #![warn(clippy::manual_filter_map)] #![allow(clippy::redundant_closure)] // FIXME suggestion may have redundant closure +#![allow(clippy::useless_vec)] fn main() { // is_some(), unwrap() diff --git a/tests/ui/manual_filter_map.rs b/tests/ui/manual_filter_map.rs index 2692303d313..6dd1e066aeb 100644 --- a/tests/ui/manual_filter_map.rs +++ b/tests/ui/manual_filter_map.rs @@ -2,6 +2,7 @@ #![allow(dead_code)] #![warn(clippy::manual_filter_map)] #![allow(clippy::redundant_closure)] // FIXME suggestion may have redundant closure +#![allow(clippy::useless_vec)] fn main() { // is_some(), unwrap() diff --git a/tests/ui/manual_filter_map.stderr b/tests/ui/manual_filter_map.stderr index 6e5bbe8f2aa..882468b0f5f 100644 --- a/tests/ui/manual_filter_map.stderr +++ b/tests/ui/manual_filter_map.stderr @@ -1,5 +1,5 @@ error: `filter(..).map(..)` can be simplified as `filter_map(..)` - --> $DIR/manual_filter_map.rs:8:19 + --> $DIR/manual_filter_map.rs:9:19 | LL | let _ = (0..).filter(|n| to_opt(*n).is_some()).map(|a| to_opt(a).unwrap()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `filter_map(|a| to_opt(a))` @@ -7,19 +7,19 @@ LL | let _ = (0..).filter(|n| to_opt(*n).is_some()).map(|a| to_opt(a).unwrap = note: `-D clippy::manual-filter-map` implied by `-D warnings` error: `filter(..).map(..)` can be simplified as `filter_map(..)` - --> $DIR/manual_filter_map.rs:11:19 + --> $DIR/manual_filter_map.rs:12:19 | LL | let _ = (0..).filter(|&n| to_opt(n).is_some()).map(|a| to_opt(a).expect("hi")); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `filter_map(|a| to_opt(a))` error: `filter(..).map(..)` can be simplified as `filter_map(..)` - --> $DIR/manual_filter_map.rs:14:19 + --> $DIR/manual_filter_map.rs:15:19 | LL | let _ = (0..).filter(|&n| to_res(n).is_ok()).map(|a| to_res(a).unwrap_or(1)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `filter_map(|a| to_res(a).ok())` error: `filter(..).map(..)` can be simplified as `filter_map(..)` - --> $DIR/manual_filter_map.rs:17:10 + --> $DIR/manual_filter_map.rs:18:10 | LL | .filter(|&x| to_ref(to_opt(x)).is_some()) | __________^ @@ -27,7 +27,7 @@ LL | | .map(|y| to_ref(to_opt(y)).unwrap()); | |____________________________________________^ help: try: `filter_map(|y| *to_ref(to_opt(y)))` error: `filter(..).map(..)` can be simplified as `filter_map(..)` - --> $DIR/manual_filter_map.rs:20:10 + --> $DIR/manual_filter_map.rs:21:10 | LL | .filter(|x| to_ref(to_opt(*x)).is_some()) | __________^ @@ -35,7 +35,7 @@ LL | | .map(|y| to_ref(to_opt(y)).unwrap()); | |____________________________________________^ help: try: `filter_map(|y| *to_ref(to_opt(y)))` error: `filter(..).map(..)` can be simplified as `filter_map(..)` - --> $DIR/manual_filter_map.rs:24:10 + --> $DIR/manual_filter_map.rs:25:10 | LL | .filter(|&x| to_ref(to_res(x)).is_ok()) | __________^ @@ -43,7 +43,7 @@ LL | | .map(|y| to_ref(to_res(y)).unwrap()); | |____________________________________________^ help: try: `filter_map(|y| to_ref(to_res(y)).ok())` error: `filter(..).map(..)` can be simplified as `filter_map(..)` - --> $DIR/manual_filter_map.rs:27:10 + --> $DIR/manual_filter_map.rs:28:10 | LL | .filter(|x| to_ref(to_res(*x)).is_ok()) | __________^ @@ -51,7 +51,7 @@ LL | | .map(|y| to_ref(to_res(y)).unwrap()); | |____________________________________________^ help: try: `filter_map(|y| to_ref(to_res(y)).ok())` error: `find(..).map(..)` can be simplified as `find_map(..)` - --> $DIR/manual_filter_map.rs:33:27 + --> $DIR/manual_filter_map.rs:34:27 | LL | iter::>().find(|x| x.is_some()).map(|x| x.cloned().unwrap()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `find_map(|x| x.cloned())` @@ -59,67 +59,67 @@ LL | iter::>().find(|x| x.is_some()).map(|x| x.cloned().unwrap() = note: `-D clippy::manual-find-map` implied by `-D warnings` error: `find(..).map(..)` can be simplified as `find_map(..)` - --> $DIR/manual_filter_map.rs:34:28 + --> $DIR/manual_filter_map.rs:35:28 | LL | iter::<&Option<&u8>>().find(|x| x.is_some()).map(|x| x.cloned().unwrap()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `find_map(|x| x.cloned())` error: `find(..).map(..)` can be simplified as `find_map(..)` - --> $DIR/manual_filter_map.rs:35:31 + --> $DIR/manual_filter_map.rs:36:31 | LL | iter::<&Option>().find(|x| x.is_some()).map(|x| x.as_deref().unwrap()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `find_map(|x| x.as_deref())` error: `find(..).map(..)` can be simplified as `find_map(..)` - --> $DIR/manual_filter_map.rs:36:31 + --> $DIR/manual_filter_map.rs:37:31 | LL | iter::>().find(|&x| to_ref(x).is_some()).map(|y| to_ref(y).cloned().unwrap()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `find_map(|y| to_ref(y).cloned())` error: `find(..).map(..)` can be simplified as `find_map(..)` - --> $DIR/manual_filter_map.rs:38:30 + --> $DIR/manual_filter_map.rs:39:30 | LL | iter::>().find(|x| x.is_ok()).map(|x| x.unwrap()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `find_map(|x| x.ok())` error: `find(..).map(..)` can be simplified as `find_map(..)` - --> $DIR/manual_filter_map.rs:39:31 + --> $DIR/manual_filter_map.rs:40:31 | LL | iter::<&Result>().find(|x| x.is_ok()).map(|x| x.unwrap()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `find_map(|x| x.ok())` error: `find(..).map(..)` can be simplified as `find_map(..)` - --> $DIR/manual_filter_map.rs:40:32 + --> $DIR/manual_filter_map.rs:41:32 | LL | iter::<&&Result>().find(|x| x.is_ok()).map(|x| x.unwrap()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `find_map(|x| x.ok())` error: `find(..).map(..)` can be simplified as `find_map(..)` - --> $DIR/manual_filter_map.rs:41:31 + --> $DIR/manual_filter_map.rs:42:31 | LL | iter::>().find(|x| x.is_ok()).map(|x| x.cloned().unwrap()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `find_map(|x| x.cloned().ok())` error: `find(..).map(..)` can be simplified as `find_map(..)` - --> $DIR/manual_filter_map.rs:42:32 + --> $DIR/manual_filter_map.rs:43:32 | LL | iter::<&Result<&u8, ()>>().find(|x| x.is_ok()).map(|x| x.cloned().unwrap()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `find_map(|x| x.cloned().ok())` error: `find(..).map(..)` can be simplified as `find_map(..)` - --> $DIR/manual_filter_map.rs:43:35 + --> $DIR/manual_filter_map.rs:44:35 | LL | iter::<&Result>().find(|x| x.is_ok()).map(|x| x.as_deref().unwrap()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `find_map(|x| x.as_deref().ok())` error: `find(..).map(..)` can be simplified as `find_map(..)` - --> $DIR/manual_filter_map.rs:44:35 + --> $DIR/manual_filter_map.rs:45:35 | LL | iter::>().find(|&x| to_ref(x).is_ok()).map(|y| to_ref(y).cloned().unwrap()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `find_map(|y| to_ref(y).cloned().ok())` error: `filter(..).map(..)` can be simplified as `filter_map(..)` - --> $DIR/manual_filter_map.rs:92:10 + --> $DIR/manual_filter_map.rs:93:10 | LL | .filter(|f| f.option_field.is_some()) | __________^ @@ -127,7 +127,7 @@ LL | | .map(|f| f.option_field.clone().unwrap()); | |_________________________________________________^ help: try: `filter_map(|f| f.option_field.clone())` error: `filter(..).map(..)` can be simplified as `filter_map(..)` - --> $DIR/manual_filter_map.rs:97:10 + --> $DIR/manual_filter_map.rs:98:10 | LL | .filter(|f| f.ref_field.is_some()) | __________^ @@ -135,7 +135,7 @@ LL | | .map(|f| f.ref_field.cloned().unwrap()); | |_______________________________________________^ help: try: `filter_map(|f| f.ref_field.cloned())` error: `filter(..).map(..)` can be simplified as `filter_map(..)` - --> $DIR/manual_filter_map.rs:102:10 + --> $DIR/manual_filter_map.rs:103:10 | LL | .filter(|f| f.ref_field.is_some()) | __________^ @@ -143,7 +143,7 @@ LL | | .map(|f| f.ref_field.copied().unwrap()); | |_______________________________________________^ help: try: `filter_map(|f| f.ref_field.copied())` error: `filter(..).map(..)` can be simplified as `filter_map(..)` - --> $DIR/manual_filter_map.rs:107:10 + --> $DIR/manual_filter_map.rs:108:10 | LL | .filter(|f| f.result_field.is_ok()) | __________^ @@ -151,7 +151,7 @@ LL | | .map(|f| f.result_field.clone().unwrap()); | |_________________________________________________^ help: try: `filter_map(|f| f.result_field.clone().ok())` error: `filter(..).map(..)` can be simplified as `filter_map(..)` - --> $DIR/manual_filter_map.rs:112:10 + --> $DIR/manual_filter_map.rs:113:10 | LL | .filter(|f| f.result_field.is_ok()) | __________^ @@ -159,7 +159,7 @@ LL | | .map(|f| f.result_field.as_ref().unwrap()); | |__________________________________________________^ help: try: `filter_map(|f| f.result_field.as_ref().ok())` error: `filter(..).map(..)` can be simplified as `filter_map(..)` - --> $DIR/manual_filter_map.rs:117:10 + --> $DIR/manual_filter_map.rs:118:10 | LL | .filter(|f| f.result_field.is_ok()) | __________^ @@ -167,7 +167,7 @@ LL | | .map(|f| f.result_field.as_deref().unwrap()); | |____________________________________________________^ help: try: `filter_map(|f| f.result_field.as_deref().ok())` error: `filter(..).map(..)` can be simplified as `filter_map(..)` - --> $DIR/manual_filter_map.rs:122:10 + --> $DIR/manual_filter_map.rs:123:10 | LL | .filter(|f| f.result_field.is_ok()) | __________^ @@ -175,7 +175,7 @@ LL | | .map(|f| f.result_field.as_mut().unwrap()); | |__________________________________________________^ help: try: `filter_map(|f| f.result_field.as_mut().ok())` error: `filter(..).map(..)` can be simplified as `filter_map(..)` - --> $DIR/manual_filter_map.rs:127:10 + --> $DIR/manual_filter_map.rs:128:10 | LL | .filter(|f| f.result_field.is_ok()) | __________^ @@ -183,7 +183,7 @@ LL | | .map(|f| f.result_field.as_deref_mut().unwrap()); | |________________________________________________________^ help: try: `filter_map(|f| f.result_field.as_deref_mut().ok())` error: `filter(..).map(..)` can be simplified as `filter_map(..)` - --> $DIR/manual_filter_map.rs:132:10 + --> $DIR/manual_filter_map.rs:133:10 | LL | .filter(|f| f.result_field.is_ok()) | __________^ diff --git a/tests/ui/manual_find_map.fixed b/tests/ui/manual_find_map.fixed index 554613a30a9..0c8eebf04b5 100644 --- a/tests/ui/manual_find_map.fixed +++ b/tests/ui/manual_find_map.fixed @@ -2,6 +2,7 @@ #![allow(dead_code)] #![warn(clippy::manual_find_map)] #![allow(clippy::redundant_closure)] // FIXME suggestion may have redundant closure +#![allow(clippy::useless_vec)] fn main() { // is_some(), unwrap() diff --git a/tests/ui/manual_find_map.rs b/tests/ui/manual_find_map.rs index d6245758f9d..b2feb48a839 100644 --- a/tests/ui/manual_find_map.rs +++ b/tests/ui/manual_find_map.rs @@ -2,6 +2,7 @@ #![allow(dead_code)] #![warn(clippy::manual_find_map)] #![allow(clippy::redundant_closure)] // FIXME suggestion may have redundant closure +#![allow(clippy::useless_vec)] fn main() { // is_some(), unwrap() diff --git a/tests/ui/manual_find_map.stderr b/tests/ui/manual_find_map.stderr index c1ac499f7c6..693a06bb559 100644 --- a/tests/ui/manual_find_map.stderr +++ b/tests/ui/manual_find_map.stderr @@ -1,5 +1,5 @@ error: `find(..).map(..)` can be simplified as `find_map(..)` - --> $DIR/manual_find_map.rs:8:19 + --> $DIR/manual_find_map.rs:9:19 | LL | let _ = (0..).find(|n| to_opt(*n).is_some()).map(|a| to_opt(a).unwrap()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `find_map(|a| to_opt(a))` @@ -7,19 +7,19 @@ LL | let _ = (0..).find(|n| to_opt(*n).is_some()).map(|a| to_opt(a).unwrap() = note: `-D clippy::manual-find-map` implied by `-D warnings` error: `find(..).map(..)` can be simplified as `find_map(..)` - --> $DIR/manual_find_map.rs:11:19 + --> $DIR/manual_find_map.rs:12:19 | LL | let _ = (0..).find(|&n| to_opt(n).is_some()).map(|a| to_opt(a).expect("hi")); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `find_map(|a| to_opt(a))` error: `find(..).map(..)` can be simplified as `find_map(..)` - --> $DIR/manual_find_map.rs:14:19 + --> $DIR/manual_find_map.rs:15:19 | LL | let _ = (0..).find(|&n| to_res(n).is_ok()).map(|a| to_res(a).unwrap_or(1)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `find_map(|a| to_res(a).ok())` error: `find(..).map(..)` can be simplified as `find_map(..)` - --> $DIR/manual_find_map.rs:17:10 + --> $DIR/manual_find_map.rs:18:10 | LL | .find(|&x| to_ref(to_opt(x)).is_some()) | __________^ @@ -27,7 +27,7 @@ LL | | .map(|y| to_ref(to_opt(y)).unwrap()); | |____________________________________________^ help: try: `find_map(|y| *to_ref(to_opt(y)))` error: `find(..).map(..)` can be simplified as `find_map(..)` - --> $DIR/manual_find_map.rs:20:10 + --> $DIR/manual_find_map.rs:21:10 | LL | .find(|x| to_ref(to_opt(*x)).is_some()) | __________^ @@ -35,7 +35,7 @@ LL | | .map(|y| to_ref(to_opt(y)).unwrap()); | |____________________________________________^ help: try: `find_map(|y| *to_ref(to_opt(y)))` error: `find(..).map(..)` can be simplified as `find_map(..)` - --> $DIR/manual_find_map.rs:24:10 + --> $DIR/manual_find_map.rs:25:10 | LL | .find(|&x| to_ref(to_res(x)).is_ok()) | __________^ @@ -43,7 +43,7 @@ LL | | .map(|y| to_ref(to_res(y)).unwrap()); | |____________________________________________^ help: try: `find_map(|y| to_ref(to_res(y)).ok())` error: `find(..).map(..)` can be simplified as `find_map(..)` - --> $DIR/manual_find_map.rs:27:10 + --> $DIR/manual_find_map.rs:28:10 | LL | .find(|x| to_ref(to_res(*x)).is_ok()) | __________^ @@ -51,91 +51,91 @@ LL | | .map(|y| to_ref(to_res(y)).unwrap()); | |____________________________________________^ help: try: `find_map(|y| to_ref(to_res(y)).ok())` error: `find(..).map(..)` can be simplified as `find_map(..)` - --> $DIR/manual_find_map.rs:33:26 + --> $DIR/manual_find_map.rs:34:26 | LL | iter::>().find(|x| x.is_some()).map(|x| x.unwrap()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `find_map(|x| x)` error: `find(..).map(..)` can be simplified as `find_map(..)` - --> $DIR/manual_find_map.rs:34:27 + --> $DIR/manual_find_map.rs:35:27 | LL | iter::<&Option>().find(|x| x.is_some()).map(|x| x.unwrap()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `find_map(|x| *x)` error: `find(..).map(..)` can be simplified as `find_map(..)` - --> $DIR/manual_find_map.rs:35:28 + --> $DIR/manual_find_map.rs:36:28 | LL | iter::<&&Option>().find(|x| x.is_some()).map(|x| x.unwrap()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `find_map(|x| **x)` error: `find(..).map(..)` can be simplified as `find_map(..)` - --> $DIR/manual_find_map.rs:36:27 + --> $DIR/manual_find_map.rs:37:27 | LL | iter::>().find(|x| x.is_some()).map(|x| x.cloned().unwrap()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `find_map(|x| x.cloned())` error: `find(..).map(..)` can be simplified as `find_map(..)` - --> $DIR/manual_find_map.rs:37:28 + --> $DIR/manual_find_map.rs:38:28 | LL | iter::<&Option<&u8>>().find(|x| x.is_some()).map(|x| x.cloned().unwrap()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `find_map(|x| x.cloned())` error: `find(..).map(..)` can be simplified as `find_map(..)` - --> $DIR/manual_find_map.rs:38:31 + --> $DIR/manual_find_map.rs:39:31 | LL | iter::<&Option>().find(|x| x.is_some()).map(|x| x.as_deref().unwrap()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `find_map(|x| x.as_deref())` error: `find(..).map(..)` can be simplified as `find_map(..)` - --> $DIR/manual_find_map.rs:39:31 + --> $DIR/manual_find_map.rs:40:31 | LL | iter::>().find(|&x| to_ref(x).is_some()).map(|y| to_ref(y).cloned().unwrap()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `find_map(|y| to_ref(y).cloned())` error: `find(..).map(..)` can be simplified as `find_map(..)` - --> $DIR/manual_find_map.rs:41:30 + --> $DIR/manual_find_map.rs:42:30 | LL | iter::>().find(|x| x.is_ok()).map(|x| x.unwrap()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `find_map(|x| x.ok())` error: `find(..).map(..)` can be simplified as `find_map(..)` - --> $DIR/manual_find_map.rs:42:31 + --> $DIR/manual_find_map.rs:43:31 | LL | iter::<&Result>().find(|x| x.is_ok()).map(|x| x.unwrap()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `find_map(|x| x.ok())` error: `find(..).map(..)` can be simplified as `find_map(..)` - --> $DIR/manual_find_map.rs:43:32 + --> $DIR/manual_find_map.rs:44:32 | LL | iter::<&&Result>().find(|x| x.is_ok()).map(|x| x.unwrap()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `find_map(|x| x.ok())` error: `find(..).map(..)` can be simplified as `find_map(..)` - --> $DIR/manual_find_map.rs:44:31 + --> $DIR/manual_find_map.rs:45:31 | LL | iter::>().find(|x| x.is_ok()).map(|x| x.cloned().unwrap()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `find_map(|x| x.cloned().ok())` error: `find(..).map(..)` can be simplified as `find_map(..)` - --> $DIR/manual_find_map.rs:45:32 + --> $DIR/manual_find_map.rs:46:32 | LL | iter::<&Result<&u8, ()>>().find(|x| x.is_ok()).map(|x| x.cloned().unwrap()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `find_map(|x| x.cloned().ok())` error: `find(..).map(..)` can be simplified as `find_map(..)` - --> $DIR/manual_find_map.rs:46:35 + --> $DIR/manual_find_map.rs:47:35 | LL | iter::<&Result>().find(|x| x.is_ok()).map(|x| x.as_deref().unwrap()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `find_map(|x| x.as_deref().ok())` error: `find(..).map(..)` can be simplified as `find_map(..)` - --> $DIR/manual_find_map.rs:47:35 + --> $DIR/manual_find_map.rs:48:35 | LL | iter::>().find(|&x| to_ref(x).is_ok()).map(|y| to_ref(y).cloned().unwrap()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `find_map(|y| to_ref(y).cloned().ok())` error: `find(..).map(..)` can be simplified as `find_map(..)` - --> $DIR/manual_find_map.rs:95:10 + --> $DIR/manual_find_map.rs:96:10 | LL | .find(|f| f.option_field.is_some()) | __________^ @@ -143,7 +143,7 @@ LL | | .map(|f| f.option_field.clone().unwrap()); | |_________________________________________________^ help: try: `find_map(|f| f.option_field.clone())` error: `find(..).map(..)` can be simplified as `find_map(..)` - --> $DIR/manual_find_map.rs:100:10 + --> $DIR/manual_find_map.rs:101:10 | LL | .find(|f| f.ref_field.is_some()) | __________^ @@ -151,7 +151,7 @@ LL | | .map(|f| f.ref_field.cloned().unwrap()); | |_______________________________________________^ help: try: `find_map(|f| f.ref_field.cloned())` error: `find(..).map(..)` can be simplified as `find_map(..)` - --> $DIR/manual_find_map.rs:105:10 + --> $DIR/manual_find_map.rs:106:10 | LL | .find(|f| f.ref_field.is_some()) | __________^ @@ -159,7 +159,7 @@ LL | | .map(|f| f.ref_field.copied().unwrap()); | |_______________________________________________^ help: try: `find_map(|f| f.ref_field.copied())` error: `find(..).map(..)` can be simplified as `find_map(..)` - --> $DIR/manual_find_map.rs:110:10 + --> $DIR/manual_find_map.rs:111:10 | LL | .find(|f| f.result_field.is_ok()) | __________^ @@ -167,7 +167,7 @@ LL | | .map(|f| f.result_field.clone().unwrap()); | |_________________________________________________^ help: try: `find_map(|f| f.result_field.clone().ok())` error: `find(..).map(..)` can be simplified as `find_map(..)` - --> $DIR/manual_find_map.rs:115:10 + --> $DIR/manual_find_map.rs:116:10 | LL | .find(|f| f.result_field.is_ok()) | __________^ @@ -175,7 +175,7 @@ LL | | .map(|f| f.result_field.as_ref().unwrap()); | |__________________________________________________^ help: try: `find_map(|f| f.result_field.as_ref().ok())` error: `find(..).map(..)` can be simplified as `find_map(..)` - --> $DIR/manual_find_map.rs:120:10 + --> $DIR/manual_find_map.rs:121:10 | LL | .find(|f| f.result_field.is_ok()) | __________^ @@ -183,7 +183,7 @@ LL | | .map(|f| f.result_field.as_deref().unwrap()); | |____________________________________________________^ help: try: `find_map(|f| f.result_field.as_deref().ok())` error: `find(..).map(..)` can be simplified as `find_map(..)` - --> $DIR/manual_find_map.rs:125:10 + --> $DIR/manual_find_map.rs:126:10 | LL | .find(|f| f.result_field.is_ok()) | __________^ @@ -191,7 +191,7 @@ LL | | .map(|f| f.result_field.as_mut().unwrap()); | |__________________________________________________^ help: try: `find_map(|f| f.result_field.as_mut().ok())` error: `find(..).map(..)` can be simplified as `find_map(..)` - --> $DIR/manual_find_map.rs:130:10 + --> $DIR/manual_find_map.rs:131:10 | LL | .find(|f| f.result_field.is_ok()) | __________^ @@ -199,7 +199,7 @@ LL | | .map(|f| f.result_field.as_deref_mut().unwrap()); | |________________________________________________________^ help: try: `find_map(|f| f.result_field.as_deref_mut().ok())` error: `find(..).map(..)` can be simplified as `find_map(..)` - --> $DIR/manual_find_map.rs:135:10 + --> $DIR/manual_find_map.rs:136:10 | LL | .find(|f| f.result_field.is_ok()) | __________^ diff --git a/tests/ui/manual_memcpy/without_loop_counters.rs b/tests/ui/manual_memcpy/without_loop_counters.rs index ea0535d076b..4d5c70f19a0 100644 --- a/tests/ui/manual_memcpy/without_loop_counters.rs +++ b/tests/ui/manual_memcpy/without_loop_counters.rs @@ -1,4 +1,5 @@ #![warn(clippy::needless_range_loop, clippy::manual_memcpy)] +#![allow(clippy::useless_vec)] const LOOP_OFFSET: usize = 5000; diff --git a/tests/ui/manual_memcpy/without_loop_counters.stderr b/tests/ui/manual_memcpy/without_loop_counters.stderr index c163ae061df..1c6a7d5c04e 100644 --- a/tests/ui/manual_memcpy/without_loop_counters.stderr +++ b/tests/ui/manual_memcpy/without_loop_counters.stderr @@ -1,5 +1,5 @@ error: it looks like you're manually copying between slices - --> $DIR/without_loop_counters.rs:7:5 + --> $DIR/without_loop_counters.rs:8:5 | LL | / for i in 0..src.len() { LL | | dst[i] = src[i]; @@ -9,7 +9,7 @@ LL | | } = note: `-D clippy::manual-memcpy` implied by `-D warnings` error: it looks like you're manually copying between slices - --> $DIR/without_loop_counters.rs:12:5 + --> $DIR/without_loop_counters.rs:13:5 | LL | / for i in 0..src.len() { LL | | dst[i + 10] = src[i]; @@ -17,7 +17,7 @@ LL | | } | |_____^ help: try replacing the loop by: `dst[10..(src.len() + 10)].copy_from_slice(&src[..]);` error: it looks like you're manually copying between slices - --> $DIR/without_loop_counters.rs:17:5 + --> $DIR/without_loop_counters.rs:18:5 | LL | / for i in 0..src.len() { LL | | dst[i] = src[i + 10]; @@ -25,7 +25,7 @@ LL | | } | |_____^ help: try replacing the loop by: `dst[..src.len()].copy_from_slice(&src[10..(src.len() + 10)]);` error: it looks like you're manually copying between slices - --> $DIR/without_loop_counters.rs:22:5 + --> $DIR/without_loop_counters.rs:23:5 | LL | / for i in 11..src.len() { LL | | dst[i] = src[i - 10]; @@ -33,7 +33,7 @@ LL | | } | |_____^ help: try replacing the loop by: `dst[11..src.len()].copy_from_slice(&src[(11 - 10)..(src.len() - 10)]);` error: it looks like you're manually copying between slices - --> $DIR/without_loop_counters.rs:27:5 + --> $DIR/without_loop_counters.rs:28:5 | LL | / for i in 0..dst.len() { LL | | dst[i] = src[i]; @@ -41,7 +41,7 @@ LL | | } | |_____^ help: try replacing the loop by: `dst.copy_from_slice(&src[..dst.len()]);` error: it looks like you're manually copying between slices - --> $DIR/without_loop_counters.rs:40:5 + --> $DIR/without_loop_counters.rs:41:5 | LL | / for i in 10..256 { LL | | dst[i] = src[i - 5]; @@ -56,7 +56,7 @@ LL + dst2[(10 + 500)..(256 + 500)].copy_from_slice(&src[10..256]); | error: it looks like you're manually copying between slices - --> $DIR/without_loop_counters.rs:52:5 + --> $DIR/without_loop_counters.rs:53:5 | LL | / for i in 10..LOOP_OFFSET { LL | | dst[i + LOOP_OFFSET] = src[i - some_var]; @@ -64,7 +64,7 @@ LL | | } | |_____^ help: try replacing the loop by: `dst[(10 + LOOP_OFFSET)..(LOOP_OFFSET + LOOP_OFFSET)].copy_from_slice(&src[(10 - some_var)..(LOOP_OFFSET - some_var)]);` error: it looks like you're manually copying between slices - --> $DIR/without_loop_counters.rs:65:5 + --> $DIR/without_loop_counters.rs:66:5 | LL | / for i in 0..src_vec.len() { LL | | dst_vec[i] = src_vec[i]; @@ -72,7 +72,7 @@ LL | | } | |_____^ help: try replacing the loop by: `dst_vec[..src_vec.len()].copy_from_slice(&src_vec[..]);` error: it looks like you're manually copying between slices - --> $DIR/without_loop_counters.rs:94:5 + --> $DIR/without_loop_counters.rs:95:5 | LL | / for i in from..from + src.len() { LL | | dst[i] = src[i - from]; @@ -80,7 +80,7 @@ LL | | } | |_____^ help: try replacing the loop by: `dst[from..(from + src.len())].copy_from_slice(&src[..(from + src.len() - from)]);` error: it looks like you're manually copying between slices - --> $DIR/without_loop_counters.rs:98:5 + --> $DIR/without_loop_counters.rs:99:5 | LL | / for i in from..from + 3 { LL | | dst[i] = src[i - from]; @@ -88,7 +88,7 @@ LL | | } | |_____^ help: try replacing the loop by: `dst[from..(from + 3)].copy_from_slice(&src[..(from + 3 - from)]);` error: it looks like you're manually copying between slices - --> $DIR/without_loop_counters.rs:103:5 + --> $DIR/without_loop_counters.rs:104:5 | LL | / for i in 0..5 { LL | | dst[i - 0] = src[i]; @@ -96,7 +96,7 @@ LL | | } | |_____^ help: try replacing the loop by: `dst[..5].copy_from_slice(&src[..5]);` error: it looks like you're manually copying between slices - --> $DIR/without_loop_counters.rs:108:5 + --> $DIR/without_loop_counters.rs:109:5 | LL | / for i in 0..0 { LL | | dst[i] = src[i]; @@ -104,7 +104,7 @@ LL | | } | |_____^ help: try replacing the loop by: `dst[..0].copy_from_slice(&src[..0]);` error: it looks like you're manually copying between slices - --> $DIR/without_loop_counters.rs:131:5 + --> $DIR/without_loop_counters.rs:132:5 | LL | / for i in 0..src.len() { LL | | dst[i] = src[i].clone(); diff --git a/tests/ui/map_clone.fixed b/tests/ui/map_clone.fixed index d7474f35719..50c0eb1a810 100644 --- a/tests/ui/map_clone.fixed +++ b/tests/ui/map_clone.fixed @@ -4,7 +4,8 @@ clippy::clone_on_copy, clippy::iter_cloned_collect, clippy::many_single_char_names, - clippy::redundant_clone + clippy::redundant_clone, + clippy::useless_vec )] fn main() { diff --git a/tests/ui/map_clone.rs b/tests/ui/map_clone.rs index 74978ae8006..91a084f2844 100644 --- a/tests/ui/map_clone.rs +++ b/tests/ui/map_clone.rs @@ -4,7 +4,8 @@ clippy::clone_on_copy, clippy::iter_cloned_collect, clippy::many_single_char_names, - clippy::redundant_clone + clippy::redundant_clone, + clippy::useless_vec )] fn main() { diff --git a/tests/ui/map_clone.stderr b/tests/ui/map_clone.stderr index d84a5bf8d4d..d768af1f48c 100644 --- a/tests/ui/map_clone.stderr +++ b/tests/ui/map_clone.stderr @@ -1,5 +1,5 @@ error: you are using an explicit closure for copying elements - --> $DIR/map_clone.rs:11:22 + --> $DIR/map_clone.rs:12:22 | LL | let _: Vec = vec![5_i8; 6].iter().map(|x| *x).collect(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider calling the dedicated `copied` method: `vec![5_i8; 6].iter().copied()` @@ -7,31 +7,31 @@ LL | let _: Vec = vec![5_i8; 6].iter().map(|x| *x).collect(); = note: `-D clippy::map-clone` implied by `-D warnings` error: you are using an explicit closure for cloning elements - --> $DIR/map_clone.rs:12:26 + --> $DIR/map_clone.rs:13:26 | LL | let _: Vec = vec![String::new()].iter().map(|x| x.clone()).collect(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider calling the dedicated `cloned` method: `vec![String::new()].iter().cloned()` error: you are using an explicit closure for copying elements - --> $DIR/map_clone.rs:13:23 + --> $DIR/map_clone.rs:14:23 | LL | let _: Vec = vec![42, 43].iter().map(|&x| x).collect(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider calling the dedicated `copied` method: `vec![42, 43].iter().copied()` error: you are using an explicit closure for copying elements - --> $DIR/map_clone.rs:15:26 + --> $DIR/map_clone.rs:16:26 | LL | let _: Option = Some(&16).map(|b| *b); | ^^^^^^^^^^^^^^^^^^^^^ help: consider calling the dedicated `copied` method: `Some(&16).copied()` error: you are using an explicit closure for copying elements - --> $DIR/map_clone.rs:16:25 + --> $DIR/map_clone.rs:17:25 | LL | let _: Option = Some(&1).map(|x| x.clone()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider calling the dedicated `copied` method: `Some(&1).copied()` error: you are needlessly cloning iterator elements - --> $DIR/map_clone.rs:27:29 + --> $DIR/map_clone.rs:28:29 | LL | let _ = std::env::args().map(|v| v.clone()); | ^^^^^^^^^^^^^^^^^^^ help: remove the `map` call diff --git a/tests/ui/match_on_vec_items.rs b/tests/ui/match_on_vec_items.rs index 30415e3b94d..d82a736963a 100644 --- a/tests/ui/match_on_vec_items.rs +++ b/tests/ui/match_on_vec_items.rs @@ -1,4 +1,5 @@ #![warn(clippy::match_on_vec_items)] +#![allow(clippy::useless_vec)] fn match_with_wildcard() { let arr = vec![0, 1, 2, 3]; diff --git a/tests/ui/match_on_vec_items.stderr b/tests/ui/match_on_vec_items.stderr index 49446d715ab..9b1f052867e 100644 --- a/tests/ui/match_on_vec_items.stderr +++ b/tests/ui/match_on_vec_items.stderr @@ -1,5 +1,5 @@ error: indexing into a vector may panic - --> $DIR/match_on_vec_items.rs:9:11 + --> $DIR/match_on_vec_items.rs:10:11 | LL | match arr[idx] { | ^^^^^^^^ help: try this: `arr.get(idx)` @@ -7,43 +7,43 @@ LL | match arr[idx] { = note: `-D clippy::match-on-vec-items` implied by `-D warnings` error: indexing into a vector may panic - --> $DIR/match_on_vec_items.rs:16:11 + --> $DIR/match_on_vec_items.rs:17:11 | LL | match arr[range] { | ^^^^^^^^^^ help: try this: `arr.get(range)` error: indexing into a vector may panic - --> $DIR/match_on_vec_items.rs:29:11 + --> $DIR/match_on_vec_items.rs:30:11 | LL | match arr[idx] { | ^^^^^^^^ help: try this: `arr.get(idx)` error: indexing into a vector may panic - --> $DIR/match_on_vec_items.rs:36:11 + --> $DIR/match_on_vec_items.rs:37:11 | LL | match arr[range] { | ^^^^^^^^^^ help: try this: `arr.get(range)` error: indexing into a vector may panic - --> $DIR/match_on_vec_items.rs:49:11 + --> $DIR/match_on_vec_items.rs:50:11 | LL | match arr[idx] { | ^^^^^^^^ help: try this: `arr.get(idx)` error: indexing into a vector may panic - --> $DIR/match_on_vec_items.rs:56:11 + --> $DIR/match_on_vec_items.rs:57:11 | LL | match arr[range] { | ^^^^^^^^^^ help: try this: `arr.get(range)` error: indexing into a vector may panic - --> $DIR/match_on_vec_items.rs:69:11 + --> $DIR/match_on_vec_items.rs:70:11 | LL | match arr[idx] { | ^^^^^^^^ help: try this: `arr.get(idx)` error: indexing into a vector may panic - --> $DIR/match_on_vec_items.rs:76:11 + --> $DIR/match_on_vec_items.rs:77:11 | LL | match arr[range] { | ^^^^^^^^^^ help: try this: `arr.get(range)` diff --git a/tests/ui/match_single_binding.fixed b/tests/ui/match_single_binding.fixed index 7c29bb08e64..f59ff456bf2 100644 --- a/tests/ui/match_single_binding.fixed +++ b/tests/ui/match_single_binding.fixed @@ -5,7 +5,8 @@ clippy::let_unit_value, clippy::no_effect, clippy::toplevel_ref_arg, - clippy::uninlined_format_args + clippy::uninlined_format_args, + clippy::useless_vec )] struct Point { diff --git a/tests/ui/match_single_binding.rs b/tests/ui/match_single_binding.rs index c068d5e17c3..e293bc33c8a 100644 --- a/tests/ui/match_single_binding.rs +++ b/tests/ui/match_single_binding.rs @@ -5,7 +5,8 @@ clippy::let_unit_value, clippy::no_effect, clippy::toplevel_ref_arg, - clippy::uninlined_format_args + clippy::uninlined_format_args, + clippy::useless_vec )] struct Point { diff --git a/tests/ui/match_single_binding.stderr b/tests/ui/match_single_binding.stderr index 9d16af76c6a..8998786de7e 100644 --- a/tests/ui/match_single_binding.stderr +++ b/tests/ui/match_single_binding.stderr @@ -1,5 +1,5 @@ error: this match could be written as a `let` statement - --> $DIR/match_single_binding.rs:33:5 + --> $DIR/match_single_binding.rs:34:5 | LL | / match (a, b, c) { LL | | (x, y, z) => { @@ -18,7 +18,7 @@ LL + } | error: this match could be written as a `let` statement - --> $DIR/match_single_binding.rs:39:5 + --> $DIR/match_single_binding.rs:40:5 | LL | / match (a, b, c) { LL | | (x, y, z) => println!("{} {} {}", x, y, z), @@ -32,7 +32,7 @@ LL + println!("{} {} {}", x, y, z); | error: this match could be replaced by its body itself - --> $DIR/match_single_binding.rs:56:5 + --> $DIR/match_single_binding.rs:57:5 | LL | / match a { LL | | _ => println!("whatever"), @@ -40,7 +40,7 @@ LL | | } | |_____^ help: consider using the match body instead: `println!("whatever");` error: this match could be replaced by its body itself - --> $DIR/match_single_binding.rs:60:5 + --> $DIR/match_single_binding.rs:61:5 | LL | / match a { LL | | _ => { @@ -59,7 +59,7 @@ LL + } | error: this match could be replaced by its body itself - --> $DIR/match_single_binding.rs:67:5 + --> $DIR/match_single_binding.rs:68:5 | LL | / match a { LL | | _ => { @@ -81,7 +81,7 @@ LL + } | error: this match could be written as a `let` statement - --> $DIR/match_single_binding.rs:77:5 + --> $DIR/match_single_binding.rs:78:5 | LL | / match p { LL | | Point { x, y } => println!("Coords: ({}, {})", x, y), @@ -95,7 +95,7 @@ LL + println!("Coords: ({}, {})", x, y); | error: this match could be written as a `let` statement - --> $DIR/match_single_binding.rs:81:5 + --> $DIR/match_single_binding.rs:82:5 | LL | / match p { LL | | Point { x: x1, y: y1 } => println!("Coords: ({}, {})", x1, y1), @@ -109,7 +109,7 @@ LL + println!("Coords: ({}, {})", x1, y1); | error: this match could be written as a `let` statement - --> $DIR/match_single_binding.rs:86:5 + --> $DIR/match_single_binding.rs:87:5 | LL | / match x { LL | | ref r => println!("Got a reference to {}", r), @@ -123,7 +123,7 @@ LL + println!("Got a reference to {}", r); | error: this match could be written as a `let` statement - --> $DIR/match_single_binding.rs:91:5 + --> $DIR/match_single_binding.rs:92:5 | LL | / match x { LL | | ref mut mr => println!("Got a mutable reference to {}", mr), @@ -137,7 +137,7 @@ LL + println!("Got a mutable reference to {}", mr); | error: this match could be written as a `let` statement - --> $DIR/match_single_binding.rs:95:5 + --> $DIR/match_single_binding.rs:96:5 | LL | / let product = match coords() { LL | | Point { x, y } => x * y, @@ -151,7 +151,7 @@ LL + let product = x * y; | error: this match could be written as a `let` statement - --> $DIR/match_single_binding.rs:103:18 + --> $DIR/match_single_binding.rs:104:18 | LL | .map(|i| match i.unwrap() { | __________________^ @@ -168,7 +168,7 @@ LL ~ }) | error: this match could be replaced by its body itself - --> $DIR/match_single_binding.rs:129:5 + --> $DIR/match_single_binding.rs:130:5 | LL | / match x { LL | | // => @@ -177,7 +177,7 @@ LL | | } | |_____^ help: consider using the match body instead: `println!("Not an array index start")` error: this assignment could be simplified - --> $DIR/match_single_binding.rs:138:5 + --> $DIR/match_single_binding.rs:139:5 | LL | / val = match val.split_at(idx) { LL | | (pre, suf) => { @@ -197,7 +197,7 @@ LL ~ }; | error: this match could be replaced by its scrutinee and body - --> $DIR/match_single_binding.rs:151:16 + --> $DIR/match_single_binding.rs:152:16 | LL | let _ = || match side_effects() { | ________________^ @@ -214,7 +214,7 @@ LL ~ }; | error: this match could be written as a `let` statement - --> $DIR/match_single_binding.rs:157:5 + --> $DIR/match_single_binding.rs:158:5 | LL | / match r { LL | | x => match x { @@ -239,7 +239,7 @@ LL ~ }; | error: this match could be replaced by its body itself - --> $DIR/match_single_binding.rs:170:5 + --> $DIR/match_single_binding.rs:171:5 | LL | / match 1 { LL | | _ => (), @@ -247,7 +247,7 @@ LL | | } | |_____^ help: consider using the match body instead: `();` error: this match could be replaced by its body itself - --> $DIR/match_single_binding.rs:174:13 + --> $DIR/match_single_binding.rs:175:13 | LL | let a = match 1 { | _____________^ @@ -256,7 +256,7 @@ LL | | }; | |_____^ help: consider using the match body instead: `()` error: this match could be replaced by its body itself - --> $DIR/match_single_binding.rs:178:5 + --> $DIR/match_single_binding.rs:179:5 | LL | / match 1 { LL | | _ => side_effects(), @@ -264,7 +264,7 @@ LL | | } | |_____^ help: consider using the match body instead: `side_effects();` error: this match could be replaced by its body itself - --> $DIR/match_single_binding.rs:182:13 + --> $DIR/match_single_binding.rs:183:13 | LL | let b = match 1 { | _____________^ @@ -273,7 +273,7 @@ LL | | }; | |_____^ help: consider using the match body instead: `side_effects()` error: this match could be replaced by its body itself - --> $DIR/match_single_binding.rs:186:5 + --> $DIR/match_single_binding.rs:187:5 | LL | / match 1 { LL | | _ => println!("1"), @@ -281,7 +281,7 @@ LL | | } | |_____^ help: consider using the match body instead: `println!("1");` error: this match could be replaced by its body itself - --> $DIR/match_single_binding.rs:190:13 + --> $DIR/match_single_binding.rs:191:13 | LL | let c = match 1 { | _____________^ @@ -290,7 +290,7 @@ LL | | }; | |_____^ help: consider using the match body instead: `println!("1")` error: this match could be replaced by its body itself - --> $DIR/match_single_binding.rs:195:9 + --> $DIR/match_single_binding.rs:196:9 | LL | / match 1 { LL | | _ => (), @@ -298,7 +298,7 @@ LL | | }, | |_________^ help: consider using the match body instead: `()` error: this match could be replaced by its body itself - --> $DIR/match_single_binding.rs:198:9 + --> $DIR/match_single_binding.rs:199:9 | LL | / match 1 { LL | | _ => side_effects(), @@ -306,7 +306,7 @@ LL | | }, | |_________^ help: consider using the match body instead: `side_effects()` error: this match could be replaced by its body itself - --> $DIR/match_single_binding.rs:201:9 + --> $DIR/match_single_binding.rs:202:9 | LL | / match 1 { LL | | _ => println!("1"), diff --git a/tests/ui/methods.rs b/tests/ui/methods.rs index e0e2cac30a2..589eab5cdfc 100644 --- a/tests/ui/methods.rs +++ b/tests/ui/methods.rs @@ -18,6 +18,7 @@ clippy::wrong_self_convention, clippy::unused_async, clippy::unused_self, + clippy::useless_vec, unused )] diff --git a/tests/ui/methods.stderr b/tests/ui/methods.stderr index 4643e09e270..73ec48643e0 100644 --- a/tests/ui/methods.stderr +++ b/tests/ui/methods.stderr @@ -1,5 +1,5 @@ error: methods called `new` usually return `Self` - --> $DIR/methods.rs:105:5 + --> $DIR/methods.rs:106:5 | LL | / fn new() -> i32 { LL | | 0 @@ -9,7 +9,7 @@ LL | | } = note: `-D clippy::new-ret-no-self` implied by `-D warnings` error: called `filter(..).next()` on an `Iterator`. This is more succinctly expressed by calling `.find(..)` instead - --> $DIR/methods.rs:126:13 + --> $DIR/methods.rs:127:13 | LL | let _ = v.iter().filter(|&x| { | _____________^ diff --git a/tests/ui/methods_fixable.fixed b/tests/ui/methods_fixable.fixed index dcbed5a4d99..ce5d19a8b6e 100644 --- a/tests/ui/methods_fixable.fixed +++ b/tests/ui/methods_fixable.fixed @@ -1,6 +1,7 @@ //@run-rustfix #![warn(clippy::filter_next)] +#![allow(clippy::useless_vec)] /// Checks implementation of `FILTER_NEXT` lint. fn main() { diff --git a/tests/ui/methods_fixable.rs b/tests/ui/methods_fixable.rs index 3a976d23527..0615817ec92 100644 --- a/tests/ui/methods_fixable.rs +++ b/tests/ui/methods_fixable.rs @@ -1,6 +1,7 @@ //@run-rustfix #![warn(clippy::filter_next)] +#![allow(clippy::useless_vec)] /// Checks implementation of `FILTER_NEXT` lint. fn main() { diff --git a/tests/ui/methods_fixable.stderr b/tests/ui/methods_fixable.stderr index 852f48e32d6..187714c75fb 100644 --- a/tests/ui/methods_fixable.stderr +++ b/tests/ui/methods_fixable.stderr @@ -1,5 +1,5 @@ error: called `filter(..).next()` on an `Iterator`. This is more succinctly expressed by calling `.find(..)` instead - --> $DIR/methods_fixable.rs:10:13 + --> $DIR/methods_fixable.rs:11:13 | LL | let _ = v.iter().filter(|&x| *x < 0).next(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `v.iter().find(|&x| *x < 0)` diff --git a/tests/ui/needless_collect_indirect.rs b/tests/ui/needless_collect_indirect.rs index fe4209e99b2..55a7c2c21d9 100644 --- a/tests/ui/needless_collect_indirect.rs +++ b/tests/ui/needless_collect_indirect.rs @@ -1,4 +1,4 @@ -#![allow(clippy::uninlined_format_args)] +#![allow(clippy::uninlined_format_args, clippy::useless_vec)] #![warn(clippy::needless_collect)] use std::collections::{BinaryHeap, HashMap, HashSet, LinkedList, VecDeque}; diff --git a/tests/ui/needless_late_init.fixed b/tests/ui/needless_late_init.fixed index 92f7b3f777a..b3ed0932ab5 100644 --- a/tests/ui/needless_late_init.fixed +++ b/tests/ui/needless_late_init.fixed @@ -8,7 +8,8 @@ clippy::let_and_return, clippy::let_unit_value, clippy::nonminimal_bool, - clippy::uninlined_format_args + clippy::uninlined_format_args, + clippy::useless_vec )] extern crate proc_macros; diff --git a/tests/ui/needless_late_init.rs b/tests/ui/needless_late_init.rs index be378c42f95..dbbbf24085e 100644 --- a/tests/ui/needless_late_init.rs +++ b/tests/ui/needless_late_init.rs @@ -8,7 +8,8 @@ clippy::let_and_return, clippy::let_unit_value, clippy::nonminimal_bool, - clippy::uninlined_format_args + clippy::uninlined_format_args, + clippy::useless_vec )] extern crate proc_macros; diff --git a/tests/ui/needless_late_init.stderr b/tests/ui/needless_late_init.stderr index eff782f8bf1..78ba8e11c57 100644 --- a/tests/ui/needless_late_init.stderr +++ b/tests/ui/needless_late_init.stderr @@ -1,5 +1,5 @@ error: unneeded late initialization - --> $DIR/needless_late_init.rs:27:5 + --> $DIR/needless_late_init.rs:28:5 | LL | let a; | ^^^^^^ created here @@ -13,7 +13,7 @@ LL | let a = "zero"; | ~~~~~ error: unneeded late initialization - --> $DIR/needless_late_init.rs:30:5 + --> $DIR/needless_late_init.rs:31:5 | LL | let b; | ^^^^^^ created here @@ -27,7 +27,7 @@ LL | let b = 1; | ~~~~~ error: unneeded late initialization - --> $DIR/needless_late_init.rs:31:5 + --> $DIR/needless_late_init.rs:32:5 | LL | let c; | ^^^^^^ created here @@ -41,7 +41,7 @@ LL | let c = 2; | ~~~~~ error: unneeded late initialization - --> $DIR/needless_late_init.rs:35:5 + --> $DIR/needless_late_init.rs:36:5 | LL | let d: usize; | ^^^^^^^^^^^^^ created here @@ -54,7 +54,7 @@ LL | let d: usize = 1; | ~~~~~~~~~~~~ error: unneeded late initialization - --> $DIR/needless_late_init.rs:38:5 + --> $DIR/needless_late_init.rs:39:5 | LL | let e; | ^^^^^^ created here @@ -67,7 +67,7 @@ LL | let e = format!("{}", d); | ~~~~~ error: unneeded late initialization - --> $DIR/needless_late_init.rs:43:5 + --> $DIR/needless_late_init.rs:44:5 | LL | let a; | ^^^^^^ @@ -88,7 +88,7 @@ LL | }; | + error: unneeded late initialization - --> $DIR/needless_late_init.rs:52:5 + --> $DIR/needless_late_init.rs:53:5 | LL | let b; | ^^^^^^ @@ -109,7 +109,7 @@ LL | }; | + error: unneeded late initialization - --> $DIR/needless_late_init.rs:59:5 + --> $DIR/needless_late_init.rs:60:5 | LL | let d; | ^^^^^^ @@ -130,7 +130,7 @@ LL | }; | + error: unneeded late initialization - --> $DIR/needless_late_init.rs:67:5 + --> $DIR/needless_late_init.rs:68:5 | LL | let e; | ^^^^^^ @@ -151,7 +151,7 @@ LL | }; | + error: unneeded late initialization - --> $DIR/needless_late_init.rs:74:5 + --> $DIR/needless_late_init.rs:75:5 | LL | let f; | ^^^^^^ @@ -167,7 +167,7 @@ LL + 1 => "three", | error: unneeded late initialization - --> $DIR/needless_late_init.rs:80:5 + --> $DIR/needless_late_init.rs:81:5 | LL | let g: usize; | ^^^^^^^^^^^^^ @@ -187,7 +187,7 @@ LL | }; | + error: unneeded late initialization - --> $DIR/needless_late_init.rs:88:5 + --> $DIR/needless_late_init.rs:89:5 | LL | let x; | ^^^^^^ created here @@ -201,7 +201,7 @@ LL | let x = 1; | ~~~~~ error: unneeded late initialization - --> $DIR/needless_late_init.rs:92:5 + --> $DIR/needless_late_init.rs:93:5 | LL | let x; | ^^^^^^ created here @@ -215,7 +215,7 @@ LL | let x = SignificantDrop; | ~~~~~ error: unneeded late initialization - --> $DIR/needless_late_init.rs:96:5 + --> $DIR/needless_late_init.rs:97:5 | LL | let x; | ^^^^^^ created here @@ -229,7 +229,7 @@ LL | let x = SignificantDrop; | ~~~~~ error: unneeded late initialization - --> $DIR/needless_late_init.rs:115:5 + --> $DIR/needless_late_init.rs:116:5 | LL | let a; | ^^^^^^ @@ -250,7 +250,7 @@ LL | }; | + error: unneeded late initialization - --> $DIR/needless_late_init.rs:132:5 + --> $DIR/needless_late_init.rs:133:5 | LL | let a; | ^^^^^^ diff --git a/tests/ui/needless_option_as_deref.fixed b/tests/ui/needless_option_as_deref.fixed index 70015fccf9e..ec981ad97e3 100644 --- a/tests/ui/needless_option_as_deref.fixed +++ b/tests/ui/needless_option_as_deref.fixed @@ -2,6 +2,7 @@ #![allow(unused)] #![warn(clippy::needless_option_as_deref)] +#![allow(clippy::useless_vec)] fn main() { // should lint diff --git a/tests/ui/needless_option_as_deref.rs b/tests/ui/needless_option_as_deref.rs index e2e35360cb3..6360874f623 100644 --- a/tests/ui/needless_option_as_deref.rs +++ b/tests/ui/needless_option_as_deref.rs @@ -2,6 +2,7 @@ #![allow(unused)] #![warn(clippy::needless_option_as_deref)] +#![allow(clippy::useless_vec)] fn main() { // should lint diff --git a/tests/ui/needless_option_as_deref.stderr b/tests/ui/needless_option_as_deref.stderr index bc07db5b38e..20d28a968c9 100644 --- a/tests/ui/needless_option_as_deref.stderr +++ b/tests/ui/needless_option_as_deref.stderr @@ -1,5 +1,5 @@ error: derefed type is same as origin - --> $DIR/needless_option_as_deref.rs:8:29 + --> $DIR/needless_option_as_deref.rs:9:29 | LL | let _: Option<&usize> = Some(&1).as_deref(); | ^^^^^^^^^^^^^^^^^^^ help: try this: `Some(&1)` @@ -7,13 +7,13 @@ LL | let _: Option<&usize> = Some(&1).as_deref(); = note: `-D clippy::needless-option-as-deref` implied by `-D warnings` error: derefed type is same as origin - --> $DIR/needless_option_as_deref.rs:9:33 + --> $DIR/needless_option_as_deref.rs:10:33 | LL | let _: Option<&mut usize> = Some(&mut 1).as_deref_mut(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `Some(&mut 1)` error: derefed type is same as origin - --> $DIR/needless_option_as_deref.rs:13:13 + --> $DIR/needless_option_as_deref.rs:14:13 | LL | let _ = x.as_deref_mut(); | ^^^^^^^^^^^^^^^^ help: try this: `x` diff --git a/tests/ui/needless_range_loop.rs b/tests/ui/needless_range_loop.rs index 921801138a9..329cdc1f06b 100644 --- a/tests/ui/needless_range_loop.rs +++ b/tests/ui/needless_range_loop.rs @@ -1,5 +1,5 @@ #![warn(clippy::needless_range_loop)] -#![allow(clippy::uninlined_format_args)] +#![allow(clippy::uninlined_format_args, clippy::useless_vec)] static STATIC: [usize; 4] = [0, 1, 8, 16]; const CONST: [usize; 4] = [0, 1, 8, 16]; diff --git a/tests/ui/needless_range_loop2.rs b/tests/ui/needless_range_loop2.rs index 7633316e0f8..516d99a3532 100644 --- a/tests/ui/needless_range_loop2.rs +++ b/tests/ui/needless_range_loop2.rs @@ -1,4 +1,5 @@ #![warn(clippy::needless_range_loop)] +#![allow(clippy::useless_vec)] fn calc_idx(i: usize) -> usize { (i + i + 20) % 4 diff --git a/tests/ui/needless_range_loop2.stderr b/tests/ui/needless_range_loop2.stderr index 1e6ec5e667a..8c4f5d954a9 100644 --- a/tests/ui/needless_range_loop2.stderr +++ b/tests/ui/needless_range_loop2.stderr @@ -1,5 +1,5 @@ error: the loop variable `i` is only used to index `ns` - --> $DIR/needless_range_loop2.rs:10:14 + --> $DIR/needless_range_loop2.rs:11:14 | LL | for i in 3..10 { | ^^^^^ @@ -11,7 +11,7 @@ LL | for in ns.iter().take(10).skip(3) { | ~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~ error: the loop variable `i` is only used to index `ms` - --> $DIR/needless_range_loop2.rs:31:14 + --> $DIR/needless_range_loop2.rs:32:14 | LL | for i in 0..ms.len() { | ^^^^^^^^^^^ @@ -22,7 +22,7 @@ LL | for in &mut ms { | ~~~~~~ ~~~~~~~ error: the loop variable `i` is only used to index `ms` - --> $DIR/needless_range_loop2.rs:37:14 + --> $DIR/needless_range_loop2.rs:38:14 | LL | for i in 0..ms.len() { | ^^^^^^^^^^^ @@ -33,7 +33,7 @@ LL | for in &mut ms { | ~~~~~~ ~~~~~~~ error: the loop variable `i` is only used to index `vec` - --> $DIR/needless_range_loop2.rs:61:14 + --> $DIR/needless_range_loop2.rs:62:14 | LL | for i in x..x + 4 { | ^^^^^^^^ @@ -44,7 +44,7 @@ LL | for in vec.iter_mut().skip(x).take(4) { | ~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ error: the loop variable `i` is only used to index `vec` - --> $DIR/needless_range_loop2.rs:68:14 + --> $DIR/needless_range_loop2.rs:69:14 | LL | for i in x..=x + 4 { | ^^^^^^^^^ @@ -55,7 +55,7 @@ LL | for in vec.iter_mut().skip(x).take(4 + 1) { | ~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ error: the loop variable `i` is only used to index `arr` - --> $DIR/needless_range_loop2.rs:74:14 + --> $DIR/needless_range_loop2.rs:75:14 | LL | for i in 0..3 { | ^^^^ @@ -66,7 +66,7 @@ LL | for in &arr { | ~~~~~~ ~~~~ error: the loop variable `i` is only used to index `arr` - --> $DIR/needless_range_loop2.rs:78:14 + --> $DIR/needless_range_loop2.rs:79:14 | LL | for i in 0..2 { | ^^^^ @@ -77,7 +77,7 @@ LL | for in arr.iter().take(2) { | ~~~~~~ ~~~~~~~~~~~~~~~~~~ error: the loop variable `i` is only used to index `arr` - --> $DIR/needless_range_loop2.rs:82:14 + --> $DIR/needless_range_loop2.rs:83:14 | LL | for i in 1..3 { | ^^^^ diff --git a/tests/ui/no_effect.rs b/tests/ui/no_effect.rs index 1e42e1fbabf..6a726941be8 100644 --- a/tests/ui/no_effect.rs +++ b/tests/ui/no_effect.rs @@ -5,7 +5,8 @@ clippy::deref_addrof, clippy::redundant_field_names, clippy::uninlined_format_args, - clippy::unnecessary_struct_initialization + clippy::unnecessary_struct_initialization, + clippy::useless_vec )] struct Unit; diff --git a/tests/ui/no_effect.stderr b/tests/ui/no_effect.stderr index f10f2bcf2a8..64edfc32504 100644 --- a/tests/ui/no_effect.stderr +++ b/tests/ui/no_effect.stderr @@ -1,5 +1,5 @@ error: statement with no effect - --> $DIR/no_effect.rs:97:5 + --> $DIR/no_effect.rs:98:5 | LL | 0; | ^^ @@ -7,151 +7,151 @@ LL | 0; = note: `-D clippy::no-effect` implied by `-D warnings` error: statement with no effect - --> $DIR/no_effect.rs:98:5 + --> $DIR/no_effect.rs:99:5 | LL | s2; | ^^^ error: statement with no effect - --> $DIR/no_effect.rs:99:5 + --> $DIR/no_effect.rs:100:5 | LL | Unit; | ^^^^^ error: statement with no effect - --> $DIR/no_effect.rs:100:5 + --> $DIR/no_effect.rs:101:5 | LL | Tuple(0); | ^^^^^^^^^ error: statement with no effect - --> $DIR/no_effect.rs:101:5 + --> $DIR/no_effect.rs:102:5 | LL | Struct { field: 0 }; | ^^^^^^^^^^^^^^^^^^^^ error: statement with no effect - --> $DIR/no_effect.rs:102:5 + --> $DIR/no_effect.rs:103:5 | LL | Struct { ..s }; | ^^^^^^^^^^^^^^^ error: statement with no effect - --> $DIR/no_effect.rs:103:5 + --> $DIR/no_effect.rs:104:5 | LL | Union { a: 0 }; | ^^^^^^^^^^^^^^^ error: statement with no effect - --> $DIR/no_effect.rs:104:5 + --> $DIR/no_effect.rs:105:5 | LL | Enum::Tuple(0); | ^^^^^^^^^^^^^^^ error: statement with no effect - --> $DIR/no_effect.rs:105:5 + --> $DIR/no_effect.rs:106:5 | LL | Enum::Struct { field: 0 }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^ error: statement with no effect - --> $DIR/no_effect.rs:106:5 + --> $DIR/no_effect.rs:107:5 | LL | 5 + 6; | ^^^^^^ error: statement with no effect - --> $DIR/no_effect.rs:107:5 + --> $DIR/no_effect.rs:108:5 | LL | *&42; | ^^^^^ error: statement with no effect - --> $DIR/no_effect.rs:108:5 + --> $DIR/no_effect.rs:109:5 | LL | &6; | ^^^ error: statement with no effect - --> $DIR/no_effect.rs:109:5 + --> $DIR/no_effect.rs:110:5 | LL | (5, 6, 7); | ^^^^^^^^^^ error: statement with no effect - --> $DIR/no_effect.rs:110:5 + --> $DIR/no_effect.rs:111:5 | LL | ..; | ^^^ error: statement with no effect - --> $DIR/no_effect.rs:111:5 + --> $DIR/no_effect.rs:112:5 | LL | 5..; | ^^^^ error: statement with no effect - --> $DIR/no_effect.rs:112:5 + --> $DIR/no_effect.rs:113:5 | LL | ..5; | ^^^^ error: statement with no effect - --> $DIR/no_effect.rs:113:5 + --> $DIR/no_effect.rs:114:5 | LL | 5..6; | ^^^^^ error: statement with no effect - --> $DIR/no_effect.rs:114:5 + --> $DIR/no_effect.rs:115:5 | LL | 5..=6; | ^^^^^^ error: statement with no effect - --> $DIR/no_effect.rs:115:5 + --> $DIR/no_effect.rs:116:5 | LL | [42, 55]; | ^^^^^^^^^ error: statement with no effect - --> $DIR/no_effect.rs:116:5 + --> $DIR/no_effect.rs:117:5 | LL | [42, 55][1]; | ^^^^^^^^^^^^ error: statement with no effect - --> $DIR/no_effect.rs:117:5 + --> $DIR/no_effect.rs:118:5 | LL | (42, 55).1; | ^^^^^^^^^^^ error: statement with no effect - --> $DIR/no_effect.rs:118:5 + --> $DIR/no_effect.rs:119:5 | LL | [42; 55]; | ^^^^^^^^^ error: statement with no effect - --> $DIR/no_effect.rs:119:5 + --> $DIR/no_effect.rs:120:5 | LL | [42; 55][13]; | ^^^^^^^^^^^^^ error: statement with no effect - --> $DIR/no_effect.rs:121:5 + --> $DIR/no_effect.rs:122:5 | LL | || x += 5; | ^^^^^^^^^^ error: statement with no effect - --> $DIR/no_effect.rs:123:5 + --> $DIR/no_effect.rs:124:5 | LL | FooString { s: s }; | ^^^^^^^^^^^^^^^^^^^ error: binding to `_` prefixed variable with no side-effect - --> $DIR/no_effect.rs:124:5 + --> $DIR/no_effect.rs:125:5 | LL | let _unused = 1; | ^^^^^^^^^^^^^^^^ @@ -159,19 +159,19 @@ LL | let _unused = 1; = note: `-D clippy::no-effect-underscore-binding` implied by `-D warnings` error: binding to `_` prefixed variable with no side-effect - --> $DIR/no_effect.rs:125:5 + --> $DIR/no_effect.rs:126:5 | LL | let _penguin = || println!("Some helpful closure"); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: binding to `_` prefixed variable with no side-effect - --> $DIR/no_effect.rs:126:5 + --> $DIR/no_effect.rs:127:5 | LL | let _duck = Struct { field: 0 }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: binding to `_` prefixed variable with no side-effect - --> $DIR/no_effect.rs:127:5 + --> $DIR/no_effect.rs:128:5 | LL | let _cat = [2, 4, 6, 8][2]; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/nonminimal_bool.rs b/tests/ui/nonminimal_bool.rs index fec6b7713ee..73e056c722e 100644 --- a/tests/ui/nonminimal_bool.rs +++ b/tests/ui/nonminimal_bool.rs @@ -1,6 +1,7 @@ #![feature(lint_reasons)] #![allow(unused, clippy::diverging_sub_expression)] #![warn(clippy::nonminimal_bool)] +#![allow(clippy::useless_vec)] fn main() { let a: bool = unimplemented!(); diff --git a/tests/ui/nonminimal_bool.stderr b/tests/ui/nonminimal_bool.stderr index 91b5805aa97..e2e4d6477c9 100644 --- a/tests/ui/nonminimal_bool.stderr +++ b/tests/ui/nonminimal_bool.stderr @@ -1,5 +1,5 @@ error: this boolean expression can be simplified - --> $DIR/nonminimal_bool.rs:11:13 + --> $DIR/nonminimal_bool.rs:12:13 | LL | let _ = !true; | ^^^^^ help: try: `false` @@ -7,43 +7,43 @@ LL | let _ = !true; = note: `-D clippy::nonminimal-bool` implied by `-D warnings` error: this boolean expression can be simplified - --> $DIR/nonminimal_bool.rs:12:13 + --> $DIR/nonminimal_bool.rs:13:13 | LL | let _ = !false; | ^^^^^^ help: try: `true` error: this boolean expression can be simplified - --> $DIR/nonminimal_bool.rs:13:13 + --> $DIR/nonminimal_bool.rs:14:13 | LL | let _ = !!a; | ^^^ help: try: `a` error: this boolean expression can be simplified - --> $DIR/nonminimal_bool.rs:14:13 + --> $DIR/nonminimal_bool.rs:15:13 | LL | let _ = false || a; | ^^^^^^^^^^ help: try: `a` error: this boolean expression can be simplified - --> $DIR/nonminimal_bool.rs:18:13 + --> $DIR/nonminimal_bool.rs:19:13 | LL | let _ = !(!a && b); | ^^^^^^^^^^ help: try: `a || !b` error: this boolean expression can be simplified - --> $DIR/nonminimal_bool.rs:19:13 + --> $DIR/nonminimal_bool.rs:20:13 | LL | let _ = !(!a || b); | ^^^^^^^^^^ help: try: `a && !b` error: this boolean expression can be simplified - --> $DIR/nonminimal_bool.rs:20:13 + --> $DIR/nonminimal_bool.rs:21:13 | LL | let _ = !a && !(b && c); | ^^^^^^^^^^^^^^^ help: try: `!(a || b && c)` error: this boolean expression can be simplified - --> $DIR/nonminimal_bool.rs:28:13 + --> $DIR/nonminimal_bool.rs:29:13 | LL | let _ = a == b && c == 5 && a == b; | ^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -56,7 +56,7 @@ LL | let _ = a == b && c == 5; | ~~~~~~~~~~~~~~~~ error: this boolean expression can be simplified - --> $DIR/nonminimal_bool.rs:29:13 + --> $DIR/nonminimal_bool.rs:30:13 | LL | let _ = a == b || c == 5 || a == b; | ^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -69,7 +69,7 @@ LL | let _ = a == b || c == 5; | ~~~~~~~~~~~~~~~~ error: this boolean expression can be simplified - --> $DIR/nonminimal_bool.rs:30:13 + --> $DIR/nonminimal_bool.rs:31:13 | LL | let _ = a == b && c == 5 && b == a; | ^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -82,7 +82,7 @@ LL | let _ = a == b && c == 5; | ~~~~~~~~~~~~~~~~ error: this boolean expression can be simplified - --> $DIR/nonminimal_bool.rs:31:13 + --> $DIR/nonminimal_bool.rs:32:13 | LL | let _ = a != b || !(a != b || c == d); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -95,7 +95,7 @@ LL | let _ = a != b || c != d; | ~~~~~~~~~~~~~~~~ error: this boolean expression can be simplified - --> $DIR/nonminimal_bool.rs:32:13 + --> $DIR/nonminimal_bool.rs:33:13 | LL | let _ = a != b && !(a != b && c == d); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -108,7 +108,7 @@ LL | let _ = a != b && c != d; | ~~~~~~~~~~~~~~~~ error: this boolean expression can be simplified - --> $DIR/nonminimal_bool.rs:62:8 + --> $DIR/nonminimal_bool.rs:63:8 | LL | if matches!(true, true) && true { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `matches!(true, true)` diff --git a/tests/ui/option_as_ref_deref.fixed b/tests/ui/option_as_ref_deref.fixed index e1c0fa3f7fd..4d1a6a1ab98 100644 --- a/tests/ui/option_as_ref_deref.fixed +++ b/tests/ui/option_as_ref_deref.fixed @@ -1,6 +1,6 @@ //@run-rustfix -#![allow(unused, clippy::redundant_clone)] +#![allow(unused, clippy::redundant_clone, clippy::useless_vec)] #![warn(clippy::option_as_ref_deref)] use std::ffi::{CString, OsString}; diff --git a/tests/ui/option_as_ref_deref.rs b/tests/ui/option_as_ref_deref.rs index 6f4917fd149..66d5a125036 100644 --- a/tests/ui/option_as_ref_deref.rs +++ b/tests/ui/option_as_ref_deref.rs @@ -1,6 +1,6 @@ //@run-rustfix -#![allow(unused, clippy::redundant_clone)] +#![allow(unused, clippy::redundant_clone, clippy::useless_vec)] #![warn(clippy::option_as_ref_deref)] use std::ffi::{CString, OsString}; diff --git a/tests/ui/or_fun_call.fixed b/tests/ui/or_fun_call.fixed index f723a55f77f..08a536a2844 100644 --- a/tests/ui/or_fun_call.fixed +++ b/tests/ui/or_fun_call.fixed @@ -1,7 +1,12 @@ //@run-rustfix #![warn(clippy::or_fun_call)] #![allow(dead_code)] -#![allow(clippy::borrow_as_ptr, clippy::uninlined_format_args, clippy::unnecessary_wraps)] +#![allow( + clippy::borrow_as_ptr, + clippy::uninlined_format_args, + clippy::unnecessary_wraps, + clippy::useless_vec +)] use std::collections::BTreeMap; use std::collections::HashMap; diff --git a/tests/ui/or_fun_call.rs b/tests/ui/or_fun_call.rs index 61ef6e27f32..83ba68382ef 100644 --- a/tests/ui/or_fun_call.rs +++ b/tests/ui/or_fun_call.rs @@ -1,7 +1,12 @@ //@run-rustfix #![warn(clippy::or_fun_call)] #![allow(dead_code)] -#![allow(clippy::borrow_as_ptr, clippy::uninlined_format_args, clippy::unnecessary_wraps)] +#![allow( + clippy::borrow_as_ptr, + clippy::uninlined_format_args, + clippy::unnecessary_wraps, + clippy::useless_vec +)] use std::collections::BTreeMap; use std::collections::HashMap; diff --git a/tests/ui/or_fun_call.stderr b/tests/ui/or_fun_call.stderr index ba3001db7a5..ec87674b100 100644 --- a/tests/ui/or_fun_call.stderr +++ b/tests/ui/or_fun_call.stderr @@ -1,5 +1,5 @@ error: use of `unwrap_or` followed by a function call - --> $DIR/or_fun_call.rs:48:22 + --> $DIR/or_fun_call.rs:53:22 | LL | with_constructor.unwrap_or(make()); | ^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_else(make)` @@ -7,163 +7,163 @@ LL | with_constructor.unwrap_or(make()); = note: `-D clippy::or-fun-call` implied by `-D warnings` error: use of `unwrap_or` followed by a call to `new` - --> $DIR/or_fun_call.rs:51:14 + --> $DIR/or_fun_call.rs:56:14 | LL | with_new.unwrap_or(Vec::new()); | ^^^^^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_default()` error: use of `unwrap_or` followed by a function call - --> $DIR/or_fun_call.rs:54:21 + --> $DIR/or_fun_call.rs:59:21 | LL | with_const_args.unwrap_or(Vec::with_capacity(12)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_else(|| Vec::with_capacity(12))` error: use of `unwrap_or` followed by a function call - --> $DIR/or_fun_call.rs:57:14 + --> $DIR/or_fun_call.rs:62:14 | LL | with_err.unwrap_or(make()); | ^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_else(|_| make())` error: use of `unwrap_or` followed by a function call - --> $DIR/or_fun_call.rs:60:19 + --> $DIR/or_fun_call.rs:65:19 | LL | with_err_args.unwrap_or(Vec::with_capacity(12)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_else(|_| Vec::with_capacity(12))` error: use of `unwrap_or` followed by a call to `default` - --> $DIR/or_fun_call.rs:63:24 + --> $DIR/or_fun_call.rs:68:24 | LL | with_default_trait.unwrap_or(Default::default()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_default()` error: use of `unwrap_or` followed by a call to `default` - --> $DIR/or_fun_call.rs:66:23 + --> $DIR/or_fun_call.rs:71:23 | LL | with_default_type.unwrap_or(u64::default()); | ^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_default()` error: use of `unwrap_or` followed by a function call - --> $DIR/or_fun_call.rs:69:18 + --> $DIR/or_fun_call.rs:74:18 | LL | self_default.unwrap_or(::default()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_else(::default)` error: use of `unwrap_or` followed by a call to `default` - --> $DIR/or_fun_call.rs:72:18 + --> $DIR/or_fun_call.rs:77:18 | LL | real_default.unwrap_or(::default()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_default()` error: use of `unwrap_or` followed by a call to `new` - --> $DIR/or_fun_call.rs:75:14 + --> $DIR/or_fun_call.rs:80:14 | LL | with_vec.unwrap_or(vec![]); | ^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_default()` error: use of `unwrap_or` followed by a function call - --> $DIR/or_fun_call.rs:78:21 + --> $DIR/or_fun_call.rs:83:21 | LL | without_default.unwrap_or(Foo::new()); | ^^^^^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_else(Foo::new)` error: use of `or_insert` followed by a call to `new` - --> $DIR/or_fun_call.rs:81:19 + --> $DIR/or_fun_call.rs:86:19 | LL | map.entry(42).or_insert(String::new()); | ^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `or_default()` error: use of `or_insert` followed by a call to `new` - --> $DIR/or_fun_call.rs:84:23 + --> $DIR/or_fun_call.rs:89:23 | LL | map_vec.entry(42).or_insert(vec![]); | ^^^^^^^^^^^^^^^^^ help: try this: `or_default()` error: use of `or_insert` followed by a call to `new` - --> $DIR/or_fun_call.rs:87:21 + --> $DIR/or_fun_call.rs:92:21 | LL | btree.entry(42).or_insert(String::new()); | ^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `or_default()` error: use of `or_insert` followed by a call to `new` - --> $DIR/or_fun_call.rs:90:25 + --> $DIR/or_fun_call.rs:95:25 | LL | btree_vec.entry(42).or_insert(vec![]); | ^^^^^^^^^^^^^^^^^ help: try this: `or_default()` error: use of `unwrap_or` followed by a call to `new` - --> $DIR/or_fun_call.rs:93:21 + --> $DIR/or_fun_call.rs:98:21 | LL | let _ = stringy.unwrap_or(String::new()); | ^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_default()` error: use of `unwrap_or` followed by a function call - --> $DIR/or_fun_call.rs:101:21 + --> $DIR/or_fun_call.rs:106:21 | LL | let _ = Some(1).unwrap_or(map[&1]); | ^^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_else(|| map[&1])` error: use of `unwrap_or` followed by a function call - --> $DIR/or_fun_call.rs:103:21 + --> $DIR/or_fun_call.rs:108:21 | LL | let _ = Some(1).unwrap_or(map[&1]); | ^^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_else(|| map[&1])` error: use of `or` followed by a function call - --> $DIR/or_fun_call.rs:127:35 + --> $DIR/or_fun_call.rs:132:35 | LL | let _ = Some("a".to_string()).or(Some("b".to_string())); | ^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `or_else(|| Some("b".to_string()))` error: use of `unwrap_or` followed by a function call - --> $DIR/or_fun_call.rs:166:14 + --> $DIR/or_fun_call.rs:171:14 | LL | None.unwrap_or(ptr_to_ref(s)); | ^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_else(|| ptr_to_ref(s))` error: use of `unwrap_or` followed by a function call - --> $DIR/or_fun_call.rs:172:14 + --> $DIR/or_fun_call.rs:177:14 | LL | None.unwrap_or(unsafe { ptr_to_ref(s) }); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_else(|| unsafe { ptr_to_ref(s) })` error: use of `unwrap_or` followed by a function call - --> $DIR/or_fun_call.rs:174:14 + --> $DIR/or_fun_call.rs:179:14 | LL | None.unwrap_or( unsafe { ptr_to_ref(s) } ); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_else(|| unsafe { ptr_to_ref(s) })` error: use of `unwrap_or` followed by a call to `new` - --> $DIR/or_fun_call.rs:188:14 + --> $DIR/or_fun_call.rs:193:14 | LL | .unwrap_or(String::new()); | ^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_default()` error: use of `unwrap_or` followed by a call to `new` - --> $DIR/or_fun_call.rs:201:14 + --> $DIR/or_fun_call.rs:206:14 | LL | .unwrap_or(String::new()); | ^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_default()` error: use of `unwrap_or` followed by a call to `new` - --> $DIR/or_fun_call.rs:213:14 + --> $DIR/or_fun_call.rs:218:14 | LL | .unwrap_or(String::new()); | ^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_default()` error: use of `unwrap_or` followed by a call to `new` - --> $DIR/or_fun_call.rs:224:10 + --> $DIR/or_fun_call.rs:229:10 | LL | .unwrap_or(String::new()); | ^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_default()` error: use of `map_or` followed by a function call - --> $DIR/or_fun_call.rs:249:25 + --> $DIR/or_fun_call.rs:254:25 | LL | let _ = Some(4).map_or(g(), |v| v); | ^^^^^^^^^^^^^^^^^^ help: try this: `map_or_else(g, |v| v)` error: use of `map_or` followed by a function call - --> $DIR/or_fun_call.rs:250:25 + --> $DIR/or_fun_call.rs:255:25 | LL | let _ = Some(4).map_or(g(), f); | ^^^^^^^^^^^^^^ help: try this: `map_or_else(g, f)` diff --git a/tests/ui/ptr_offset_with_cast.fixed b/tests/ui/ptr_offset_with_cast.fixed index f69bc131898..6ffa401d761 100644 --- a/tests/ui/ptr_offset_with_cast.fixed +++ b/tests/ui/ptr_offset_with_cast.fixed @@ -1,5 +1,5 @@ //@run-rustfix -#![allow(clippy::unnecessary_cast)] +#![allow(clippy::unnecessary_cast, clippy::useless_vec)] fn main() { let vec = vec![b'a', b'b', b'c']; diff --git a/tests/ui/ptr_offset_with_cast.rs b/tests/ui/ptr_offset_with_cast.rs index eae36c27729..de1f86cb855 100644 --- a/tests/ui/ptr_offset_with_cast.rs +++ b/tests/ui/ptr_offset_with_cast.rs @@ -1,5 +1,5 @@ //@run-rustfix -#![allow(clippy::unnecessary_cast)] +#![allow(clippy::unnecessary_cast, clippy::useless_vec)] fn main() { let vec = vec![b'a', b'b', b'c']; diff --git a/tests/ui/range.rs b/tests/ui/range.rs index 628282509c1..46edf0921bf 100644 --- a/tests/ui/range.rs +++ b/tests/ui/range.rs @@ -1,3 +1,4 @@ +#![allow(clippy::useless_vec)] #[warn(clippy::range_zip_with_len)] fn main() { let v1 = vec![1, 2, 3]; diff --git a/tests/ui/range.stderr b/tests/ui/range.stderr index dcb5061371f..ac83b67fde3 100644 --- a/tests/ui/range.stderr +++ b/tests/ui/range.stderr @@ -1,5 +1,5 @@ error: it is more idiomatic to use `v1.iter().enumerate()` - --> $DIR/range.rs:5:14 + --> $DIR/range.rs:6:14 | LL | let _x = v1.iter().zip(0..v1.len()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/rc_clone_in_vec_init/arc.rs b/tests/ui/rc_clone_in_vec_init/arc.rs index 384060e6eae..53fcbf3c49b 100644 --- a/tests/ui/rc_clone_in_vec_init/arc.rs +++ b/tests/ui/rc_clone_in_vec_init/arc.rs @@ -1,4 +1,5 @@ #![warn(clippy::rc_clone_in_vec_init)] +#![allow(clippy::useless_vec)] use std::sync::{Arc, Mutex}; fn main() {} diff --git a/tests/ui/rc_clone_in_vec_init/arc.stderr b/tests/ui/rc_clone_in_vec_init/arc.stderr index 7814f5b5403..a8fd28b84b3 100644 --- a/tests/ui/rc_clone_in_vec_init/arc.stderr +++ b/tests/ui/rc_clone_in_vec_init/arc.stderr @@ -1,5 +1,5 @@ error: initializing a reference-counted pointer in `vec![elem; len]` - --> $DIR/arc.rs:7:13 + --> $DIR/arc.rs:8:13 | LL | let v = vec![Arc::new("x".to_string()); 2]; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -23,7 +23,7 @@ LL ~ }; | error: initializing a reference-counted pointer in `vec![elem; len]` - --> $DIR/arc.rs:15:21 + --> $DIR/arc.rs:16:21 | LL | let v = vec![Arc::new("x".to_string()); 2]; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -46,7 +46,7 @@ LL ~ }; | error: initializing a reference-counted pointer in `vec![elem; len]` - --> $DIR/arc.rs:21:13 + --> $DIR/arc.rs:22:13 | LL | let v = vec![ | _____________^ @@ -76,7 +76,7 @@ LL ~ }; | error: initializing a reference-counted pointer in `vec![elem; len]` - --> $DIR/arc.rs:30:14 + --> $DIR/arc.rs:31:14 | LL | let v1 = vec![ | ______________^ diff --git a/tests/ui/rc_clone_in_vec_init/rc.rs b/tests/ui/rc_clone_in_vec_init/rc.rs index 0394457fe17..88ea39bf908 100644 --- a/tests/ui/rc_clone_in_vec_init/rc.rs +++ b/tests/ui/rc_clone_in_vec_init/rc.rs @@ -1,4 +1,5 @@ #![warn(clippy::rc_clone_in_vec_init)] +#![allow(clippy::useless_vec)] use std::rc::Rc; use std::sync::Mutex; diff --git a/tests/ui/rc_clone_in_vec_init/rc.stderr b/tests/ui/rc_clone_in_vec_init/rc.stderr index 80deb7cb9f2..eab464800ca 100644 --- a/tests/ui/rc_clone_in_vec_init/rc.stderr +++ b/tests/ui/rc_clone_in_vec_init/rc.stderr @@ -1,5 +1,5 @@ error: initializing a reference-counted pointer in `vec![elem; len]` - --> $DIR/rc.rs:8:13 + --> $DIR/rc.rs:9:13 | LL | let v = vec![Rc::new("x".to_string()); 2]; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -23,7 +23,7 @@ LL ~ }; | error: initializing a reference-counted pointer in `vec![elem; len]` - --> $DIR/rc.rs:16:21 + --> $DIR/rc.rs:17:21 | LL | let v = vec![Rc::new("x".to_string()); 2]; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -46,7 +46,7 @@ LL ~ }; | error: initializing a reference-counted pointer in `vec![elem; len]` - --> $DIR/rc.rs:22:13 + --> $DIR/rc.rs:23:13 | LL | let v = vec![ | _____________^ @@ -76,7 +76,7 @@ LL ~ }; | error: initializing a reference-counted pointer in `vec![elem; len]` - --> $DIR/rc.rs:31:14 + --> $DIR/rc.rs:32:14 | LL | let v1 = vec![ | ______________^ diff --git a/tests/ui/rc_clone_in_vec_init/weak.rs b/tests/ui/rc_clone_in_vec_init/weak.rs index 693c9b553c5..03142165057 100644 --- a/tests/ui/rc_clone_in_vec_init/weak.rs +++ b/tests/ui/rc_clone_in_vec_init/weak.rs @@ -1,4 +1,5 @@ #![warn(clippy::rc_clone_in_vec_init)] +#![allow(clippy::useless_vec)] use std::rc::{Rc, Weak as UnSyncWeak}; use std::sync::{Arc, Mutex, Weak as SyncWeak}; diff --git a/tests/ui/rc_clone_in_vec_init/weak.stderr b/tests/ui/rc_clone_in_vec_init/weak.stderr index 789e14a302f..1f7a849b180 100644 --- a/tests/ui/rc_clone_in_vec_init/weak.stderr +++ b/tests/ui/rc_clone_in_vec_init/weak.stderr @@ -1,5 +1,5 @@ error: initializing a reference-counted pointer in `vec![elem; len]` - --> $DIR/weak.rs:8:13 + --> $DIR/weak.rs:9:13 | LL | let v = vec![SyncWeak::::new(); 2]; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -23,7 +23,7 @@ LL ~ }; | error: initializing a reference-counted pointer in `vec![elem; len]` - --> $DIR/weak.rs:9:14 + --> $DIR/weak.rs:10:14 | LL | let v2 = vec![UnSyncWeak::::new(); 2]; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -46,7 +46,7 @@ LL ~ }; | error: initializing a reference-counted pointer in `vec![elem; len]` - --> $DIR/weak.rs:11:13 + --> $DIR/weak.rs:12:13 | LL | let v = vec![Rc::downgrade(&Rc::new("x".to_string())); 2]; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -69,7 +69,7 @@ LL ~ }; | error: initializing a reference-counted pointer in `vec![elem; len]` - --> $DIR/weak.rs:12:13 + --> $DIR/weak.rs:13:13 | LL | let v = vec![Arc::downgrade(&Arc::new("x".to_string())); 2]; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -92,7 +92,7 @@ LL ~ }; | error: initializing a reference-counted pointer in `vec![elem; len]` - --> $DIR/weak.rs:20:21 + --> $DIR/weak.rs:21:21 | LL | let v = vec![Arc::downgrade(&Arc::new("x".to_string())); 2]; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -115,7 +115,7 @@ LL ~ }; | error: initializing a reference-counted pointer in `vec![elem; len]` - --> $DIR/weak.rs:21:22 + --> $DIR/weak.rs:22:22 | LL | let v2 = vec![Rc::downgrade(&Rc::new("x".to_string())); 2]; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -138,7 +138,7 @@ LL ~ }; | error: initializing a reference-counted pointer in `vec![elem; len]` - --> $DIR/weak.rs:27:13 + --> $DIR/weak.rs:28:13 | LL | let v = vec![ | _____________^ @@ -168,7 +168,7 @@ LL ~ }; | error: initializing a reference-counted pointer in `vec![elem; len]` - --> $DIR/weak.rs:36:14 + --> $DIR/weak.rs:37:14 | LL | let v1 = vec![ | ______________^ diff --git a/tests/ui/search_is_some.rs b/tests/ui/search_is_some.rs index 670599b0dcf..3cdbfaa1626 100644 --- a/tests/ui/search_is_some.rs +++ b/tests/ui/search_is_some.rs @@ -1,5 +1,6 @@ //@aux-build:option_helpers.rs #![warn(clippy::search_is_some)] +#![allow(clippy::useless_vec)] #![allow(dead_code)] extern crate option_helpers; use option_helpers::IteratorFalsePositives; diff --git a/tests/ui/search_is_some.stderr b/tests/ui/search_is_some.stderr index 6bea8c67477..7eff614d17c 100644 --- a/tests/ui/search_is_some.stderr +++ b/tests/ui/search_is_some.stderr @@ -1,5 +1,5 @@ error: called `is_some()` after searching an `Iterator` with `find` - --> $DIR/search_is_some.rs:14:13 + --> $DIR/search_is_some.rs:15:13 | LL | let _ = v.iter().find(|&x| { | _____________^ @@ -12,7 +12,7 @@ LL | | ).is_some(); = note: `-D clippy::search-is-some` implied by `-D warnings` error: called `is_some()` after searching an `Iterator` with `position` - --> $DIR/search_is_some.rs:20:13 + --> $DIR/search_is_some.rs:21:13 | LL | let _ = v.iter().position(|&x| { | _____________^ @@ -24,7 +24,7 @@ LL | | ).is_some(); = help: this is more succinctly expressed by calling `any()` error: called `is_some()` after searching an `Iterator` with `rposition` - --> $DIR/search_is_some.rs:26:13 + --> $DIR/search_is_some.rs:27:13 | LL | let _ = v.iter().rposition(|&x| { | _____________^ @@ -36,13 +36,13 @@ LL | | ).is_some(); = help: this is more succinctly expressed by calling `any()` error: called `is_some()` after searching an `Iterator` with `find` - --> $DIR/search_is_some.rs:41:20 + --> $DIR/search_is_some.rs:42:20 | LL | let _ = (0..1).find(some_closure).is_some(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `any()` instead: `any(some_closure)` error: called `is_none()` after searching an `Iterator` with `find` - --> $DIR/search_is_some.rs:51:13 + --> $DIR/search_is_some.rs:52:13 | LL | let _ = v.iter().find(|&x| { | _____________^ @@ -54,7 +54,7 @@ LL | | ).is_none(); = help: this is more succinctly expressed by calling `any()` with negation error: called `is_none()` after searching an `Iterator` with `position` - --> $DIR/search_is_some.rs:57:13 + --> $DIR/search_is_some.rs:58:13 | LL | let _ = v.iter().position(|&x| { | _____________^ @@ -66,7 +66,7 @@ LL | | ).is_none(); = help: this is more succinctly expressed by calling `any()` with negation error: called `is_none()` after searching an `Iterator` with `rposition` - --> $DIR/search_is_some.rs:63:13 + --> $DIR/search_is_some.rs:64:13 | LL | let _ = v.iter().rposition(|&x| { | _____________^ @@ -78,7 +78,7 @@ LL | | ).is_none(); = help: this is more succinctly expressed by calling `any()` with negation error: called `is_none()` after searching an `Iterator` with `find` - --> $DIR/search_is_some.rs:78:13 + --> $DIR/search_is_some.rs:79:13 | LL | let _ = (0..1).find(some_closure).is_none(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `!_.any()` instead: `!(0..1).any(some_closure)` diff --git a/tests/ui/search_is_some_fixable_none.fixed b/tests/ui/search_is_some_fixable_none.fixed index 9386618c123..08fb87cb306 100644 --- a/tests/ui/search_is_some_fixable_none.fixed +++ b/tests/ui/search_is_some_fixable_none.fixed @@ -1,5 +1,5 @@ //@run-rustfix -#![allow(dead_code, clippy::explicit_auto_deref)] +#![allow(dead_code, clippy::explicit_auto_deref, clippy::useless_vec)] #![warn(clippy::search_is_some)] fn main() { diff --git a/tests/ui/search_is_some_fixable_none.rs b/tests/ui/search_is_some_fixable_none.rs index 6b2537a96c2..ec3386933a6 100644 --- a/tests/ui/search_is_some_fixable_none.rs +++ b/tests/ui/search_is_some_fixable_none.rs @@ -1,5 +1,5 @@ //@run-rustfix -#![allow(dead_code, clippy::explicit_auto_deref)] +#![allow(dead_code, clippy::explicit_auto_deref, clippy::useless_vec)] #![warn(clippy::search_is_some)] fn main() { diff --git a/tests/ui/search_is_some_fixable_some.fixed b/tests/ui/search_is_some_fixable_some.fixed index e9116fc59f1..aa16f9da037 100644 --- a/tests/ui/search_is_some_fixable_some.fixed +++ b/tests/ui/search_is_some_fixable_some.fixed @@ -1,5 +1,5 @@ //@run-rustfix -#![allow(dead_code, clippy::explicit_auto_deref)] +#![allow(dead_code, clippy::explicit_auto_deref, clippy::useless_vec)] #![warn(clippy::search_is_some)] fn main() { diff --git a/tests/ui/search_is_some_fixable_some.rs b/tests/ui/search_is_some_fixable_some.rs index b1528399457..aeb6f118bed 100644 --- a/tests/ui/search_is_some_fixable_some.rs +++ b/tests/ui/search_is_some_fixable_some.rs @@ -1,5 +1,5 @@ //@run-rustfix -#![allow(dead_code, clippy::explicit_auto_deref)] +#![allow(dead_code, clippy::explicit_auto_deref, clippy::useless_vec)] #![warn(clippy::search_is_some)] fn main() { diff --git a/tests/ui/self_assignment.rs b/tests/ui/self_assignment.rs index ef647622910..ec3ae120942 100644 --- a/tests/ui/self_assignment.rs +++ b/tests/ui/self_assignment.rs @@ -1,4 +1,5 @@ #![warn(clippy::self_assignment)] +#![allow(clippy::useless_vec)] pub struct S<'a> { a: i32, diff --git a/tests/ui/self_assignment.stderr b/tests/ui/self_assignment.stderr index 826e0d0ba88..bed88244eea 100644 --- a/tests/ui/self_assignment.stderr +++ b/tests/ui/self_assignment.stderr @@ -1,5 +1,5 @@ error: self-assignment of `a` to `a` - --> $DIR/self_assignment.rs:12:5 + --> $DIR/self_assignment.rs:13:5 | LL | a = a; | ^^^^^ @@ -7,61 +7,61 @@ LL | a = a; = note: `-D clippy::self-assignment` implied by `-D warnings` error: self-assignment of `*b` to `*b` - --> $DIR/self_assignment.rs:13:5 + --> $DIR/self_assignment.rs:14:5 | LL | *b = *b; | ^^^^^^^ error: self-assignment of `s` to `s` - --> $DIR/self_assignment.rs:14:5 + --> $DIR/self_assignment.rs:15:5 | LL | s = s; | ^^^^^ error: self-assignment of `s.a` to `s.a` - --> $DIR/self_assignment.rs:15:5 + --> $DIR/self_assignment.rs:16:5 | LL | s.a = s.a; | ^^^^^^^^^ error: self-assignment of `s.b[5 + 5]` to `s.b[10]` - --> $DIR/self_assignment.rs:16:5 + --> $DIR/self_assignment.rs:17:5 | LL | s.b[10] = s.b[5 + 5]; | ^^^^^^^^^^^^^^^^^^^^ error: self-assignment of `s.c[0][1]` to `s.c[0][1]` - --> $DIR/self_assignment.rs:17:5 + --> $DIR/self_assignment.rs:18:5 | LL | s.c[0][1] = s.c[0][1]; | ^^^^^^^^^^^^^^^^^^^^^ error: self-assignment of `s.b[a]` to `s.b[a]` - --> $DIR/self_assignment.rs:18:5 + --> $DIR/self_assignment.rs:19:5 | LL | s.b[a] = s.b[a]; | ^^^^^^^^^^^^^^^ error: self-assignment of `*s.e` to `*s.e` - --> $DIR/self_assignment.rs:19:5 + --> $DIR/self_assignment.rs:20:5 | LL | *s.e = *s.e; | ^^^^^^^^^^^ error: self-assignment of `s.b[10 + a]` to `s.b[a + 10]` - --> $DIR/self_assignment.rs:20:5 + --> $DIR/self_assignment.rs:21:5 | LL | s.b[a + 10] = s.b[10 + a]; | ^^^^^^^^^^^^^^^^^^^^^^^^^ error: self-assignment of `t.1` to `t.1` - --> $DIR/self_assignment.rs:23:5 + --> $DIR/self_assignment.rs:24:5 | LL | t.1 = t.1; | ^^^^^^^^^ error: self-assignment of `(t.0)` to `t.0` - --> $DIR/self_assignment.rs:24:5 + --> $DIR/self_assignment.rs:25:5 | LL | t.0 = (t.0); | ^^^^^^^^^^^ diff --git a/tests/ui/skip_while_next.rs b/tests/ui/skip_while_next.rs index 62574e2c8ce..8e4cd82cec3 100644 --- a/tests/ui/skip_while_next.rs +++ b/tests/ui/skip_while_next.rs @@ -1,7 +1,7 @@ //@aux-build:option_helpers.rs #![warn(clippy::skip_while_next)] -#![allow(clippy::disallowed_names)] +#![allow(clippy::disallowed_names, clippy::useless_vec)] extern crate option_helpers; use option_helpers::IteratorFalsePositives; diff --git a/tests/ui/stable_sort_primitive.fixed b/tests/ui/stable_sort_primitive.fixed index 1370dd2df4d..50c1fc71a3f 100644 --- a/tests/ui/stable_sort_primitive.fixed +++ b/tests/ui/stable_sort_primitive.fixed @@ -1,5 +1,6 @@ //@run-rustfix #![warn(clippy::stable_sort_primitive)] +#![allow(clippy::useless_vec)] fn main() { // positive examples diff --git a/tests/ui/stable_sort_primitive.rs b/tests/ui/stable_sort_primitive.rs index cd344dd1238..bd1bb428f2b 100644 --- a/tests/ui/stable_sort_primitive.rs +++ b/tests/ui/stable_sort_primitive.rs @@ -1,5 +1,6 @@ //@run-rustfix #![warn(clippy::stable_sort_primitive)] +#![allow(clippy::useless_vec)] fn main() { // positive examples diff --git a/tests/ui/stable_sort_primitive.stderr b/tests/ui/stable_sort_primitive.stderr index 1432fdcff77..aa5d7b7e491 100644 --- a/tests/ui/stable_sort_primitive.stderr +++ b/tests/ui/stable_sort_primitive.stderr @@ -1,5 +1,5 @@ error: used `sort` on primitive type `i32` - --> $DIR/stable_sort_primitive.rs:7:5 + --> $DIR/stable_sort_primitive.rs:8:5 | LL | vec.sort(); | ^^^^^^^^^^ help: try: `vec.sort_unstable()` @@ -8,7 +8,7 @@ LL | vec.sort(); = note: `-D clippy::stable-sort-primitive` implied by `-D warnings` error: used `sort` on primitive type `bool` - --> $DIR/stable_sort_primitive.rs:9:5 + --> $DIR/stable_sort_primitive.rs:10:5 | LL | vec.sort(); | ^^^^^^^^^^ help: try: `vec.sort_unstable()` @@ -16,7 +16,7 @@ LL | vec.sort(); = note: an unstable sort typically performs faster without any observable difference for this data type error: used `sort` on primitive type `char` - --> $DIR/stable_sort_primitive.rs:11:5 + --> $DIR/stable_sort_primitive.rs:12:5 | LL | vec.sort(); | ^^^^^^^^^^ help: try: `vec.sort_unstable()` @@ -24,7 +24,7 @@ LL | vec.sort(); = note: an unstable sort typically performs faster without any observable difference for this data type error: used `sort` on primitive type `str` - --> $DIR/stable_sort_primitive.rs:13:5 + --> $DIR/stable_sort_primitive.rs:14:5 | LL | vec.sort(); | ^^^^^^^^^^ help: try: `vec.sort_unstable()` @@ -32,7 +32,7 @@ LL | vec.sort(); = note: an unstable sort typically performs faster without any observable difference for this data type error: used `sort` on primitive type `tuple` - --> $DIR/stable_sort_primitive.rs:15:5 + --> $DIR/stable_sort_primitive.rs:16:5 | LL | vec.sort(); | ^^^^^^^^^^ help: try: `vec.sort_unstable()` @@ -40,7 +40,7 @@ LL | vec.sort(); = note: an unstable sort typically performs faster without any observable difference for this data type error: used `sort` on primitive type `array` - --> $DIR/stable_sort_primitive.rs:17:5 + --> $DIR/stable_sort_primitive.rs:18:5 | LL | vec.sort(); | ^^^^^^^^^^ help: try: `vec.sort_unstable()` @@ -48,7 +48,7 @@ LL | vec.sort(); = note: an unstable sort typically performs faster without any observable difference for this data type error: used `sort` on primitive type `i32` - --> $DIR/stable_sort_primitive.rs:19:5 + --> $DIR/stable_sort_primitive.rs:20:5 | LL | arr.sort(); | ^^^^^^^^^^ help: try: `arr.sort_unstable()` diff --git a/tests/ui/swap.fixed b/tests/ui/swap.fixed index fd3569cf362..22f904e3fd9 100644 --- a/tests/ui/swap.fixed +++ b/tests/ui/swap.fixed @@ -10,7 +10,8 @@ dead_code, unused_assignments, unused_variables, - clippy::let_and_return + clippy::let_and_return, + clippy::useless_vec )] struct Foo(u32); diff --git a/tests/ui/swap.rs b/tests/ui/swap.rs index 34fbce0524b..ada64f89e6d 100644 --- a/tests/ui/swap.rs +++ b/tests/ui/swap.rs @@ -10,7 +10,8 @@ dead_code, unused_assignments, unused_variables, - clippy::let_and_return + clippy::let_and_return, + clippy::useless_vec )] struct Foo(u32); diff --git a/tests/ui/swap.stderr b/tests/ui/swap.stderr index 0c246268499..a3b9c2b744c 100644 --- a/tests/ui/swap.stderr +++ b/tests/ui/swap.stderr @@ -1,5 +1,5 @@ error: this looks like you are swapping `bar.a` and `bar.b` manually - --> $DIR/swap.rs:27:5 + --> $DIR/swap.rs:28:5 | LL | / let temp = bar.a; LL | | bar.a = bar.b; @@ -10,7 +10,7 @@ LL | | bar.b = temp; = note: `-D clippy::manual-swap` implied by `-D warnings` error: this looks like you are swapping elements of `foo` manually - --> $DIR/swap.rs:39:5 + --> $DIR/swap.rs:40:5 | LL | / let temp = foo[0]; LL | | foo[0] = foo[1]; @@ -18,7 +18,7 @@ LL | | foo[1] = temp; | |__________________^ help: try: `foo.swap(0, 1);` error: this looks like you are swapping elements of `foo` manually - --> $DIR/swap.rs:48:5 + --> $DIR/swap.rs:49:5 | LL | / let temp = foo[0]; LL | | foo[0] = foo[1]; @@ -26,7 +26,7 @@ LL | | foo[1] = temp; | |__________________^ help: try: `foo.swap(0, 1);` error: this looks like you are swapping elements of `foo` manually - --> $DIR/swap.rs:67:5 + --> $DIR/swap.rs:68:5 | LL | / let temp = foo[0]; LL | | foo[0] = foo[1]; @@ -34,7 +34,7 @@ LL | | foo[1] = temp; | |__________________^ help: try: `foo.swap(0, 1);` error: this looks like you are swapping `a` and `b` manually - --> $DIR/swap.rs:78:5 + --> $DIR/swap.rs:79:5 | LL | / a ^= b; LL | | b ^= a; @@ -42,7 +42,7 @@ LL | | a ^= b; | |___________^ help: try: `std::mem::swap(&mut a, &mut b);` error: this looks like you are swapping `bar.a` and `bar.b` manually - --> $DIR/swap.rs:86:5 + --> $DIR/swap.rs:87:5 | LL | / bar.a ^= bar.b; LL | | bar.b ^= bar.a; @@ -50,7 +50,7 @@ LL | | bar.a ^= bar.b; | |___________________^ help: try: `std::mem::swap(&mut bar.a, &mut bar.b);` error: this looks like you are swapping elements of `foo` manually - --> $DIR/swap.rs:94:5 + --> $DIR/swap.rs:95:5 | LL | / foo[0] ^= foo[1]; LL | | foo[1] ^= foo[0]; @@ -58,7 +58,7 @@ LL | | foo[0] ^= foo[1]; | |_____________________^ help: try: `foo.swap(0, 1);` error: this looks like you are swapping `foo[0][1]` and `bar[1][0]` manually - --> $DIR/swap.rs:123:5 + --> $DIR/swap.rs:124:5 | LL | / let temp = foo[0][1]; LL | | foo[0][1] = bar[1][0]; @@ -68,7 +68,7 @@ LL | | bar[1][0] = temp; = note: or maybe you should use `std::mem::replace`? error: this looks like you are swapping `a` and `b` manually - --> $DIR/swap.rs:137:7 + --> $DIR/swap.rs:138:7 | LL | ; let t = a; | _______^ @@ -79,7 +79,7 @@ LL | | b = t; = note: or maybe you should use `std::mem::replace`? error: this looks like you are swapping `c.0` and `a` manually - --> $DIR/swap.rs:146:7 + --> $DIR/swap.rs:147:7 | LL | ; let t = c.0; | _______^ @@ -90,7 +90,7 @@ LL | | a = t; = note: or maybe you should use `std::mem::replace`? error: this looks like you are swapping `b` and `a` manually - --> $DIR/swap.rs:172:5 + --> $DIR/swap.rs:173:5 | LL | / let t = b; LL | | b = a; @@ -100,7 +100,7 @@ LL | | a = t; = note: or maybe you should use `std::mem::replace`? error: this looks like you are trying to swap `a` and `b` - --> $DIR/swap.rs:134:5 + --> $DIR/swap.rs:135:5 | LL | / a = b; LL | | b = a; @@ -110,7 +110,7 @@ LL | | b = a; = note: `-D clippy::almost-swapped` implied by `-D warnings` error: this looks like you are trying to swap `c.0` and `a` - --> $DIR/swap.rs:143:5 + --> $DIR/swap.rs:144:5 | LL | / c.0 = a; LL | | a = c.0; @@ -119,7 +119,7 @@ LL | | a = c.0; = note: or maybe you should use `std::mem::replace`? error: this looks like you are trying to swap `a` and `b` - --> $DIR/swap.rs:150:5 + --> $DIR/swap.rs:151:5 | LL | / let a = b; LL | | let b = a; @@ -128,7 +128,7 @@ LL | | let b = a; = note: or maybe you should use `std::mem::replace`? error: this looks like you are trying to swap `d` and `c` - --> $DIR/swap.rs:155:5 + --> $DIR/swap.rs:156:5 | LL | / d = c; LL | | c = d; @@ -137,7 +137,7 @@ LL | | c = d; = note: or maybe you should use `std::mem::replace`? error: this looks like you are trying to swap `a` and `b` - --> $DIR/swap.rs:159:5 + --> $DIR/swap.rs:160:5 | LL | / let a = b; LL | | b = a; @@ -146,7 +146,7 @@ LL | | b = a; = note: or maybe you should use `std::mem::replace`? error: this looks like you are swapping `s.0.x` and `s.0.y` manually - --> $DIR/swap.rs:207:5 + --> $DIR/swap.rs:208:5 | LL | / let t = s.0.x; LL | | s.0.x = s.0.y; diff --git a/tests/ui/toplevel_ref_arg.fixed b/tests/ui/toplevel_ref_arg.fixed index ea30c1fda6f..4bacf9efdae 100644 --- a/tests/ui/toplevel_ref_arg.fixed +++ b/tests/ui/toplevel_ref_arg.fixed @@ -1,7 +1,7 @@ //@run-rustfix //@aux-build:proc_macros.rs #![warn(clippy::toplevel_ref_arg)] -#![allow(clippy::uninlined_format_args, unused)] +#![allow(clippy::uninlined_format_args, unused, clippy::useless_vec)] extern crate proc_macros; use proc_macros::{external, inline_macros}; diff --git a/tests/ui/toplevel_ref_arg.rs b/tests/ui/toplevel_ref_arg.rs index 7a3d33e5be5..723870ccc80 100644 --- a/tests/ui/toplevel_ref_arg.rs +++ b/tests/ui/toplevel_ref_arg.rs @@ -1,7 +1,7 @@ //@run-rustfix //@aux-build:proc_macros.rs #![warn(clippy::toplevel_ref_arg)] -#![allow(clippy::uninlined_format_args, unused)] +#![allow(clippy::uninlined_format_args, unused, clippy::useless_vec)] extern crate proc_macros; use proc_macros::{external, inline_macros}; diff --git a/tests/ui/type_complexity.rs b/tests/ui/type_complexity.rs index 86a7bd7b627..816950110b2 100644 --- a/tests/ui/type_complexity.rs +++ b/tests/ui/type_complexity.rs @@ -1,5 +1,5 @@ #![warn(clippy::all)] -#![allow(unused, clippy::needless_pass_by_value, clippy::vec_box)] +#![allow(unused, clippy::needless_pass_by_value, clippy::vec_box, clippy::useless_vec)] #![feature(associated_type_defaults)] type Alias = Vec>>; // no warning here diff --git a/tests/ui/unit_return_expecting_ord.rs b/tests/ui/unit_return_expecting_ord.rs index bdb4710cc69..f2a9694f99e 100644 --- a/tests/ui/unit_return_expecting_ord.rs +++ b/tests/ui/unit_return_expecting_ord.rs @@ -1,6 +1,7 @@ #![warn(clippy::unit_return_expecting_ord)] #![allow(clippy::needless_return)] #![allow(clippy::unused_unit)] +#![allow(clippy::useless_vec)] #![feature(is_sorted)] struct Struct { diff --git a/tests/ui/unit_return_expecting_ord.stderr b/tests/ui/unit_return_expecting_ord.stderr index 1d9564ce225..3a295af55ea 100644 --- a/tests/ui/unit_return_expecting_ord.stderr +++ b/tests/ui/unit_return_expecting_ord.stderr @@ -1,36 +1,36 @@ error: this closure returns the unit type which also implements Ord - --> $DIR/unit_return_expecting_ord.rs:18:25 + --> $DIR/unit_return_expecting_ord.rs:19:25 | LL | structs.sort_by_key(|s| { | ^^^ | help: probably caused by this trailing semicolon - --> $DIR/unit_return_expecting_ord.rs:19:24 + --> $DIR/unit_return_expecting_ord.rs:20:24 | LL | double(s.field); | ^ = note: `-D clippy::unit-return-expecting-ord` implied by `-D warnings` error: this closure returns the unit type which also implements PartialOrd - --> $DIR/unit_return_expecting_ord.rs:22:30 + --> $DIR/unit_return_expecting_ord.rs:23:30 | LL | structs.is_sorted_by_key(|s| { | ^^^ | help: probably caused by this trailing semicolon - --> $DIR/unit_return_expecting_ord.rs:23:24 + --> $DIR/unit_return_expecting_ord.rs:24:24 | LL | double(s.field); | ^ error: this closure returns the unit type which also implements PartialOrd - --> $DIR/unit_return_expecting_ord.rs:25:30 + --> $DIR/unit_return_expecting_ord.rs:26:30 | LL | structs.is_sorted_by_key(|s| { | ^^^ error: this closure returns the unit type which also implements Ord - --> $DIR/unit_return_expecting_ord.rs:35:25 + --> $DIR/unit_return_expecting_ord.rs:36:25 | LL | structs.sort_by_key(|s| unit(s.field)); | ^^^ diff --git a/tests/ui/unnecessary_join.fixed b/tests/ui/unnecessary_join.fixed index e102df62599..f13a5275e31 100644 --- a/tests/ui/unnecessary_join.fixed +++ b/tests/ui/unnecessary_join.fixed @@ -1,6 +1,6 @@ //@run-rustfix #![warn(clippy::unnecessary_join)] -#![allow(clippy::uninlined_format_args)] +#![allow(clippy::uninlined_format_args, clippy::useless_vec)] fn main() { // should be linted diff --git a/tests/ui/unnecessary_join.rs b/tests/ui/unnecessary_join.rs index b87c15bc126..6014d723a2f 100644 --- a/tests/ui/unnecessary_join.rs +++ b/tests/ui/unnecessary_join.rs @@ -1,6 +1,6 @@ //@run-rustfix #![warn(clippy::unnecessary_join)] -#![allow(clippy::uninlined_format_args)] +#![allow(clippy::uninlined_format_args, clippy::useless_vec)] fn main() { // should be linted diff --git a/tests/ui/unnecessary_sort_by.fixed b/tests/ui/unnecessary_sort_by.fixed index 165cabd8298..19380ad00dc 100644 --- a/tests/ui/unnecessary_sort_by.fixed +++ b/tests/ui/unnecessary_sort_by.fixed @@ -1,6 +1,6 @@ //@run-rustfix -#![allow(clippy::stable_sort_primitive)] +#![allow(clippy::stable_sort_primitive, clippy::useless_vec)] use std::cell::Ref; diff --git a/tests/ui/unnecessary_sort_by.rs b/tests/ui/unnecessary_sort_by.rs index 8a2158d5a84..cea1b65b520 100644 --- a/tests/ui/unnecessary_sort_by.rs +++ b/tests/ui/unnecessary_sort_by.rs @@ -1,6 +1,6 @@ //@run-rustfix -#![allow(clippy::stable_sort_primitive)] +#![allow(clippy::stable_sort_primitive, clippy::useless_vec)] use std::cell::Ref; diff --git a/tests/ui/vec.fixed b/tests/ui/vec.fixed index d77a4dd8e0b..1bdde69f6f4 100644 --- a/tests/ui/vec.fixed +++ b/tests/ui/vec.fixed @@ -2,6 +2,12 @@ #![warn(clippy::useless_vec)] #![allow(clippy::nonstandard_macro_braces, clippy::uninlined_format_args)] +use std::rc::Rc; + +struct StructWithVec { + _x: Vec, +} + #[derive(Debug)] struct NonCopy; @@ -75,4 +81,44 @@ fn main() { for a in vec![1; 201] { println!("{:?}", a); } + + // Do lint + let mut x = [1, 2, 3]; + x.fill(123); + dbg!(x[0]); + dbg!(x.len()); + dbg!(x.iter().sum::()); + + let _x: &[i32] = &[1, 2, 3]; + + for _ in &[1, 2, 3] {} + + // Don't lint + let x = vec![1, 2, 3]; + let _v: Vec = x; + + let x = vec![1, 2, 3]; + let _s = StructWithVec { _x: x }; + + // Explicit type annotation would make the change to [1, 2, 3] + // a compile error. + let _x: Vec = vec![1, 2, 3]; + + // Calling a Vec method through a mutable reference + let mut x = vec![1, 2, 3]; + let re = &mut x; + re.push(4); + + // Comparing arrays whose length is not equal is a compile error + let x = vec![1, 2, 3]; + let y = vec![1, 2, 3, 4]; + dbg!(x == y); + + // Non-copy types + let _x = vec![String::new(); 10]; + #[allow(clippy::rc_clone_in_vec_init)] + let _x = vec![Rc::new(1); 10]; + + // Too large + let _x = vec![1; 201]; } diff --git a/tests/ui/vec.rs b/tests/ui/vec.rs index dfed3a29a03..89c6a72f339 100644 --- a/tests/ui/vec.rs +++ b/tests/ui/vec.rs @@ -2,6 +2,12 @@ #![warn(clippy::useless_vec)] #![allow(clippy::nonstandard_macro_braces, clippy::uninlined_format_args)] +use std::rc::Rc; + +struct StructWithVec { + _x: Vec, +} + #[derive(Debug)] struct NonCopy; @@ -75,4 +81,44 @@ fn main() { for a in vec![1; 201] { println!("{:?}", a); } + + // Do lint + let mut x = vec![1, 2, 3]; + x.fill(123); + dbg!(x[0]); + dbg!(x.len()); + dbg!(x.iter().sum::()); + + let _x: &[i32] = &vec![1, 2, 3]; + + for _ in vec![1, 2, 3] {} + + // Don't lint + let x = vec![1, 2, 3]; + let _v: Vec = x; + + let x = vec![1, 2, 3]; + let _s = StructWithVec { _x: x }; + + // Explicit type annotation would make the change to [1, 2, 3] + // a compile error. + let _x: Vec = vec![1, 2, 3]; + + // Calling a Vec method through a mutable reference + let mut x = vec![1, 2, 3]; + let re = &mut x; + re.push(4); + + // Comparing arrays whose length is not equal is a compile error + let x = vec![1, 2, 3]; + let y = vec![1, 2, 3, 4]; + dbg!(x == y); + + // Non-copy types + let _x = vec![String::new(); 10]; + #[allow(clippy::rc_clone_in_vec_init)] + let _x = vec![Rc::new(1); 10]; + + // Too large + let _x = vec![1; 201]; } diff --git a/tests/ui/vec.stderr b/tests/ui/vec.stderr index 7d1de05a5c8..f94a82d2171 100644 --- a/tests/ui/vec.stderr +++ b/tests/ui/vec.stderr @@ -1,5 +1,5 @@ error: useless use of `vec!` - --> $DIR/vec.rs:28:14 + --> $DIR/vec.rs:34:14 | LL | on_slice(&vec![]); | ^^^^^^^ help: you can use a slice directly: `&[]` @@ -7,64 +7,82 @@ LL | on_slice(&vec![]); = note: `-D clippy::useless-vec` implied by `-D warnings` error: useless use of `vec!` - --> $DIR/vec.rs:30:18 + --> $DIR/vec.rs:36:18 | LL | on_mut_slice(&mut vec![]); | ^^^^^^^^^^^ help: you can use a slice directly: `&mut []` error: useless use of `vec!` - --> $DIR/vec.rs:32:14 + --> $DIR/vec.rs:38:14 | LL | on_slice(&vec![1, 2]); | ^^^^^^^^^^^ help: you can use a slice directly: `&[1, 2]` error: useless use of `vec!` - --> $DIR/vec.rs:34:18 + --> $DIR/vec.rs:40:18 | LL | on_mut_slice(&mut vec![1, 2]); | ^^^^^^^^^^^^^^^ help: you can use a slice directly: `&mut [1, 2]` error: useless use of `vec!` - --> $DIR/vec.rs:36:14 + --> $DIR/vec.rs:42:14 | LL | on_slice(&vec![1, 2]); | ^^^^^^^^^^^ help: you can use a slice directly: `&[1, 2]` error: useless use of `vec!` - --> $DIR/vec.rs:38:18 + --> $DIR/vec.rs:44:18 | LL | on_mut_slice(&mut vec![1, 2]); | ^^^^^^^^^^^^^^^ help: you can use a slice directly: `&mut [1, 2]` error: useless use of `vec!` - --> $DIR/vec.rs:40:14 + --> $DIR/vec.rs:46:14 | LL | on_slice(&vec!(1, 2)); | ^^^^^^^^^^^ help: you can use a slice directly: `&[1, 2]` error: useless use of `vec!` - --> $DIR/vec.rs:42:18 + --> $DIR/vec.rs:48:18 | LL | on_mut_slice(&mut vec![1, 2]); | ^^^^^^^^^^^^^^^ help: you can use a slice directly: `&mut [1, 2]` error: useless use of `vec!` - --> $DIR/vec.rs:44:14 + --> $DIR/vec.rs:50:14 | LL | on_slice(&vec![1; 2]); | ^^^^^^^^^^^ help: you can use a slice directly: `&[1; 2]` error: useless use of `vec!` - --> $DIR/vec.rs:46:18 + --> $DIR/vec.rs:52:18 | LL | on_mut_slice(&mut vec![1; 2]); | ^^^^^^^^^^^^^^^ help: you can use a slice directly: `&mut [1; 2]` error: useless use of `vec!` - --> $DIR/vec.rs:63:14 + --> $DIR/vec.rs:69:14 | LL | for a in vec![1, 2, 3] { | ^^^^^^^^^^^^^ help: you can use a slice directly: `&[1, 2, 3]` -error: aborting due to 11 previous errors +error: useless use of `vec!` + --> $DIR/vec.rs:86:17 + | +LL | let mut x = vec![1, 2, 3]; + | ^^^^^^^^^^^^^ help: you can use an array directly: `[1, 2, 3]` + +error: useless use of `vec!` + --> $DIR/vec.rs:92:22 + | +LL | let _x: &[i32] = &vec![1, 2, 3]; + | ^^^^^^^^^^^^^^ help: you can use a slice directly: `&[1, 2, 3]` + +error: useless use of `vec!` + --> $DIR/vec.rs:94:14 + | +LL | for _ in vec![1, 2, 3] {} + | ^^^^^^^^^^^^^ help: you can use a slice directly: `&[1, 2, 3]` + +error: aborting due to 14 previous errors diff --git a/tests/ui/while_let_on_iterator.fixed b/tests/ui/while_let_on_iterator.fixed index c2f216a8911..11f0de07c62 100644 --- a/tests/ui/while_let_on_iterator.fixed +++ b/tests/ui/while_let_on_iterator.fixed @@ -6,7 +6,8 @@ clippy::manual_find, clippy::never_loop, clippy::redundant_closure_call, - clippy::uninlined_format_args + clippy::uninlined_format_args, + clippy::useless_vec )] fn base() { diff --git a/tests/ui/while_let_on_iterator.rs b/tests/ui/while_let_on_iterator.rs index 971bd5f0c4a..e54575dd3b4 100644 --- a/tests/ui/while_let_on_iterator.rs +++ b/tests/ui/while_let_on_iterator.rs @@ -6,7 +6,8 @@ clippy::manual_find, clippy::never_loop, clippy::redundant_closure_call, - clippy::uninlined_format_args + clippy::uninlined_format_args, + clippy::useless_vec )] fn base() { diff --git a/tests/ui/while_let_on_iterator.stderr b/tests/ui/while_let_on_iterator.stderr index 4d98666190d..f8a66f2ad3e 100644 --- a/tests/ui/while_let_on_iterator.stderr +++ b/tests/ui/while_let_on_iterator.stderr @@ -1,5 +1,5 @@ error: this loop could be written as a `for` loop - --> $DIR/while_let_on_iterator.rs:14:5 + --> $DIR/while_let_on_iterator.rs:15:5 | LL | while let Option::Some(x) = iter.next() { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `for x in iter` @@ -7,151 +7,151 @@ LL | while let Option::Some(x) = iter.next() { = note: `-D clippy::while-let-on-iterator` implied by `-D warnings` error: this loop could be written as a `for` loop - --> $DIR/while_let_on_iterator.rs:19:5 + --> $DIR/while_let_on_iterator.rs:20:5 | LL | while let Some(x) = iter.next() { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `for x in iter` error: this loop could be written as a `for` loop - --> $DIR/while_let_on_iterator.rs:24:5 + --> $DIR/while_let_on_iterator.rs:25:5 | LL | while let Some(_) = iter.next() {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `for _ in iter` error: this loop could be written as a `for` loop - --> $DIR/while_let_on_iterator.rs:100:9 + --> $DIR/while_let_on_iterator.rs:101:9 | LL | while let Some([..]) = it.next() {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `for [..] in it` error: this loop could be written as a `for` loop - --> $DIR/while_let_on_iterator.rs:107:9 + --> $DIR/while_let_on_iterator.rs:108:9 | LL | while let Some([_x]) = it.next() {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `for [_x] in it` error: this loop could be written as a `for` loop - --> $DIR/while_let_on_iterator.rs:120:9 + --> $DIR/while_let_on_iterator.rs:121:9 | LL | while let Some(x @ [_]) = it.next() { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `for x @ [_] in it` error: this loop could be written as a `for` loop - --> $DIR/while_let_on_iterator.rs:140:9 + --> $DIR/while_let_on_iterator.rs:141:9 | LL | while let Some(_) = y.next() { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `for _ in y` error: this loop could be written as a `for` loop - --> $DIR/while_let_on_iterator.rs:197:9 + --> $DIR/while_let_on_iterator.rs:198:9 | LL | while let Some(m) = it.next() { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `for m in it.by_ref()` error: this loop could be written as a `for` loop - --> $DIR/while_let_on_iterator.rs:208:5 + --> $DIR/while_let_on_iterator.rs:209:5 | LL | while let Some(n) = it.next() { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `for n in it` error: this loop could be written as a `for` loop - --> $DIR/while_let_on_iterator.rs:210:9 + --> $DIR/while_let_on_iterator.rs:211:9 | LL | while let Some(m) = it.next() { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `for m in it` error: this loop could be written as a `for` loop - --> $DIR/while_let_on_iterator.rs:219:9 + --> $DIR/while_let_on_iterator.rs:220:9 | LL | while let Some(m) = it.next() { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `for m in it` error: this loop could be written as a `for` loop - --> $DIR/while_let_on_iterator.rs:228:9 + --> $DIR/while_let_on_iterator.rs:229:9 | LL | while let Some(m) = it.next() { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `for m in it.by_ref()` error: this loop could be written as a `for` loop - --> $DIR/while_let_on_iterator.rs:245:9 + --> $DIR/while_let_on_iterator.rs:246:9 | LL | while let Some(m) = it.next() { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `for m in it.by_ref()` error: this loop could be written as a `for` loop - --> $DIR/while_let_on_iterator.rs:260:13 + --> $DIR/while_let_on_iterator.rs:261:13 | LL | while let Some(i) = self.0.next() { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `for i in self.0.by_ref()` error: this loop could be written as a `for` loop - --> $DIR/while_let_on_iterator.rs:292:13 + --> $DIR/while_let_on_iterator.rs:293:13 | LL | while let Some(i) = self.0.0.0.next() { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `for i in self.0.0.0.by_ref()` error: this loop could be written as a `for` loop - --> $DIR/while_let_on_iterator.rs:321:5 + --> $DIR/while_let_on_iterator.rs:322:5 | LL | while let Some(n) = it.next() { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `for n in it.by_ref()` error: this loop could be written as a `for` loop - --> $DIR/while_let_on_iterator.rs:333:9 + --> $DIR/while_let_on_iterator.rs:334:9 | LL | while let Some(x) = it.next() { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `for x in it.by_ref()` error: this loop could be written as a `for` loop - --> $DIR/while_let_on_iterator.rs:347:5 + --> $DIR/while_let_on_iterator.rs:348:5 | LL | while let Some(x) = it.next() { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `for x in it.by_ref()` error: this loop could be written as a `for` loop - --> $DIR/while_let_on_iterator.rs:358:5 + --> $DIR/while_let_on_iterator.rs:359:5 | LL | while let Some(x) = it.0.next() { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `for x in it.0.by_ref()` error: this loop could be written as a `for` loop - --> $DIR/while_let_on_iterator.rs:393:5 + --> $DIR/while_let_on_iterator.rs:394:5 | LL | while let Some(x) = s.x.next() { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `for x in s.x.by_ref()` error: this loop could be written as a `for` loop - --> $DIR/while_let_on_iterator.rs:400:5 + --> $DIR/while_let_on_iterator.rs:401:5 | LL | while let Some(x) = x[0].next() { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `for x in x[0].by_ref()` error: this loop could be written as a `for` loop - --> $DIR/while_let_on_iterator.rs:408:9 + --> $DIR/while_let_on_iterator.rs:409:9 | LL | while let Some(x) = it.next() { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `for x in it` error: this loop could be written as a `for` loop - --> $DIR/while_let_on_iterator.rs:418:9 + --> $DIR/while_let_on_iterator.rs:419:9 | LL | while let Some(x) = it.next() { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `for x in it` error: this loop could be written as a `for` loop - --> $DIR/while_let_on_iterator.rs:428:9 + --> $DIR/while_let_on_iterator.rs:429:9 | LL | while let Some(x) = it.next() { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `for x in it.by_ref()` error: this loop could be written as a `for` loop - --> $DIR/while_let_on_iterator.rs:438:9 + --> $DIR/while_let_on_iterator.rs:439:9 | LL | while let Some(x) = it.next() { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `for x in it` error: this loop could be written as a `for` loop - --> $DIR/while_let_on_iterator.rs:448:5 + --> $DIR/while_let_on_iterator.rs:449:5 | LL | while let Some(..) = it.next() { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `for _ in it` From e97f190a9dab40aa1fe2e5ec72af5d52f5fcf1fd Mon Sep 17 00:00:00 2001 From: Centri3 <114838443+Centri3@users.noreply.github.com> Date: Tue, 6 Jun 2023 18:05:15 -0500 Subject: [PATCH 079/310] `ty_search_pat` --- clippy_utils/src/check_proc_macro.rs | 42 ++++++++++++++++++++++++++-- 1 file changed, 40 insertions(+), 2 deletions(-) diff --git a/clippy_utils/src/check_proc_macro.rs b/clippy_utils/src/check_proc_macro.rs index 7e954898460..7f79b8f87dd 100644 --- a/clippy_utils/src/check_proc_macro.rs +++ b/clippy_utils/src/check_proc_macro.rs @@ -19,8 +19,8 @@ use rustc_ast::{ }; use rustc_hir::{ intravisit::FnKind, Block, BlockCheckMode, Body, Closure, Destination, Expr, ExprKind, FieldDef, FnHeader, HirId, - Impl, ImplItem, ImplItemKind, IsAuto, Item, ItemKind, LoopSource, MatchSource, Node, QPath, TraitItem, - TraitItemKind, UnOp, UnsafeSource, Unsafety, Variant, VariantData, YieldSource, + Impl, ImplItem, ImplItemKind, IsAuto, Item, ItemKind, LoopSource, MatchSource, MutTy, Node, QPath, TraitItem, + TraitItemKind, Ty, TyKind, UnOp, UnsafeSource, Unsafety, Variant, VariantData, YieldSource, }; use rustc_lint::{LateContext, LintContext}; use rustc_middle::ty::TyCtxt; @@ -319,6 +319,43 @@ fn attr_search_pat(attr: &Attribute) -> (Pat, Pat) { } } +// TODO: Waiting on `ty_search_pat`. +// fn where_pred_search_pat(where_pred: &WherePredicate<'_>) -> (Pat, Pat) { +// match where_pred { +// WherePredicate::BoundPredicate(bound) => { +// todo!(); +// }, +// WherePredicate::RegionPredicate(region) => { +// +// }, +// WherePredicate::EqPredicate(..) => unimplemented!(), +// } +// } + +fn ty_search_pat(ty: &Ty<'_>) -> (Pat, Pat) { + match ty.kind { + TyKind::Slice(..) | TyKind::Array(..) => (Pat::Str("["), Pat::Str("]")), + TyKind::Ptr(MutTy { mutbl, ty }) => ( + if mutbl.is_mut() { + Pat::Str("*const") + } else { + Pat::Str("*mut") + }, + ty_search_pat(ty).1, + ), + TyKind::Ref(_, MutTy { ty, .. }) => (Pat::Str("&"), ty_search_pat(ty).1), + TyKind::BareFn(bare_fn) => ( + Pat::OwnedStr(format!("{}{} fn", bare_fn.unsafety.prefix_str(), bare_fn.abi.name())), + ty_search_pat(ty).1, + ), + TyKind::Never => (Pat::Str("!"), Pat::Str("")), + TyKind::Tup(..) => (Pat::Str("("), Pat::Str(")")), + TyKind::OpaqueDef(..) => (Pat::Str("impl"), Pat::Str("")), + // NOTE: This is missing `TraitObject` and `Path` here. It always return true then. + _ => (Pat::Str(""), Pat::Str("")), + } +} + pub trait WithSearchPat { type Context: LintContext; fn search_pat(&self, cx: &Self::Context) -> (Pat, Pat); @@ -345,6 +382,7 @@ impl_with_search_pat!(LateContext: TraitItem with trait_item_search_pat); impl_with_search_pat!(LateContext: ImplItem with impl_item_search_pat); impl_with_search_pat!(LateContext: FieldDef with field_def_search_pat); impl_with_search_pat!(LateContext: Variant with variant_search_pat); +impl_with_search_pat!(LateContext: Ty with ty_search_pat); impl<'cx> WithSearchPat for (&FnKind<'cx>, &Body<'cx>, HirId, Span) { type Context = LateContext<'cx>; From ba1fb74bf1633a5150b4843f6d0bde7af2443950 Mon Sep 17 00:00:00 2001 From: Centri3 <114838443+Centri3@users.noreply.github.com> Date: Tue, 6 Jun 2023 21:01:14 -0500 Subject: [PATCH 080/310] check for `_` instead --- clippy_lints/src/let_with_type_underscore.rs | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/clippy_lints/src/let_with_type_underscore.rs b/clippy_lints/src/let_with_type_underscore.rs index 4f8c5ff58b5..4e9d77ea156 100644 --- a/clippy_lints/src/let_with_type_underscore.rs +++ b/clippy_lints/src/let_with_type_underscore.rs @@ -26,19 +26,16 @@ declare_clippy_lint! { declare_lint_pass!(UnderscoreTyped => [LET_WITH_TYPE_UNDERSCORE]); impl LateLintPass<'_> for UnderscoreTyped { - fn check_local<'tcx>(&mut self, cx: &LateContext<'tcx>, local: &'tcx Local<'tcx>) { + fn check_local(&mut self, cx: &LateContext<'_>, local: &Local<'_>) { if_chain! { if !in_external_macro(cx.tcx.sess, local.span); if let Some(ty) = local.ty; // Ensure that it has a type defined if let TyKind::Infer = &ty.kind; // that type is '_' if local.span.ctxt() == ty.span.ctxt(); then { - let underscore_span = ty.span.with_lo(local.pat.span.hi()); - let snippet = snippet(cx, underscore_span, ": _"); - // NOTE: Using `is_from_proc_macro` on `init` will require that it's initialized, // this doesn't. Alternatively, `WithSearchPat` can be implemented for `Ty` - if !snippet.trim().starts_with(':') && !snippet.trim().ends_with('_') { + if snippet(cx, ty.span, "_").trim() != "_" { return; } @@ -47,7 +44,7 @@ impl LateLintPass<'_> for UnderscoreTyped { LET_WITH_TYPE_UNDERSCORE, local.span, "variable declared with type underscore", - Some(underscore_span), + Some(ty.span.with_lo(local.pat.span.hi())), "remove the explicit type `_` declaration" ) } From a434a7715d205959c3a07c9a7fe43e56a128e0c4 Mon Sep 17 00:00:00 2001 From: Centri3 <114838443+Centri3@users.noreply.github.com> Date: Tue, 6 Jun 2023 22:16:02 -0500 Subject: [PATCH 081/310] `impl WithSearchPat for Ty` --- clippy_lints/src/trait_bounds.rs | 12 ++++++------ clippy_utils/src/check_proc_macro.rs | 3 ++- 2 files changed, 8 insertions(+), 7 deletions(-) diff --git a/clippy_lints/src/trait_bounds.rs b/clippy_lints/src/trait_bounds.rs index 2e6108d6b24..f4554fbcf9b 100644 --- a/clippy_lints/src/trait_bounds.rs +++ b/clippy_lints/src/trait_bounds.rs @@ -1,6 +1,6 @@ use clippy_utils::diagnostics::{span_lint_and_help, span_lint_and_sugg}; use clippy_utils::source::{snippet, snippet_opt, snippet_with_applicability}; -use clippy_utils::{SpanlessEq, SpanlessHash}; +use clippy_utils::{is_from_proc_macro, SpanlessEq, SpanlessHash}; use core::hash::{Hash, Hasher}; use if_chain::if_chain; use itertools::Itertools; @@ -260,10 +260,7 @@ impl TraitBounds { SpanlessTy { ty: p.bounded_ty, cx }, p.bounds.iter().collect::>() ); - let bounded_ty = snippet(cx, p.bounded_ty.span, "_"); - if let TyKind::Path(qpath) = p.bounded_ty.kind; - if format!("{}:", rustc_hir_pretty::qpath_to_string(&qpath)) == format!("{bounded_ty}:"); - + if !is_from_proc_macro(cx, p.bounded_ty); then { let trait_bounds = v .iter() @@ -272,7 +269,10 @@ impl TraitBounds { .filter_map(get_trait_info_from_bound) .map(|(_, _, span)| snippet_with_applicability(cx, span, "..", &mut applicability)) .join(" + "); - let hint_string = format!("consider combining the bounds: `{bounded_ty}: {trait_bounds}`"); + let hint_string = format!( + "consider combining the bounds: `{}: {trait_bounds}`", + snippet(cx, p.bounded_ty.span, "_"), + ); span_lint_and_help( cx, TYPE_REPETITION_IN_BOUNDS, diff --git a/clippy_utils/src/check_proc_macro.rs b/clippy_utils/src/check_proc_macro.rs index 7f79b8f87dd..05b34986274 100644 --- a/clippy_utils/src/check_proc_macro.rs +++ b/clippy_utils/src/check_proc_macro.rs @@ -351,7 +351,8 @@ fn ty_search_pat(ty: &Ty<'_>) -> (Pat, Pat) { TyKind::Never => (Pat::Str("!"), Pat::Str("")), TyKind::Tup(..) => (Pat::Str("("), Pat::Str(")")), TyKind::OpaqueDef(..) => (Pat::Str("impl"), Pat::Str("")), - // NOTE: This is missing `TraitObject` and `Path` here. It always return true then. + TyKind::Path(qpath) => qpath_search_pat(&qpath), + // NOTE: This is missing `TraitObject`. It always return true then. _ => (Pat::Str(""), Pat::Str("")), } } From 7af77f74da28b51207cb35dd7d627109571eb678 Mon Sep 17 00:00:00 2001 From: y21 <30553356+y21@users.noreply.github.com> Date: Wed, 7 Jun 2023 08:54:32 +0200 Subject: [PATCH 082/310] don't allow `as_slice` for now --- clippy_lints/src/vec.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clippy_lints/src/vec.rs b/clippy_lints/src/vec.rs index ec21f3bb54f..467805d90ff 100644 --- a/clippy_lints/src/vec.rs +++ b/clippy_lints/src/vec.rs @@ -63,7 +63,7 @@ fn adjusts_to_slice(cx: &LateContext<'_>, e: &Expr<'_>) -> bool { /// that also exists on slices. If this returns true, it means that /// this expression does not actually require a `Vec` and could just work with an array. fn is_allowed_vec_method(cx: &LateContext<'_>, e: &Expr<'_>) -> bool { - const ALLOWED_METHOD_NAMES: &[&str] = &["len", "as_ptr", "as_slice", "is_empty"]; + const ALLOWED_METHOD_NAMES: &[&str] = &["len", "as_ptr", "is_empty"]; if let ExprKind::MethodCall(path, ..) = e.kind { ALLOWED_METHOD_NAMES.contains(&path.ident.name.as_str()) From 3e8f53b51de543feca85af0d413376b18f598cb9 Mon Sep 17 00:00:00 2001 From: Renato Lochetti Date: Wed, 7 Jun 2023 08:35:39 +0100 Subject: [PATCH 083/310] Don't warn if there is a comment between else and curly bracket --- clippy_lints/src/formatting.rs | 6 ++++++ tests/ui/suspicious_else_formatting.rs | 7 +++++++ 2 files changed, 13 insertions(+) diff --git a/clippy_lints/src/formatting.rs b/clippy_lints/src/formatting.rs index 4762b354392..d03480c2108 100644 --- a/clippy_lints/src/formatting.rs +++ b/clippy_lints/src/formatting.rs @@ -236,6 +236,12 @@ fn check_else(cx: &EarlyContext<'_>, expr: &Expr) { } } + // Don't warn if the only thing inside post_else_post_eol is a comment block. + let trimmed_post_else_post_eol = post_else_post_eol.trim(); + if trimmed_post_else_post_eol.starts_with("/*") && trimmed_post_else_post_eol.ends_with("*/") { + return + } + let else_desc = if is_if(else_) { "if" } else { "{..}" }; span_lint_and_note( cx, diff --git a/tests/ui/suspicious_else_formatting.rs b/tests/ui/suspicious_else_formatting.rs index 4823d909208..a96cc1b090c 100644 --- a/tests/ui/suspicious_else_formatting.rs +++ b/tests/ui/suspicious_else_formatting.rs @@ -108,6 +108,13 @@ fn main() { else { } + + //#10273 This is fine. Don't warn + if foo() { + } else + /* whelp */ + { + } } // #7650 - Don't lint. Proc-macro using bad spans for `if` expressions. From 2c7cf2cfa113e28e82854574eb1227d7c001d84c Mon Sep 17 00:00:00 2001 From: y21 <30553356+y21@users.noreply.github.com> Date: Wed, 7 Jun 2023 22:57:15 +0200 Subject: [PATCH 084/310] handle RangeInclusive function desugar --- clippy_lints/src/eta_reduction.rs | 10 ++++++- tests/ui/eta.fixed | 6 ++++ tests/ui/eta.rs | 6 ++++ tests/ui/eta.stderr | 50 +++++++++++++++++-------------- 4 files changed, 49 insertions(+), 23 deletions(-) diff --git a/clippy_lints/src/eta_reduction.rs b/clippy_lints/src/eta_reduction.rs index c919b4de65d..fcbf0898890 100644 --- a/clippy_lints/src/eta_reduction.rs +++ b/clippy_lints/src/eta_reduction.rs @@ -123,7 +123,14 @@ impl<'tcx> LateLintPass<'tcx> for EtaReduction { then { span_lint_and_then(cx, REDUNDANT_CLOSURE, expr.span, "redundant closure", |diag| { if let Some(mut snippet) = snippet_opt(cx, callee.span) { - if let Some(fn_mut_id) = cx.tcx.lang_items().fn_mut_trait() + if let Some(higher::Range { + start: Some(_), + end: Some(_), + limits: rustc_ast::RangeLimits::Closed + }) = higher::Range::hir(body.value) { + // `|x,y| x..=y` becomes `|x, y| RangeInclusive::new(x, y)` + snippet = "core::ops::RangeInclusive::new".to_owned(); + } else if let Some(fn_mut_id) = cx.tcx.lang_items().fn_mut_trait() && let args = cx.tcx.erase_late_bound_regions(substs.as_closure().sig()).inputs() && implements_trait( cx, @@ -136,6 +143,7 @@ impl<'tcx> LateLintPass<'tcx> for EtaReduction { // Mutable closure is used after current expr; we cannot consume it. snippet = format!("&mut {snippet}"); } + diag.span_suggestion( expr.span, "replace the closure with the function itself", diff --git a/tests/ui/eta.fixed b/tests/ui/eta.fixed index b1baf462c0f..934deb66362 100644 --- a/tests/ui/eta.fixed +++ b/tests/ui/eta.fixed @@ -46,6 +46,12 @@ fn main() { // issue #7224 let _: Option> = Some(0).map(|_| vec![]); + + // issue #10684 + fn test(x: impl Fn(usize, usize) -> T) -> T { + x(1, 2) + } + test(core::ops::RangeInclusive::new); } trait TestTrait { diff --git a/tests/ui/eta.rs b/tests/ui/eta.rs index e113c3d6cd6..978aecd24b3 100644 --- a/tests/ui/eta.rs +++ b/tests/ui/eta.rs @@ -46,6 +46,12 @@ fn main() { // issue #7224 let _: Option> = Some(0).map(|_| vec![]); + + // issue #10684 + fn test(x: impl Fn(usize, usize) -> T) -> T { + x(1, 2) + } + test(|start, end| start..=end); } trait TestTrait { diff --git a/tests/ui/eta.stderr b/tests/ui/eta.stderr index a521fb86860..1f5db2d5129 100644 --- a/tests/ui/eta.stderr +++ b/tests/ui/eta.stderr @@ -31,7 +31,13 @@ LL | let e = Some(1u8).map(|a| generic(a)); | ^^^^^^^^^^^^^^ help: replace the closure with the function itself: `generic` error: redundant closure - --> $DIR/eta.rs:87:51 + --> $DIR/eta.rs:54:10 + | +LL | test(|start, end| start..=end); + | ^^^^^^^^^^^^^^^^^^^^^^^^ help: replace the closure with the function itself: `core::ops::RangeInclusive::new` + +error: redundant closure + --> $DIR/eta.rs:93:51 | LL | let e = Some(TestStruct { some_ref: &i }).map(|a| a.foo()); | ^^^^^^^^^^^ help: replace the closure with the method itself: `TestStruct::foo` @@ -39,124 +45,124 @@ LL | let e = Some(TestStruct { some_ref: &i }).map(|a| a.foo()); = note: `-D clippy::redundant-closure-for-method-calls` implied by `-D warnings` error: redundant closure - --> $DIR/eta.rs:88:51 + --> $DIR/eta.rs:94:51 | LL | let e = Some(TestStruct { some_ref: &i }).map(|a| a.trait_foo()); | ^^^^^^^^^^^^^^^^^ help: replace the closure with the method itself: `TestTrait::trait_foo` error: redundant closure - --> $DIR/eta.rs:90:42 + --> $DIR/eta.rs:96:42 | LL | let e = Some(&mut vec![1, 2, 3]).map(|v| v.clear()); | ^^^^^^^^^^^^^ help: replace the closure with the method itself: `std::vec::Vec::clear` error: redundant closure - --> $DIR/eta.rs:94:29 + --> $DIR/eta.rs:100:29 | LL | let e = Some("str").map(|s| s.to_string()); | ^^^^^^^^^^^^^^^^^ help: replace the closure with the method itself: `std::string::ToString::to_string` error: redundant closure - --> $DIR/eta.rs:95:27 + --> $DIR/eta.rs:101:27 | LL | let e = Some('a').map(|s| s.to_uppercase()); | ^^^^^^^^^^^^^^^^^^^^ help: replace the closure with the method itself: `char::to_uppercase` error: redundant closure - --> $DIR/eta.rs:97:65 + --> $DIR/eta.rs:103:65 | LL | let e: std::vec::Vec = vec!['a', 'b', 'c'].iter().map(|c| c.to_ascii_uppercase()).collect(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace the closure with the method itself: `char::to_ascii_uppercase` error: redundant closure - --> $DIR/eta.rs:160:22 + --> $DIR/eta.rs:166:22 | LL | requires_fn_once(|| x()); | ^^^^^^ help: replace the closure with the function itself: `x` error: redundant closure - --> $DIR/eta.rs:167:27 + --> $DIR/eta.rs:173:27 | LL | let a = Some(1u8).map(|a| foo_ptr(a)); | ^^^^^^^^^^^^^^ help: replace the closure with the function itself: `foo_ptr` error: redundant closure - --> $DIR/eta.rs:172:27 + --> $DIR/eta.rs:178:27 | LL | let a = Some(1u8).map(|a| closure(a)); | ^^^^^^^^^^^^^^ help: replace the closure with the function itself: `closure` error: redundant closure - --> $DIR/eta.rs:204:28 + --> $DIR/eta.rs:210:28 | LL | x.into_iter().for_each(|x| add_to_res(x)); | ^^^^^^^^^^^^^^^^^ help: replace the closure with the function itself: `&mut add_to_res` error: redundant closure - --> $DIR/eta.rs:205:28 + --> $DIR/eta.rs:211:28 | LL | y.into_iter().for_each(|x| add_to_res(x)); | ^^^^^^^^^^^^^^^^^ help: replace the closure with the function itself: `&mut add_to_res` error: redundant closure - --> $DIR/eta.rs:206:28 + --> $DIR/eta.rs:212:28 | LL | z.into_iter().for_each(|x| add_to_res(x)); | ^^^^^^^^^^^^^^^^^ help: replace the closure with the function itself: `add_to_res` error: redundant closure - --> $DIR/eta.rs:213:21 + --> $DIR/eta.rs:219:21 | LL | Some(1).map(|n| closure(n)); | ^^^^^^^^^^^^^^ help: replace the closure with the function itself: `&mut closure` error: redundant closure - --> $DIR/eta.rs:217:21 + --> $DIR/eta.rs:223:21 | LL | Some(1).map(|n| in_loop(n)); | ^^^^^^^^^^^^^^ help: replace the closure with the function itself: `in_loop` error: redundant closure - --> $DIR/eta.rs:310:18 + --> $DIR/eta.rs:316:18 | LL | takes_fn_mut(|| f()); | ^^^^^^ help: replace the closure with the function itself: `&mut f` error: redundant closure - --> $DIR/eta.rs:313:19 + --> $DIR/eta.rs:319:19 | LL | takes_fn_once(|| f()); | ^^^^^^ help: replace the closure with the function itself: `&mut f` error: redundant closure - --> $DIR/eta.rs:317:26 + --> $DIR/eta.rs:323:26 | LL | move || takes_fn_mut(|| f_used_once()) | ^^^^^^^^^^^^^^^^ help: replace the closure with the function itself: `&mut f_used_once` error: redundant closure - --> $DIR/eta.rs:329:19 + --> $DIR/eta.rs:335:19 | LL | array_opt.map(|a| a.as_slice()); | ^^^^^^^^^^^^^^^^ help: replace the closure with the method itself: `<[u8; 3]>::as_slice` error: redundant closure - --> $DIR/eta.rs:332:19 + --> $DIR/eta.rs:338:19 | LL | slice_opt.map(|s| s.len()); | ^^^^^^^^^^^ help: replace the closure with the method itself: `<[u8]>::len` error: redundant closure - --> $DIR/eta.rs:335:17 + --> $DIR/eta.rs:341:17 | LL | ptr_opt.map(|p| p.is_null()); | ^^^^^^^^^^^^^^^ help: replace the closure with the method itself: `<*const usize>::is_null` error: redundant closure - --> $DIR/eta.rs:339:17 + --> $DIR/eta.rs:345:17 | LL | dyn_opt.map(|d| d.method_on_dyn()); | ^^^^^^^^^^^^^^^^^^^^^ help: replace the closure with the method itself: `::method_on_dyn` -error: aborting due to 26 previous errors +error: aborting due to 27 previous errors From 9ff34acf211c1b2aa7b4a282b2dd38927e137169 Mon Sep 17 00:00:00 2001 From: y21 <30553356+y21@users.noreply.github.com> Date: Thu, 8 Jun 2023 00:34:23 +0200 Subject: [PATCH 085/310] actually don't lint for inclusive range --- clippy_lints/src/eta_reduction.rs | 16 ++++++++-------- tests/ui/eta.fixed | 2 +- tests/ui/eta.stderr | 8 +------- 3 files changed, 10 insertions(+), 16 deletions(-) diff --git a/clippy_lints/src/eta_reduction.rs b/clippy_lints/src/eta_reduction.rs index fcbf0898890..58e62d1f3d3 100644 --- a/clippy_lints/src/eta_reduction.rs +++ b/clippy_lints/src/eta_reduction.rs @@ -120,17 +120,17 @@ impl<'tcx> LateLintPass<'tcx> for EtaReduction { if !is_type_diagnostic_item(cx, callee_ty_unadjusted, sym::Arc); if !is_type_diagnostic_item(cx, callee_ty_unadjusted, sym::Rc); if let ty::Closure(_, substs) = *closure_ty.kind(); + // Don't lint if this is an inclusive range expression. + // They desugar to a call to `RangeInclusiveNew` which would have odd suggestions. (#10684) + if !matches!(higher::Range::hir(body.value), Some(higher::Range { + start: Some(_), + end: Some(_), + limits: rustc_ast::RangeLimits::Closed + })); then { span_lint_and_then(cx, REDUNDANT_CLOSURE, expr.span, "redundant closure", |diag| { if let Some(mut snippet) = snippet_opt(cx, callee.span) { - if let Some(higher::Range { - start: Some(_), - end: Some(_), - limits: rustc_ast::RangeLimits::Closed - }) = higher::Range::hir(body.value) { - // `|x,y| x..=y` becomes `|x, y| RangeInclusive::new(x, y)` - snippet = "core::ops::RangeInclusive::new".to_owned(); - } else if let Some(fn_mut_id) = cx.tcx.lang_items().fn_mut_trait() + if let Some(fn_mut_id) = cx.tcx.lang_items().fn_mut_trait() && let args = cx.tcx.erase_late_bound_regions(substs.as_closure().sig()).inputs() && implements_trait( cx, diff --git a/tests/ui/eta.fixed b/tests/ui/eta.fixed index 934deb66362..31a94cb10e8 100644 --- a/tests/ui/eta.fixed +++ b/tests/ui/eta.fixed @@ -51,7 +51,7 @@ fn main() { fn test(x: impl Fn(usize, usize) -> T) -> T { x(1, 2) } - test(core::ops::RangeInclusive::new); + test(|start, end| start..=end); } trait TestTrait { diff --git a/tests/ui/eta.stderr b/tests/ui/eta.stderr index 1f5db2d5129..19be5fc7389 100644 --- a/tests/ui/eta.stderr +++ b/tests/ui/eta.stderr @@ -30,12 +30,6 @@ error: redundant closure LL | let e = Some(1u8).map(|a| generic(a)); | ^^^^^^^^^^^^^^ help: replace the closure with the function itself: `generic` -error: redundant closure - --> $DIR/eta.rs:54:10 - | -LL | test(|start, end| start..=end); - | ^^^^^^^^^^^^^^^^^^^^^^^^ help: replace the closure with the function itself: `core::ops::RangeInclusive::new` - error: redundant closure --> $DIR/eta.rs:93:51 | @@ -164,5 +158,5 @@ error: redundant closure LL | dyn_opt.map(|d| d.method_on_dyn()); | ^^^^^^^^^^^^^^^^^^^^^ help: replace the closure with the method itself: `::method_on_dyn` -error: aborting due to 27 previous errors +error: aborting due to 26 previous errors From 97c10075eca950c34958f2f32bf9956b3945ff42 Mon Sep 17 00:00:00 2001 From: Centri3 <114838443+Centri3@users.noreply.github.com> Date: Thu, 20 Apr 2023 01:14:50 -0500 Subject: [PATCH 086/310] add the `excessive_*` style lints --- CHANGELOG.md | 2 + clippy_lints/src/declared_lints.rs | 2 + clippy_lints/src/excessive_width.rs | 82 +++++++++++++++++++ clippy_lints/src/lib.rs | 11 +++ clippy_lints/src/utils/conf.rs | 12 +++ tests/ui-toml/excessive_width/clippy.toml | 3 + .../excessive_width/excessive_width.rs | 26 ++++++ .../excessive_width/excessive_width.stderr | 24 ++++++ tests/ui/excessive_width.rs | 44 ++++++++++ tests/ui/excessive_width.stderr | 11 +++ 10 files changed, 217 insertions(+) create mode 100644 clippy_lints/src/excessive_width.rs create mode 100644 tests/ui-toml/excessive_width/clippy.toml create mode 100644 tests/ui-toml/excessive_width/excessive_width.rs create mode 100644 tests/ui-toml/excessive_width/excessive_width.stderr create mode 100644 tests/ui/excessive_width.rs create mode 100644 tests/ui/excessive_width.stderr diff --git a/CHANGELOG.md b/CHANGELOG.md index a65ac4d46de..76fd81a25c6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4758,7 +4758,9 @@ Released 2018-09-13 [`erasing_op`]: https://rust-lang.github.io/rust-clippy/master/index.html#erasing_op [`err_expect`]: https://rust-lang.github.io/rust-clippy/master/index.html#err_expect [`eval_order_dependence`]: https://rust-lang.github.io/rust-clippy/master/index.html#eval_order_dependence +[`excessive_indentation`]: https://rust-lang.github.io/rust-clippy/master/index.html#excessive_indentation [`excessive_precision`]: https://rust-lang.github.io/rust-clippy/master/index.html#excessive_precision +[`excessive_width`]: https://rust-lang.github.io/rust-clippy/master/index.html#excessive_width [`exhaustive_enums`]: https://rust-lang.github.io/rust-clippy/master/index.html#exhaustive_enums [`exhaustive_structs`]: https://rust-lang.github.io/rust-clippy/master/index.html#exhaustive_structs [`exit`]: https://rust-lang.github.io/rust-clippy/master/index.html#exit diff --git a/clippy_lints/src/declared_lints.rs b/clippy_lints/src/declared_lints.rs index d014534cee9..20911348690 100644 --- a/clippy_lints/src/declared_lints.rs +++ b/clippy_lints/src/declared_lints.rs @@ -159,6 +159,8 @@ pub(crate) static LINTS: &[&crate::LintInfo] = &[ crate::eta_reduction::REDUNDANT_CLOSURE_FOR_METHOD_CALLS_INFO, crate::excessive_bools::FN_PARAMS_EXCESSIVE_BOOLS_INFO, crate::excessive_bools::STRUCT_EXCESSIVE_BOOLS_INFO, + crate::excessive_width::EXCESSIVE_INDENTATION_INFO, + crate::excessive_width::EXCESSIVE_WIDTH_INFO, crate::exhaustive_items::EXHAUSTIVE_ENUMS_INFO, crate::exhaustive_items::EXHAUSTIVE_STRUCTS_INFO, crate::exit::EXIT_INFO, diff --git a/clippy_lints/src/excessive_width.rs b/clippy_lints/src/excessive_width.rs new file mode 100644 index 00000000000..84ae54f401e --- /dev/null +++ b/clippy_lints/src/excessive_width.rs @@ -0,0 +1,82 @@ +use clippy_utils::diagnostics::span_lint_and_help; +use rustc_hir::*; +use rustc_lint::{LateContext, LateLintPass, LintContext}; +use rustc_middle::lint::in_external_macro; +use rustc_session::{declare_tool_lint, impl_lint_pass}; +use rustc_span::Pos; + +// TODO: This still needs to be implemented. +declare_clippy_lint! { + /// ### What it does + /// + /// Checks for lines which are indented beyond a certain threshold. + /// + /// ### Why is this bad? + /// + /// It can severely hinder readability. The default is very generous; if you + /// exceed this, it's a sign you should refactor. + /// + /// ### Example + /// TODO + /// Use instead: + /// TODO + #[clippy::version = "1.70.0"] + pub EXCESSIVE_INDENTATION, + style, + "check for lines intended beyond a certain threshold" +} +declare_clippy_lint! { + /// ### What it does + /// + /// Checks for lines which are longer than a certain threshold. + /// + /// ### Why is this bad? + /// + /// It can severely hinder readability. Almost always, running rustfmt will get this + /// below this threshold (or whatever you have set as max_width), but if it fails, + /// it's probably a sign you should refactor. + /// + /// ### Example + /// TODO + /// Use instead: + /// TODO + #[clippy::version = "1.70.0"] + pub EXCESSIVE_WIDTH, + style, + "check for lines longer than a certain threshold" +} +impl_lint_pass!(ExcessiveWidth => [EXCESSIVE_INDENTATION, EXCESSIVE_WIDTH]); + +#[derive(Clone, Copy)] +pub struct ExcessiveWidth { + pub excessive_width_threshold: u64, + pub excessive_width_ignore_indentation: bool, + pub excessive_indentation_threshold: u64, +} + +impl LateLintPass<'_> for ExcessiveWidth { + fn check_stmt(&mut self, cx: &LateContext<'_>, stmt: &Stmt<'_>) { + if in_external_macro(cx.sess(), stmt.span) { + return; + } + + if let Ok(lines) = cx.sess().source_map().span_to_lines(stmt.span).map(|info| info.lines) { + for line in &lines { + // TODO: yeah, no. + if (line.end_col.to_usize() + - line.start_col.to_usize() * self.excessive_width_ignore_indentation as usize) + > self.excessive_width_threshold as usize + { + span_lint_and_help( + cx, + EXCESSIVE_WIDTH, + stmt.span, + "this line is too long", + None, + "consider running rustfmt or refactoring this", + ); + } + } + } + } +} diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index d53c6de5451..8b08861bc1d 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -122,6 +122,7 @@ mod equatable_if_let; mod escape; mod eta_reduction; mod excessive_bools; +mod excessive_width; mod exhaustive_items; mod exit; mod explicit_write; @@ -1007,6 +1008,16 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: 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)); + let excessive_width_threshold = conf.excessive_width_threshold; + let excessive_width_ignore_indentation = conf.excessive_width_ignore_indentation; + let excessive_indentation_threshold = conf.excessive_indentation_threshold; + store.register_late_pass(move |_| { + Box::new(excessive_width::ExcessiveWidth { + excessive_width_threshold, + excessive_width_ignore_indentation, + excessive_indentation_threshold, + }) + }); store.register_late_pass(|_| Box::new(items_after_test_module::ItemsAfterTestModule)); store.register_early_pass(|| Box::new(ref_patterns::RefPatterns)); store.register_late_pass(|_| Box::new(default_constructed_unit_structs::DefaultConstructedUnitStructs)); diff --git a/clippy_lints/src/utils/conf.rs b/clippy_lints/src/utils/conf.rs index 35f40830681..1bdb5e42418 100644 --- a/clippy_lints/src/utils/conf.rs +++ b/clippy_lints/src/utils/conf.rs @@ -305,6 +305,18 @@ define_Conf! { /// /// The maximum cognitive complexity a function can have (cognitive_complexity_threshold: u64 = 25), + /// Lint: EXCESSIVE_WIDTH. + /// + /// The maximum width a statement can have + (excessive_width_threshold: u64 = 100), + /// Lint: EXCESSIVE_WIDTH. + /// + /// Whether to ignore the line's indentation + (excessive_width_ignore_indentation: bool = true), + /// Lint: EXCESSIVE_INDENTATION. + /// + /// The maximum indentation a statement can have + (excessive_indentation_threshold: u64 = 10), /// DEPRECATED LINT: CYCLOMATIC_COMPLEXITY. /// /// Use the Cognitive Complexity lint instead. diff --git a/tests/ui-toml/excessive_width/clippy.toml b/tests/ui-toml/excessive_width/clippy.toml new file mode 100644 index 00000000000..1824c8a3127 --- /dev/null +++ b/tests/ui-toml/excessive_width/clippy.toml @@ -0,0 +1,3 @@ +excessive-width-threshold = 20 +excessive-width-ignore-indentation = false +excessive-indentation-threshold = 3 diff --git a/tests/ui-toml/excessive_width/excessive_width.rs b/tests/ui-toml/excessive_width/excessive_width.rs new file mode 100644 index 00000000000..261b937e72e --- /dev/null +++ b/tests/ui-toml/excessive_width/excessive_width.rs @@ -0,0 +1,26 @@ +#![allow(unused)] +#![allow(clippy::identity_op)] +#![allow(clippy::no_effect)] +#![warn(clippy::excessive_width)] + +static mut C: u32 = 2u32; + +#[rustfmt::skip] +fn main() { + let x = 2 * unsafe { C }; + + { + { + // this too, even though it's only 15 characters! + (); + } + } + + { + { + { + println!("this will now emit a warning, how neat!") + } + } + } +} diff --git a/tests/ui-toml/excessive_width/excessive_width.stderr b/tests/ui-toml/excessive_width/excessive_width.stderr new file mode 100644 index 00000000000..00dce391be0 --- /dev/null +++ b/tests/ui-toml/excessive_width/excessive_width.stderr @@ -0,0 +1,24 @@ +error: this line is too long + --> $DIR/excessive_width.rs:10:5 + | +LL | let x = 2 * unsafe { C }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: consider running rustfmt or refactoring this + = note: `-D clippy::excessive-width` implied by `-D warnings` + +error: this line is too long + --> $DIR/excessive_width.rs:12:5 + | +LL | / { +LL | | { +LL | | // this too, even though it's only 15 characters! +LL | | (); +LL | | } +LL | | } + | |_____^ + | + = help: consider running rustfmt or refactoring this + +error: aborting due to 2 previous errors + diff --git a/tests/ui/excessive_width.rs b/tests/ui/excessive_width.rs new file mode 100644 index 00000000000..218950f9684 --- /dev/null +++ b/tests/ui/excessive_width.rs @@ -0,0 +1,44 @@ +#![allow(unused)] +#![allow(clippy::identity_op)] +#![warn(clippy::excessive_width)] + +#[rustfmt::skip] +fn main() { + let x = 1; + + let really_long_binding_name_because_this_needs_to_be_over_90_characters_long = 1usize * 200 / 2 * 500 / 1; + + { + { + { + { + { + { + { + { + { + { + { + { + { + { + { + { + println!("highly indented lines do not cause a warning (by default)!") + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } +} diff --git a/tests/ui/excessive_width.stderr b/tests/ui/excessive_width.stderr new file mode 100644 index 00000000000..707a3796b56 --- /dev/null +++ b/tests/ui/excessive_width.stderr @@ -0,0 +1,11 @@ +error: this line is too long + --> $DIR/excessive_width.rs:9:5 + | +LL | let really_long_binding_name_because_this_needs_to_be_over_90_characters_long = 1usize * 200 / 2 * 500 / 1; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: consider running rustfmt or refactoring this + = note: `-D clippy::excessive-width` implied by `-D warnings` + +error: aborting due to previous error + From 4af3ac1cd8cf907b142c5cd813f1733289c29063 Mon Sep 17 00:00:00 2001 From: Centri3 <114838443+Centri3@users.noreply.github.com> Date: Thu, 20 Apr 2023 01:19:26 -0500 Subject: [PATCH 087/310] change it to nursery category --- clippy_lints/src/excessive_width.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/clippy_lints/src/excessive_width.rs b/clippy_lints/src/excessive_width.rs index 84ae54f401e..0e23b39a14e 100644 --- a/clippy_lints/src/excessive_width.rs +++ b/clippy_lints/src/excessive_width.rs @@ -22,7 +22,7 @@ declare_clippy_lint! { /// TODO #[clippy::version = "1.70.0"] pub EXCESSIVE_INDENTATION, - style, + nursery, "check for lines intended beyond a certain threshold" } declare_clippy_lint! { @@ -42,7 +42,7 @@ declare_clippy_lint! { /// TODO #[clippy::version = "1.70.0"] pub EXCESSIVE_WIDTH, - style, + nursery, "check for lines longer than a certain threshold" } impl_lint_pass!(ExcessiveWidth => [EXCESSIVE_INDENTATION, EXCESSIVE_WIDTH]); From e68dbc3308397e68d672f9f70742af41897b06be Mon Sep 17 00:00:00 2001 From: Centri3 <114838443+Centri3@users.noreply.github.com> Date: Thu, 20 Apr 2023 08:03:25 -0500 Subject: [PATCH 088/310] add `excessive_nesting` Close code block in example --- CHANGELOG.md | 3 +- clippy_lints/src/declared_lints.rs | 3 +- clippy_lints/src/excessive_nesting.rs | 325 ++++++++++++++++ clippy_lints/src/excessive_width.rs | 82 ---- clippy_lints/src/lib.rs | 14 +- clippy_lints/src/utils/conf.rs | 14 +- .../auxiliary/macro_rules.rs | 7 + tests/ui-toml/excessive_nesting/clippy.toml | 1 + .../excessive_nesting/excessive_nesting.rs | 191 ++++++++++ .../excessive_nesting.stderr | 358 ++++++++++++++++++ tests/ui-toml/excessive_width/clippy.toml | 3 - .../excessive_width/excessive_width.rs | 26 -- .../excessive_width/excessive_width.stderr | 24 -- .../toml_unknown_key/conf_unknown_key.stderr | 1 + tests/ui/auxiliary/macro_rules.rs | 1 - tests/ui/excessive_width.rs | 44 --- tests/ui/excessive_width.stderr | 11 - 17 files changed, 893 insertions(+), 215 deletions(-) create mode 100644 clippy_lints/src/excessive_nesting.rs delete mode 100644 clippy_lints/src/excessive_width.rs create mode 100644 tests/ui-toml/excessive_nesting/auxiliary/macro_rules.rs create mode 100644 tests/ui-toml/excessive_nesting/clippy.toml create mode 100644 tests/ui-toml/excessive_nesting/excessive_nesting.rs create mode 100644 tests/ui-toml/excessive_nesting/excessive_nesting.stderr delete mode 100644 tests/ui-toml/excessive_width/clippy.toml delete mode 100644 tests/ui-toml/excessive_width/excessive_width.rs delete mode 100644 tests/ui-toml/excessive_width/excessive_width.stderr delete mode 100644 tests/ui/excessive_width.rs delete mode 100644 tests/ui/excessive_width.stderr diff --git a/CHANGELOG.md b/CHANGELOG.md index 76fd81a25c6..69ac2c893d9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4758,9 +4758,8 @@ Released 2018-09-13 [`erasing_op`]: https://rust-lang.github.io/rust-clippy/master/index.html#erasing_op [`err_expect`]: https://rust-lang.github.io/rust-clippy/master/index.html#err_expect [`eval_order_dependence`]: https://rust-lang.github.io/rust-clippy/master/index.html#eval_order_dependence -[`excessive_indentation`]: https://rust-lang.github.io/rust-clippy/master/index.html#excessive_indentation +[`excessive_nesting`]: https://rust-lang.github.io/rust-clippy/master/index.html#excessive_nesting [`excessive_precision`]: https://rust-lang.github.io/rust-clippy/master/index.html#excessive_precision -[`excessive_width`]: https://rust-lang.github.io/rust-clippy/master/index.html#excessive_width [`exhaustive_enums`]: https://rust-lang.github.io/rust-clippy/master/index.html#exhaustive_enums [`exhaustive_structs`]: https://rust-lang.github.io/rust-clippy/master/index.html#exhaustive_structs [`exit`]: https://rust-lang.github.io/rust-clippy/master/index.html#exit diff --git a/clippy_lints/src/declared_lints.rs b/clippy_lints/src/declared_lints.rs index 20911348690..0c51996b625 100644 --- a/clippy_lints/src/declared_lints.rs +++ b/clippy_lints/src/declared_lints.rs @@ -159,8 +159,7 @@ pub(crate) static LINTS: &[&crate::LintInfo] = &[ crate::eta_reduction::REDUNDANT_CLOSURE_FOR_METHOD_CALLS_INFO, crate::excessive_bools::FN_PARAMS_EXCESSIVE_BOOLS_INFO, crate::excessive_bools::STRUCT_EXCESSIVE_BOOLS_INFO, - crate::excessive_width::EXCESSIVE_INDENTATION_INFO, - crate::excessive_width::EXCESSIVE_WIDTH_INFO, + crate::excessive_nesting::EXCESSIVE_NESTING_INFO, crate::exhaustive_items::EXHAUSTIVE_ENUMS_INFO, crate::exhaustive_items::EXHAUSTIVE_STRUCTS_INFO, crate::exit::EXIT_INFO, diff --git a/clippy_lints/src/excessive_nesting.rs b/clippy_lints/src/excessive_nesting.rs new file mode 100644 index 00000000000..a60e2442fa2 --- /dev/null +++ b/clippy_lints/src/excessive_nesting.rs @@ -0,0 +1,325 @@ +use clippy_utils::diagnostics::span_lint_and_help; +use rustc_ast::{ + node_id::NodeId, + ptr::P, + visit::{FnKind, Visitor}, + Arm, AssocItemKind, Block, Expr, ExprKind, Inline, Item, ItemKind, Local, LocalKind, ModKind, ModSpans, Pat, + PatKind, Stmt, StmtKind, +}; +use rustc_lint::{EarlyContext, EarlyLintPass, LintContext}; +use rustc_middle::lint::in_external_macro; +use rustc_session::{declare_tool_lint, impl_lint_pass}; +use rustc_span::Span; +use thin_vec::ThinVec; + +declare_clippy_lint! { + /// ### What it does + /// + /// Checks for blocks which are indented beyond a certain threshold. + /// + /// ### Why is this bad? + /// + /// It can severely hinder readability. The default is very generous; if you + /// exceed this, it's a sign you should refactor. + /// + /// ### Known issues + /// + /// Nested inline modules will all be linted, rather than just the outermost one + /// that applies. This makes the output a bit verbose. + /// + /// ### Example + /// An example clippy.toml configuration: + /// ```toml + /// # clippy.toml + /// excessive-nesting-threshold = 3 + /// ``` + /// lib.rs: + /// ```rust,ignore + /// pub mod a { + /// pub struct X; + /// impl X { + /// pub fn run(&self) { + /// if true { + /// // etc... + /// } + /// } + /// } + /// } + /// Use instead: + /// a.rs: + /// ```rust,ignore + /// fn private_run(x: &X) { + /// if true { + /// // etc... + /// } + /// } + /// + /// pub struct X; + /// impl X { + /// pub fn run(&self) { + /// private_run(self); + /// } + /// } + /// ``` + #[clippy::version = "1.70.0"] + pub EXCESSIVE_NESTING, + restriction, + "checks for blocks nested beyond a certain threshold" +} +impl_lint_pass!(ExcessiveNesting => [EXCESSIVE_NESTING]); + +#[derive(Clone, Copy)] +pub struct ExcessiveNesting { + pub excessive_nesting_threshold: u64, +} + +impl EarlyLintPass for ExcessiveNesting { + fn check_item(&mut self, cx: &EarlyContext<'_>, item: &Item) { + let conf = self; + NestingVisitor { + conf, + cx, + nest_level: 0, + } + .visit_item(item); + } +} + +struct NestingVisitor<'conf, 'cx> { + conf: &'conf ExcessiveNesting, + cx: &'cx EarlyContext<'cx>, + nest_level: u64, +} + +impl<'conf, 'cx> Visitor<'_> for NestingVisitor<'conf, 'cx> { + fn visit_local(&mut self, local: &Local) { + self.visit_pat(&local.pat); + + match &local.kind { + LocalKind::Init(expr) => self.visit_expr(expr), + LocalKind::InitElse(expr, block) => { + self.visit_expr(expr); + self.visit_block(block); + }, + LocalKind::Decl => (), + } + } + + fn visit_block(&mut self, block: &Block) { + self.nest_level += 1; + + if !check_indent(self, block.span) { + for stmt in &block.stmts { + self.visit_stmt(stmt); + } + } + + self.nest_level -= 1; + } + + fn visit_stmt(&mut self, stmt: &Stmt) { + match &stmt.kind { + StmtKind::Local(local) => self.visit_local(local), + StmtKind::Item(item) => self.visit_item(item), + StmtKind::Expr(expr) | StmtKind::Semi(expr) => self.visit_expr(expr), + _ => (), + } + } + + fn visit_arm(&mut self, arm: &Arm) { + self.visit_pat(&arm.pat); + if let Some(expr) = &arm.guard { + self.visit_expr(expr); + } + self.visit_expr(&arm.body); + } + + // TODO: Is this necessary? + fn visit_pat(&mut self, pat: &Pat) { + match &pat.kind { + PatKind::Box(pat) | PatKind::Ref(pat, ..) | PatKind::Paren(pat) => self.visit_pat(pat), + PatKind::Lit(expr) => self.visit_expr(expr), + PatKind::Range(start, end, ..) => { + if let Some(expr) = start { + self.visit_expr(expr); + } + if let Some(expr) = end { + self.visit_expr(expr); + } + }, + PatKind::Ident(.., pat) if let Some(pat) = pat => { + self.visit_pat(pat); + }, + PatKind::Struct(.., pat_fields, _) => { + for pat_field in pat_fields { + self.visit_pat(&pat_field.pat); + } + }, + PatKind::TupleStruct(.., pats) | PatKind::Or(pats) | PatKind::Tuple(pats) | PatKind::Slice(pats) => { + for pat in pats { + self.visit_pat(pat); + } + }, + _ => (), + } + } + + fn visit_expr(&mut self, expr: &Expr) { + // This is a mess, but really all it does is extract every expression from every applicable variant + // of ExprKind until it finds a Block. + match &expr.kind { + ExprKind::ConstBlock(anon_const) => self.visit_expr(&anon_const.value), + ExprKind::Call(.., args) => { + for expr in args { + self.visit_expr(expr); + } + }, + ExprKind::MethodCall(method_call) => { + for expr in &method_call.args { + self.visit_expr(expr); + } + }, + ExprKind::Tup(exprs) | ExprKind::Array(exprs) => { + for expr in exprs { + self.visit_expr(expr); + } + }, + ExprKind::Binary(.., left, right) + | ExprKind::Assign(left, right, ..) + | ExprKind::AssignOp(.., left, right) + | ExprKind::Index(left, right) => { + self.visit_expr(left); + self.visit_expr(right); + }, + ExprKind::Let(pat, expr, ..) => { + self.visit_pat(pat); + self.visit_expr(expr); + }, + ExprKind::Unary(.., expr) + | ExprKind::Await(expr) + | ExprKind::Field(expr, ..) + | ExprKind::AddrOf(.., expr) + | ExprKind::Try(expr) => { + self.visit_expr(expr); + }, + ExprKind::Repeat(expr, anon_const) => { + self.visit_expr(expr); + self.visit_expr(&anon_const.value); + }, + ExprKind::If(expr, block, else_expr) => { + self.visit_expr(expr); + self.visit_block(block); + + if let Some(expr) = else_expr { + self.visit_expr(expr); + } + }, + ExprKind::While(expr, block, ..) => { + self.visit_expr(expr); + self.visit_block(block); + }, + ExprKind::ForLoop(pat, expr, block, ..) => { + self.visit_pat(pat); + self.visit_expr(expr); + self.visit_block(block); + }, + ExprKind::Loop(block, ..) + | ExprKind::Block(block, ..) + | ExprKind::Async(.., block) + | ExprKind::TryBlock(block) => { + self.visit_block(block); + }, + ExprKind::Match(expr, arms) => { + self.visit_expr(expr); + + for arm in arms { + self.visit_arm(arm); + } + }, + ExprKind::Closure(closure) => self.visit_expr(&closure.body), + ExprKind::Range(start, end, ..) => { + if let Some(expr) = start { + self.visit_expr(expr); + } + if let Some(expr) = end { + self.visit_expr(expr); + } + }, + ExprKind::Break(.., expr) | ExprKind::Ret(expr) | ExprKind::Yield(expr) | ExprKind::Yeet(expr) => { + if let Some(expr) = expr { + self.visit_expr(expr); + } + }, + ExprKind::Struct(struct_expr) => { + for field in &struct_expr.fields { + self.visit_expr(&field.expr); + } + }, + _ => (), + } + } + + fn visit_fn(&mut self, fk: FnKind<'_>, _: Span, _: NodeId) { + match fk { + FnKind::Fn(.., block) if let Some(block) = block => self.visit_block(block), + FnKind::Closure(.., expr) => self.visit_expr(expr), + // :/ + FnKind::Fn(..) => (), + } + } + + fn visit_item(&mut self, item: &Item) { + match &item.kind { + ItemKind::Static(static_item) if let Some(expr) = static_item.expr.as_ref() => self.visit_expr(expr), + ItemKind::Const(const_item) if let Some(expr) = const_item.expr.as_ref() => self.visit_expr(expr), + ItemKind::Fn(fk) if let Some(block) = fk.body.as_ref() => self.visit_block(block), + ItemKind::Mod(.., mod_kind) + if let ModKind::Loaded(items, Inline::Yes, ModSpans { inner_span, ..}) = mod_kind => + { + self.nest_level += 1; + + check_indent(self, *inner_span); + + self.nest_level -= 1; + } + ItemKind::Trait(trit) => check_trait_and_impl(self, item, &trit.items), + ItemKind::Impl(imp) => check_trait_and_impl(self, item, &imp.items), + _ => (), + } + } +} + +fn check_trait_and_impl(visitor: &mut NestingVisitor<'_, '_>, item: &Item, items: &ThinVec>>) { + visitor.nest_level += 1; + + if !check_indent(visitor, item.span) { + for item in items { + match &item.kind { + AssocItemKind::Const(const_item) if let Some(expr) = const_item.expr.as_ref() => { + visitor.visit_expr(expr); + }, + AssocItemKind::Fn(fk) if let Some(block) = fk.body.as_ref() => visitor.visit_block(block), + _ => (), + } + } + } + + visitor.nest_level -= 1; +} + +fn check_indent(visitor: &NestingVisitor<'_, '_>, span: Span) -> bool { + if visitor.nest_level > visitor.conf.excessive_nesting_threshold && !in_external_macro(visitor.cx.sess(), span) { + span_lint_and_help( + visitor.cx, + EXCESSIVE_NESTING, + span, + "this block is too nested", + None, + "try refactoring your code, extraction is often both easier to read and less nested", + ); + + return true; + } + + false +} diff --git a/clippy_lints/src/excessive_width.rs b/clippy_lints/src/excessive_width.rs deleted file mode 100644 index 0e23b39a14e..00000000000 --- a/clippy_lints/src/excessive_width.rs +++ /dev/null @@ -1,82 +0,0 @@ -use clippy_utils::diagnostics::span_lint_and_help; -use rustc_hir::*; -use rustc_lint::{LateContext, LateLintPass, LintContext}; -use rustc_middle::lint::in_external_macro; -use rustc_session::{declare_tool_lint, impl_lint_pass}; -use rustc_span::Pos; - -// TODO: This still needs to be implemented. -declare_clippy_lint! { - /// ### What it does - /// - /// Checks for lines which are indented beyond a certain threshold. - /// - /// ### Why is this bad? - /// - /// It can severely hinder readability. The default is very generous; if you - /// exceed this, it's a sign you should refactor. - /// - /// ### Example - /// TODO - /// Use instead: - /// TODO - #[clippy::version = "1.70.0"] - pub EXCESSIVE_INDENTATION, - nursery, - "check for lines intended beyond a certain threshold" -} -declare_clippy_lint! { - /// ### What it does - /// - /// Checks for lines which are longer than a certain threshold. - /// - /// ### Why is this bad? - /// - /// It can severely hinder readability. Almost always, running rustfmt will get this - /// below this threshold (or whatever you have set as max_width), but if it fails, - /// it's probably a sign you should refactor. - /// - /// ### Example - /// TODO - /// Use instead: - /// TODO - #[clippy::version = "1.70.0"] - pub EXCESSIVE_WIDTH, - nursery, - "check for lines longer than a certain threshold" -} -impl_lint_pass!(ExcessiveWidth => [EXCESSIVE_INDENTATION, EXCESSIVE_WIDTH]); - -#[derive(Clone, Copy)] -pub struct ExcessiveWidth { - pub excessive_width_threshold: u64, - pub excessive_width_ignore_indentation: bool, - pub excessive_indentation_threshold: u64, -} - -impl LateLintPass<'_> for ExcessiveWidth { - fn check_stmt(&mut self, cx: &LateContext<'_>, stmt: &Stmt<'_>) { - if in_external_macro(cx.sess(), stmt.span) { - return; - } - - if let Ok(lines) = cx.sess().source_map().span_to_lines(stmt.span).map(|info| info.lines) { - for line in &lines { - // TODO: yeah, no. - if (line.end_col.to_usize() - - line.start_col.to_usize() * self.excessive_width_ignore_indentation as usize) - > self.excessive_width_threshold as usize - { - span_lint_and_help( - cx, - EXCESSIVE_WIDTH, - stmt.span, - "this line is too long", - None, - "consider running rustfmt or refactoring this", - ); - } - } - } - } -} diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index 8b08861bc1d..202b4709ad4 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -122,7 +122,7 @@ mod equatable_if_let; mod escape; mod eta_reduction; mod excessive_bools; -mod excessive_width; +mod excessive_nesting; mod exhaustive_items; mod exit; mod explicit_write; @@ -1008,14 +1008,10 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: 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)); - let excessive_width_threshold = conf.excessive_width_threshold; - let excessive_width_ignore_indentation = conf.excessive_width_ignore_indentation; - let excessive_indentation_threshold = conf.excessive_indentation_threshold; - store.register_late_pass(move |_| { - Box::new(excessive_width::ExcessiveWidth { - excessive_width_threshold, - excessive_width_ignore_indentation, - excessive_indentation_threshold, + let excessive_nesting_threshold = conf.excessive_nesting_threshold; + store.register_early_pass(move || { + Box::new(excessive_nesting::ExcessiveNesting { + excessive_nesting_threshold, }) }); store.register_late_pass(|_| Box::new(items_after_test_module::ItemsAfterTestModule)); diff --git a/clippy_lints/src/utils/conf.rs b/clippy_lints/src/utils/conf.rs index 1bdb5e42418..cf0da266dc9 100644 --- a/clippy_lints/src/utils/conf.rs +++ b/clippy_lints/src/utils/conf.rs @@ -305,18 +305,10 @@ define_Conf! { /// /// The maximum cognitive complexity a function can have (cognitive_complexity_threshold: u64 = 25), - /// Lint: EXCESSIVE_WIDTH. + /// Lint: EXCESSIVE_NESTING. /// - /// The maximum width a statement can have - (excessive_width_threshold: u64 = 100), - /// Lint: EXCESSIVE_WIDTH. - /// - /// Whether to ignore the line's indentation - (excessive_width_ignore_indentation: bool = true), - /// Lint: EXCESSIVE_INDENTATION. - /// - /// The maximum indentation a statement can have - (excessive_indentation_threshold: u64 = 10), + /// The maximum amount of nesting a block can reside in + (excessive_nesting_threshold: u64 = 10), /// DEPRECATED LINT: CYCLOMATIC_COMPLEXITY. /// /// Use the Cognitive Complexity lint instead. diff --git a/tests/ui-toml/excessive_nesting/auxiliary/macro_rules.rs b/tests/ui-toml/excessive_nesting/auxiliary/macro_rules.rs new file mode 100644 index 00000000000..86663db68f2 --- /dev/null +++ b/tests/ui-toml/excessive_nesting/auxiliary/macro_rules.rs @@ -0,0 +1,7 @@ +#[rustfmt::skip] +#[macro_export] +macro_rules! excessive_nesting { + () => {{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{ + println!("hi!!") + }}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}} +} diff --git a/tests/ui-toml/excessive_nesting/clippy.toml b/tests/ui-toml/excessive_nesting/clippy.toml new file mode 100644 index 00000000000..10be2751a86 --- /dev/null +++ b/tests/ui-toml/excessive_nesting/clippy.toml @@ -0,0 +1 @@ +excessive-nesting-threshold = 3 diff --git a/tests/ui-toml/excessive_nesting/excessive_nesting.rs b/tests/ui-toml/excessive_nesting/excessive_nesting.rs new file mode 100644 index 00000000000..66fc8166314 --- /dev/null +++ b/tests/ui-toml/excessive_nesting/excessive_nesting.rs @@ -0,0 +1,191 @@ +//@aux-build:macro_rules.rs +#![rustfmt::skip] +#![feature(custom_inner_attributes)] +#![allow(unused)] +#![allow(clippy::let_and_return)] +#![allow(clippy::redundant_closure_call)] +#![allow(clippy::no_effect)] +#![allow(clippy::unnecessary_operation)] +#![allow(clippy::never_loop)] +#![warn(clippy::excessive_nesting)] +#![allow(clippy::collapsible_if)] + +#[macro_use] +extern crate macro_rules; + +static X: u32 = { + let x = { + let y = { + let z = { + let w = { 3 }; + w + }; + z + }; + y + }; + x +}; + +macro_rules! xx { + () => {{ + { + { + { + { + { + { + { + { + { + { + println!("ehe"); + } + } + } + } + } + } + } + } + } + } + }}; +} + +struct A; + +impl A { + pub fn a(&self, v: u32) { + struct B; + + impl B { + pub fn b() { + struct C; + + impl C { + pub fn c() {} + } + } + } + } +} + +struct D { d: u32 } + +trait Lol { + fn lmao() { + fn bb() { + fn cc() { + let x = { 1 }; // not a warning + } + + let x = { 1 }; // warning + } + } +} + +use a::{b::{c::{d::{e::{f::{}}}}}}; // should not lint + +pub mod a { + pub mod b { + pub mod c { + pub mod d { + pub mod e { + pub mod f {} + } + } + } + } +} + +fn a_but_not(v: u32) {} + +fn main() { + let a = A; + + a_but_not({{{{{{{{0}}}}}}}}); + a.a({{{{{{{{{0}}}}}}}}}); + (0, {{{{{{{1}}}}}}}); + + if true { + if true { + if true { + if true { + if true { + + } + } + } + } + } + + let y = (|| { + let x = (|| { + let y = (|| { + let z = (|| { + let w = { 3 }; + w + })(); + z + })(); + y + })(); + x + })(); + + excessive_nesting!(); // ensure this isn't linted in external macros + xx!(); + let boo = true; + !{boo as u32 + !{boo as u32 + !{boo as u32}}}; + + let mut y = 1; + y += {{{{{5}}}}}; + let z = y + {{{{{{{{{5}}}}}}}}}; + [0, {{{{{{{{{{0}}}}}}}}}}]; + let mut xx = [0; {{{{{{{{100}}}}}}}}]; + xx[{{{{{{{{{{{{{{{{{{{{{{{{3}}}}}}}}}}}}}}}}}}}}}}}}]; + &mut {{{{{{{{{{y}}}}}}}}}}; + + for i in {{{{xx}}}} {{{{{{{{}}}}}}}} + + while let Some(i) = {{{{{{Some(1)}}}}}} {{{{{{{}}}}}}} + + while {{{{{{{{true}}}}}}}} {{{{{{{{{}}}}}}}}} + + let d = D { d: {{{{{{{{{{{{{{{{{{{{{{{3}}}}}}}}}}}}}}}}}}}}}}} }; + + {{{{1;}}}}..{{{{{{3}}}}}}; + {{{{1;}}}}..={{{{{{{{{{{{{{{{{{{{{{{{{{6}}}}}}}}}}}}}}}}}}}}}}}}}}; + ..{{{{{{{5}}}}}}}; + ..={{{{{3}}}}}; + {{{{{1;}}}}}..; + + loop { break {{{{1}}}} }; + loop {{{{{{}}}}}} + + match {{{{{{true}}}}}} { + true => {{{{}}}}, + false => {{{{}}}}, + } + + { + { + { + { + println!("warning! :)"); + } + } + } + } +} + +async fn b() -> u32 { + async fn c() -> u32 {{{{{{{0}}}}}}} + + c().await +} + +async fn a() { + {{{{b().await}}}}; +} diff --git a/tests/ui-toml/excessive_nesting/excessive_nesting.stderr b/tests/ui-toml/excessive_nesting/excessive_nesting.stderr new file mode 100644 index 00000000000..0bd43da21e2 --- /dev/null +++ b/tests/ui-toml/excessive_nesting/excessive_nesting.stderr @@ -0,0 +1,358 @@ +error: this block is too nested + --> $DIR/excessive_nesting.rs:19:21 + | +LL | let z = { + | _____________________^ +LL | | let w = { 3 }; +LL | | w +LL | | }; + | |_____________^ + | + = help: try refactoring your code, extraction is often both easier to read and less nested + = note: `-D clippy::excessive-nesting` implied by `-D warnings` + +error: this block is too nested + --> $DIR/excessive_nesting.rs:63:24 + | +LL | pub fn b() { + | ________________________^ +LL | | struct C; +LL | | +LL | | impl C { +LL | | pub fn c() {} +LL | | } +LL | | } + | |_____________^ + | + = help: try refactoring your code, extraction is often both easier to read and less nested + +error: this block is too nested + --> $DIR/excessive_nesting.rs:67:32 + | +LL | pub fn c() {} + | ^^ + | + = help: try refactoring your code, extraction is often both easier to read and less nested + +error: this block is too nested + --> $DIR/excessive_nesting.rs:79:21 + | +LL | fn cc() { + | _____________________^ +LL | | let x = { 1 }; // not a warning +LL | | } + | |_____________^ + | + = help: try refactoring your code, extraction is often both easier to read and less nested + +error: this block is too nested + --> $DIR/excessive_nesting.rs:83:21 + | +LL | let x = { 1 }; // warning + | ^^^^^ + | + = help: try refactoring your code, extraction is often both easier to read and less nested + +error: this block is too nested + --> $DIR/excessive_nesting.rs:107:17 + | +LL | a_but_not({{{{{{{{0}}}}}}}}); + | ^^^^^^^^^^^^^ + | + = help: try refactoring your code, extraction is often both easier to read and less nested + +error: this block is too nested + --> $DIR/excessive_nesting.rs:108:11 + | +LL | a.a({{{{{{{{{0}}}}}}}}}); + | ^^^^^^^^^^^^^^^ + | + = help: try refactoring your code, extraction is often both easier to read and less nested + +error: this block is too nested + --> $DIR/excessive_nesting.rs:109:11 + | +LL | (0, {{{{{{{1}}}}}}}); + | ^^^^^^^^^^^ + | + = help: try refactoring your code, extraction is often both easier to read and less nested + +error: this block is too nested + --> $DIR/excessive_nesting.rs:113:21 + | +LL | if true { + | _____________________^ +LL | | if true { +LL | | if true { +LL | | +LL | | } +LL | | } +LL | | } + | |_____________^ + | + = help: try refactoring your code, extraction is often both easier to read and less nested + +error: this block is too nested + --> $DIR/excessive_nesting.rs:33:13 + | +LL | / { +LL | | { +LL | | { +LL | | { +... | +LL | | } +LL | | } + | |_____________^ +... +LL | xx!(); + | ----- in this macro invocation + | + = help: try refactoring your code, extraction is often both easier to read and less nested + = note: this error originates in the macro `xx` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: this block is too nested + --> $DIR/excessive_nesting.rs:140:36 + | +LL | !{boo as u32 + !{boo as u32 + !{boo as u32}}}; + | ^^^^^^^^^^^^ + | + = help: try refactoring your code, extraction is often both easier to read and less nested + +error: this block is too nested + --> $DIR/excessive_nesting.rs:143:12 + | +LL | y += {{{{{5}}}}}; + | ^^^^^^^ + | + = help: try refactoring your code, extraction is often both easier to read and less nested + +error: this block is too nested + --> $DIR/excessive_nesting.rs:144:19 + | +LL | let z = y + {{{{{{{{{5}}}}}}}}}; + | ^^^^^^^^^^^^^^^ + | + = help: try refactoring your code, extraction is often both easier to read and less nested + +error: this block is too nested + --> $DIR/excessive_nesting.rs:145:11 + | +LL | [0, {{{{{{{{{{0}}}}}}}}}}]; + | ^^^^^^^^^^^^^^^^^ + | + = help: try refactoring your code, extraction is often both easier to read and less nested + +error: this block is too nested + --> $DIR/excessive_nesting.rs:146:24 + | +LL | let mut xx = [0; {{{{{{{{100}}}}}}}}]; + | ^^^^^^^^^^^^^^^ + | + = help: try refactoring your code, extraction is often both easier to read and less nested + +error: this block is too nested + --> $DIR/excessive_nesting.rs:147:10 + | +LL | xx[{{{{{{{{{{{{{{{{{{{{{{{{3}}}}}}}}}}}}}}}}}}}}}}}}]; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: try refactoring your code, extraction is often both easier to read and less nested + +error: this block is too nested + --> $DIR/excessive_nesting.rs:148:12 + | +LL | &mut {{{{{{{{{{y}}}}}}}}}}; + | ^^^^^^^^^^^^^^^^^ + | + = help: try refactoring your code, extraction is often both easier to read and less nested + +error: this block is too nested + --> $DIR/excessive_nesting.rs:150:16 + | +LL | for i in {{{{xx}}}} {{{{{{{{}}}}}}}} + | ^^^^^^ + | + = help: try refactoring your code, extraction is often both easier to read and less nested + +error: this block is too nested + --> $DIR/excessive_nesting.rs:150:27 + | +LL | for i in {{{{xx}}}} {{{{{{{{}}}}}}}} + | ^^^^^^^^^^^^ + | + = help: try refactoring your code, extraction is often both easier to read and less nested + +error: this block is too nested + --> $DIR/excessive_nesting.rs:152:27 + | +LL | while let Some(i) = {{{{{{Some(1)}}}}}} {{{{{{{}}}}}}} + | ^^^^^^^^^^^^^^^ + | + = help: try refactoring your code, extraction is often both easier to read and less nested + +error: this block is too nested + --> $DIR/excessive_nesting.rs:152:47 + | +LL | while let Some(i) = {{{{{{Some(1)}}}}}} {{{{{{{}}}}}}} + | ^^^^^^^^^^ + | + = help: try refactoring your code, extraction is often both easier to read and less nested + +error: this block is too nested + --> $DIR/excessive_nesting.rs:154:13 + | +LL | while {{{{{{{{true}}}}}}}} {{{{{{{{{}}}}}}}}} + | ^^^^^^^^^^^^^^^^ + | + = help: try refactoring your code, extraction is often both easier to read and less nested + +error: this block is too nested + --> $DIR/excessive_nesting.rs:154:34 + | +LL | while {{{{{{{{true}}}}}}}} {{{{{{{{{}}}}}}}}} + | ^^^^^^^^^^^^^^ + | + = help: try refactoring your code, extraction is often both easier to read and less nested + +error: this block is too nested + --> $DIR/excessive_nesting.rs:156:22 + | +LL | let d = D { d: {{{{{{{{{{{{{{{{{{{{{{{3}}}}}}}}}}}}}}}}}}}}}}} }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: try refactoring your code, extraction is often both easier to read and less nested + +error: this block is too nested + --> $DIR/excessive_nesting.rs:158:7 + | +LL | {{{{1;}}}}..{{{{{{3}}}}}}; + | ^^^^^^ + | + = help: try refactoring your code, extraction is often both easier to read and less nested + +error: this block is too nested + --> $DIR/excessive_nesting.rs:158:19 + | +LL | {{{{1;}}}}..{{{{{{3}}}}}}; + | ^^^^^^^^^ + | + = help: try refactoring your code, extraction is often both easier to read and less nested + +error: this block is too nested + --> $DIR/excessive_nesting.rs:159:7 + | +LL | {{{{1;}}}}..={{{{{{{{{{{{{{{{{{{{{{{{{{6}}}}}}}}}}}}}}}}}}}}}}}}}}; + | ^^^^^^ + | + = help: try refactoring your code, extraction is often both easier to read and less nested + +error: this block is too nested + --> $DIR/excessive_nesting.rs:159:20 + | +LL | {{{{1;}}}}..={{{{{{{{{{{{{{{{{{{{{{{{{{6}}}}}}}}}}}}}}}}}}}}}}}}}}; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: try refactoring your code, extraction is often both easier to read and less nested + +error: this block is too nested + --> $DIR/excessive_nesting.rs:160:9 + | +LL | ..{{{{{{{5}}}}}}}; + | ^^^^^^^^^^^ + | + = help: try refactoring your code, extraction is often both easier to read and less nested + +error: this block is too nested + --> $DIR/excessive_nesting.rs:161:10 + | +LL | ..={{{{{3}}}}}; + | ^^^^^^^ + | + = help: try refactoring your code, extraction is often both easier to read and less nested + +error: this block is too nested + --> $DIR/excessive_nesting.rs:162:7 + | +LL | {{{{{1;}}}}}..; + | ^^^^^^^^ + | + = help: try refactoring your code, extraction is often both easier to read and less nested + +error: this block is too nested + --> $DIR/excessive_nesting.rs:164:19 + | +LL | loop { break {{{{1}}}} }; + | ^^^^^^^ + | + = help: try refactoring your code, extraction is often both easier to read and less nested + +error: this block is too nested + --> $DIR/excessive_nesting.rs:165:12 + | +LL | loop {{{{{{}}}}}} + | ^^^^^^^^ + | + = help: try refactoring your code, extraction is often both easier to read and less nested + +error: this block is too nested + --> $DIR/excessive_nesting.rs:167:13 + | +LL | match {{{{{{true}}}}}} { + | ^^^^^^^^^^^^ + | + = help: try refactoring your code, extraction is often both easier to read and less nested + +error: this block is too nested + --> $DIR/excessive_nesting.rs:168:19 + | +LL | true => {{{{}}}}, + | ^^^^ + | + = help: try refactoring your code, extraction is often both easier to read and less nested + +error: this block is too nested + --> $DIR/excessive_nesting.rs:169:20 + | +LL | false => {{{{}}}}, + | ^^^^ + | + = help: try refactoring your code, extraction is often both easier to read and less nested + +error: this block is too nested + --> $DIR/excessive_nesting.rs:174:13 + | +LL | / { +LL | | { +LL | | println!("warning! :)"); +LL | | } +LL | | } + | |_____________^ + | + = help: try refactoring your code, extraction is often both easier to read and less nested + +error: this block is too nested + --> $DIR/excessive_nesting.rs:184:27 + | +LL | async fn c() -> u32 {{{{{{{0}}}}}}} + | ^^^^^^^^^^^ + | + = help: try refactoring your code, extraction is often both easier to read and less nested + +error: this block is too nested + --> $DIR/excessive_nesting.rs:184:28 + | +LL | async fn c() -> u32 {{{{{{{0}}}}}}} + | ^^^^^^^^^ + | + = help: try refactoring your code, extraction is often both easier to read and less nested + +error: this block is too nested + --> $DIR/excessive_nesting.rs:190:7 + | +LL | {{{{b().await}}}}; + | ^^^^^^^^^^^^^ + | + = help: try refactoring your code, extraction is often both easier to read and less nested + +error: aborting due to 40 previous errors + diff --git a/tests/ui-toml/excessive_width/clippy.toml b/tests/ui-toml/excessive_width/clippy.toml deleted file mode 100644 index 1824c8a3127..00000000000 --- a/tests/ui-toml/excessive_width/clippy.toml +++ /dev/null @@ -1,3 +0,0 @@ -excessive-width-threshold = 20 -excessive-width-ignore-indentation = false -excessive-indentation-threshold = 3 diff --git a/tests/ui-toml/excessive_width/excessive_width.rs b/tests/ui-toml/excessive_width/excessive_width.rs deleted file mode 100644 index 261b937e72e..00000000000 --- a/tests/ui-toml/excessive_width/excessive_width.rs +++ /dev/null @@ -1,26 +0,0 @@ -#![allow(unused)] -#![allow(clippy::identity_op)] -#![allow(clippy::no_effect)] -#![warn(clippy::excessive_width)] - -static mut C: u32 = 2u32; - -#[rustfmt::skip] -fn main() { - let x = 2 * unsafe { C }; - - { - { - // this too, even though it's only 15 characters! - (); - } - } - - { - { - { - println!("this will now emit a warning, how neat!") - } - } - } -} diff --git a/tests/ui-toml/excessive_width/excessive_width.stderr b/tests/ui-toml/excessive_width/excessive_width.stderr deleted file mode 100644 index 00dce391be0..00000000000 --- a/tests/ui-toml/excessive_width/excessive_width.stderr +++ /dev/null @@ -1,24 +0,0 @@ -error: this line is too long - --> $DIR/excessive_width.rs:10:5 - | -LL | let x = 2 * unsafe { C }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = help: consider running rustfmt or refactoring this - = note: `-D clippy::excessive-width` implied by `-D warnings` - -error: this line is too long - --> $DIR/excessive_width.rs:12:5 - | -LL | / { -LL | | { -LL | | // this too, even though it's only 15 characters! -LL | | (); -LL | | } -LL | | } - | |_____^ - | - = help: consider running rustfmt or refactoring this - -error: aborting due to 2 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 b6038f031f3..28b6e7aa824 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: unknown field `foobar`, expect enforced-import-renames enum-variant-name-threshold enum-variant-size-threshold + excessive-nesting-threshold future-size-threshold ignore-interior-mutability large-error-threshold diff --git a/tests/ui/auxiliary/macro_rules.rs b/tests/ui/auxiliary/macro_rules.rs index e5bb906663c..d9a1e76c077 100644 --- a/tests/ui/auxiliary/macro_rules.rs +++ b/tests/ui/auxiliary/macro_rules.rs @@ -1,7 +1,6 @@ #![allow(dead_code)] //! Used to test that certain lints don't trigger in imported external macros - #[macro_export] macro_rules! try_err { () => { diff --git a/tests/ui/excessive_width.rs b/tests/ui/excessive_width.rs deleted file mode 100644 index 218950f9684..00000000000 --- a/tests/ui/excessive_width.rs +++ /dev/null @@ -1,44 +0,0 @@ -#![allow(unused)] -#![allow(clippy::identity_op)] -#![warn(clippy::excessive_width)] - -#[rustfmt::skip] -fn main() { - let x = 1; - - let really_long_binding_name_because_this_needs_to_be_over_90_characters_long = 1usize * 200 / 2 * 500 / 1; - - { - { - { - { - { - { - { - { - { - { - { - { - { - { - { - { - println!("highly indented lines do not cause a warning (by default)!") - } - } - } - } - } - } - } - } - } - } - } - } - } - } - } - } -} diff --git a/tests/ui/excessive_width.stderr b/tests/ui/excessive_width.stderr deleted file mode 100644 index 707a3796b56..00000000000 --- a/tests/ui/excessive_width.stderr +++ /dev/null @@ -1,11 +0,0 @@ -error: this line is too long - --> $DIR/excessive_width.rs:9:5 - | -LL | let really_long_binding_name_because_this_needs_to_be_over_90_characters_long = 1usize * 200 / 2 * 500 / 1; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = help: consider running rustfmt or refactoring this - = note: `-D clippy::excessive-width` implied by `-D warnings` - -error: aborting due to previous error - From a9da61b1153edd8a8b49226ffd433e0c6a402e38 Mon Sep 17 00:00:00 2001 From: Catherine <114838443+Centri3@users.noreply.github.com> Date: Fri, 21 Apr 2023 10:59:36 -0500 Subject: [PATCH 089/310] couple more notes --- clippy_lints/src/excessive_nesting.rs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/clippy_lints/src/excessive_nesting.rs b/clippy_lints/src/excessive_nesting.rs index a60e2442fa2..604448d2e9c 100644 --- a/clippy_lints/src/excessive_nesting.rs +++ b/clippy_lints/src/excessive_nesting.rs @@ -106,6 +106,8 @@ impl<'conf, 'cx> Visitor<'_> for NestingVisitor<'conf, 'cx> { } fn visit_block(&mut self, block: &Block) { + // TODO: Can we use some RAII guard instead? Borrow checker seems to hate that + // idea but it would be a lot cleaner. self.nest_level += 1; if !check_indent(self, block.span) { @@ -167,6 +169,8 @@ impl<'conf, 'cx> Visitor<'_> for NestingVisitor<'conf, 'cx> { fn visit_expr(&mut self, expr: &Expr) { // This is a mess, but really all it does is extract every expression from every applicable variant // of ExprKind until it finds a Block. + // TODO: clippy_utils has the two functions for_each_expr and for_each_expr_with_closures, can those + // be used here or are they not applicable for this case? match &expr.kind { ExprKind::ConstBlock(anon_const) => self.visit_expr(&anon_const.value), ExprKind::Call(.., args) => { From 88143ac295ba0656b78af8f9413e4074529b42d9 Mon Sep 17 00:00:00 2001 From: Centri3 <114838443+Centri3@users.noreply.github.com> Date: Fri, 28 Apr 2023 14:22:24 -0500 Subject: [PATCH 090/310] decided against reinventing the wheel --- book/src/lint_configuration.md | 10 + clippy_lints/src/excessive_nesting.rs | 267 +++--------------- .../excessive_nesting/excessive_nesting.rs | 7 +- .../excessive_nesting.stderr | 199 +++++++------ 4 files changed, 156 insertions(+), 327 deletions(-) diff --git a/book/src/lint_configuration.md b/book/src/lint_configuration.md index 4c888b63793..4fa6b81c002 100644 --- a/book/src/lint_configuration.md +++ b/book/src/lint_configuration.md @@ -158,6 +158,16 @@ The maximum cognitive complexity a function can have * [`cognitive_complexity`](https://rust-lang.github.io/rust-clippy/master/index.html#cognitive_complexity) +## `excessive-nesting-threshold` +The maximum amount of nesting a block can reside in + +**Default Value:** `10` (`u64`) + +--- +**Affected lints:** +* [`excessive_nesting`](https://rust-lang.github.io/rust-clippy/master/index.html#excessive_nesting) + + ## `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 diff --git a/clippy_lints/src/excessive_nesting.rs b/clippy_lints/src/excessive_nesting.rs index 604448d2e9c..a133bdc2edf 100644 --- a/clippy_lints/src/excessive_nesting.rs +++ b/clippy_lints/src/excessive_nesting.rs @@ -1,16 +1,12 @@ use clippy_utils::diagnostics::span_lint_and_help; use rustc_ast::{ - node_id::NodeId, - ptr::P, - visit::{FnKind, Visitor}, - Arm, AssocItemKind, Block, Expr, ExprKind, Inline, Item, ItemKind, Local, LocalKind, ModKind, ModSpans, Pat, - PatKind, Stmt, StmtKind, + visit::{walk_block, walk_item, Visitor}, + Block, Crate, Inline, Item, ItemKind, ModKind, }; use rustc_lint::{EarlyContext, EarlyLintPass, LintContext}; use rustc_middle::lint::in_external_macro; use rustc_session::{declare_tool_lint, impl_lint_pass}; use rustc_span::Span; -use thin_vec::ThinVec; declare_clippy_lint! { /// ### What it does @@ -22,11 +18,6 @@ declare_clippy_lint! { /// It can severely hinder readability. The default is very generous; if you /// exceed this, it's a sign you should refactor. /// - /// ### Known issues - /// - /// Nested inline modules will all be linted, rather than just the outermost one - /// that applies. This makes the output a bit verbose. - /// /// ### Example /// An example clippy.toml configuration: /// ```toml @@ -74,14 +65,17 @@ pub struct ExcessiveNesting { } impl EarlyLintPass for ExcessiveNesting { - fn check_item(&mut self, cx: &EarlyContext<'_>, item: &Item) { + fn check_crate(&mut self, cx: &EarlyContext<'_>, krate: &Crate) { let conf = self; - NestingVisitor { + let mut visitor = NestingVisitor { conf, cx, nest_level: 0, + }; + + for item in &krate.items { + visitor.visit_item(item); } - .visit_item(item); } } @@ -91,239 +85,52 @@ struct NestingVisitor<'conf, 'cx> { nest_level: u64, } -impl<'conf, 'cx> Visitor<'_> for NestingVisitor<'conf, 'cx> { - fn visit_local(&mut self, local: &Local) { - self.visit_pat(&local.pat); +impl NestingVisitor<'_, '_> { + fn check_indent(&self, span: Span) -> bool { + if self.nest_level > self.conf.excessive_nesting_threshold && !in_external_macro(self.cx.sess(), span) { + span_lint_and_help( + self.cx, + EXCESSIVE_NESTING, + span, + "this block is too nested", + None, + "try refactoring your code to minimize nesting", + ); - match &local.kind { - LocalKind::Init(expr) => self.visit_expr(expr), - LocalKind::InitElse(expr, block) => { - self.visit_expr(expr); - self.visit_block(block); - }, - LocalKind::Decl => (), + return true; } - } + false + } +} + +impl<'conf, 'cx> Visitor<'_> for NestingVisitor<'conf, 'cx> { fn visit_block(&mut self, block: &Block) { - // TODO: Can we use some RAII guard instead? Borrow checker seems to hate that - // idea but it would be a lot cleaner. self.nest_level += 1; - if !check_indent(self, block.span) { - for stmt in &block.stmts { - self.visit_stmt(stmt); - } + if !self.check_indent(block.span) { + walk_block(self, block); } self.nest_level -= 1; } - fn visit_stmt(&mut self, stmt: &Stmt) { - match &stmt.kind { - StmtKind::Local(local) => self.visit_local(local), - StmtKind::Item(item) => self.visit_item(item), - StmtKind::Expr(expr) | StmtKind::Semi(expr) => self.visit_expr(expr), - _ => (), - } - } - - fn visit_arm(&mut self, arm: &Arm) { - self.visit_pat(&arm.pat); - if let Some(expr) = &arm.guard { - self.visit_expr(expr); - } - self.visit_expr(&arm.body); - } - - // TODO: Is this necessary? - fn visit_pat(&mut self, pat: &Pat) { - match &pat.kind { - PatKind::Box(pat) | PatKind::Ref(pat, ..) | PatKind::Paren(pat) => self.visit_pat(pat), - PatKind::Lit(expr) => self.visit_expr(expr), - PatKind::Range(start, end, ..) => { - if let Some(expr) = start { - self.visit_expr(expr); - } - if let Some(expr) = end { - self.visit_expr(expr); - } - }, - PatKind::Ident(.., pat) if let Some(pat) = pat => { - self.visit_pat(pat); - }, - PatKind::Struct(.., pat_fields, _) => { - for pat_field in pat_fields { - self.visit_pat(&pat_field.pat); - } - }, - PatKind::TupleStruct(.., pats) | PatKind::Or(pats) | PatKind::Tuple(pats) | PatKind::Slice(pats) => { - for pat in pats { - self.visit_pat(pat); - } - }, - _ => (), - } - } - - fn visit_expr(&mut self, expr: &Expr) { - // This is a mess, but really all it does is extract every expression from every applicable variant - // of ExprKind until it finds a Block. - // TODO: clippy_utils has the two functions for_each_expr and for_each_expr_with_closures, can those - // be used here or are they not applicable for this case? - match &expr.kind { - ExprKind::ConstBlock(anon_const) => self.visit_expr(&anon_const.value), - ExprKind::Call(.., args) => { - for expr in args { - self.visit_expr(expr); - } - }, - ExprKind::MethodCall(method_call) => { - for expr in &method_call.args { - self.visit_expr(expr); - } - }, - ExprKind::Tup(exprs) | ExprKind::Array(exprs) => { - for expr in exprs { - self.visit_expr(expr); - } - }, - ExprKind::Binary(.., left, right) - | ExprKind::Assign(left, right, ..) - | ExprKind::AssignOp(.., left, right) - | ExprKind::Index(left, right) => { - self.visit_expr(left); - self.visit_expr(right); - }, - ExprKind::Let(pat, expr, ..) => { - self.visit_pat(pat); - self.visit_expr(expr); - }, - ExprKind::Unary(.., expr) - | ExprKind::Await(expr) - | ExprKind::Field(expr, ..) - | ExprKind::AddrOf(.., expr) - | ExprKind::Try(expr) => { - self.visit_expr(expr); - }, - ExprKind::Repeat(expr, anon_const) => { - self.visit_expr(expr); - self.visit_expr(&anon_const.value); - }, - ExprKind::If(expr, block, else_expr) => { - self.visit_expr(expr); - self.visit_block(block); - - if let Some(expr) = else_expr { - self.visit_expr(expr); - } - }, - ExprKind::While(expr, block, ..) => { - self.visit_expr(expr); - self.visit_block(block); - }, - ExprKind::ForLoop(pat, expr, block, ..) => { - self.visit_pat(pat); - self.visit_expr(expr); - self.visit_block(block); - }, - ExprKind::Loop(block, ..) - | ExprKind::Block(block, ..) - | ExprKind::Async(.., block) - | ExprKind::TryBlock(block) => { - self.visit_block(block); - }, - ExprKind::Match(expr, arms) => { - self.visit_expr(expr); - - for arm in arms { - self.visit_arm(arm); - } - }, - ExprKind::Closure(closure) => self.visit_expr(&closure.body), - ExprKind::Range(start, end, ..) => { - if let Some(expr) = start { - self.visit_expr(expr); - } - if let Some(expr) = end { - self.visit_expr(expr); - } - }, - ExprKind::Break(.., expr) | ExprKind::Ret(expr) | ExprKind::Yield(expr) | ExprKind::Yeet(expr) => { - if let Some(expr) = expr { - self.visit_expr(expr); - } - }, - ExprKind::Struct(struct_expr) => { - for field in &struct_expr.fields { - self.visit_expr(&field.expr); - } - }, - _ => (), - } - } - - fn visit_fn(&mut self, fk: FnKind<'_>, _: Span, _: NodeId) { - match fk { - FnKind::Fn(.., block) if let Some(block) = block => self.visit_block(block), - FnKind::Closure(.., expr) => self.visit_expr(expr), - // :/ - FnKind::Fn(..) => (), - } - } - fn visit_item(&mut self, item: &Item) { match &item.kind { - ItemKind::Static(static_item) if let Some(expr) = static_item.expr.as_ref() => self.visit_expr(expr), - ItemKind::Const(const_item) if let Some(expr) = const_item.expr.as_ref() => self.visit_expr(expr), - ItemKind::Fn(fk) if let Some(block) = fk.body.as_ref() => self.visit_block(block), - ItemKind::Mod(.., mod_kind) - if let ModKind::Loaded(items, Inline::Yes, ModSpans { inner_span, ..}) = mod_kind => - { + ItemKind::Trait(_) | ItemKind::Impl(_) | ItemKind::Mod(.., ModKind::Loaded(_, Inline::Yes, _)) => { self.nest_level += 1; - check_indent(self, *inner_span); + if !self.check_indent(item.span) { + walk_item(self, item); + } self.nest_level -= 1; - } - ItemKind::Trait(trit) => check_trait_and_impl(self, item, &trit.items), - ItemKind::Impl(imp) => check_trait_and_impl(self, item, &imp.items), - _ => (), + }, + // Mod: Don't visit non-inline modules + // ForeignMod: I don't think this is necessary, but just incase let's not take any chances (don't want to + // cause any false positives) + ItemKind::Mod(..) | ItemKind::ForeignMod(..) => {}, + _ => walk_item(self, item), } } } - -fn check_trait_and_impl(visitor: &mut NestingVisitor<'_, '_>, item: &Item, items: &ThinVec>>) { - visitor.nest_level += 1; - - if !check_indent(visitor, item.span) { - for item in items { - match &item.kind { - AssocItemKind::Const(const_item) if let Some(expr) = const_item.expr.as_ref() => { - visitor.visit_expr(expr); - }, - AssocItemKind::Fn(fk) if let Some(block) = fk.body.as_ref() => visitor.visit_block(block), - _ => (), - } - } - } - - visitor.nest_level -= 1; -} - -fn check_indent(visitor: &NestingVisitor<'_, '_>, span: Span) -> bool { - if visitor.nest_level > visitor.conf.excessive_nesting_threshold && !in_external_macro(visitor.cx.sess(), span) { - span_lint_and_help( - visitor.cx, - EXCESSIVE_NESTING, - span, - "this block is too nested", - None, - "try refactoring your code, extraction is often both easier to read and less nested", - ); - - return true; - } - - false -} diff --git a/tests/ui-toml/excessive_nesting/excessive_nesting.rs b/tests/ui-toml/excessive_nesting/excessive_nesting.rs index 66fc8166314..62cf5125816 100644 --- a/tests/ui-toml/excessive_nesting/excessive_nesting.rs +++ b/tests/ui-toml/excessive_nesting/excessive_nesting.rs @@ -77,7 +77,7 @@ trait Lol { fn lmao() { fn bb() { fn cc() { - let x = { 1 }; // not a warning + let x = { 1 }; // not a warning, but cc is } let x = { 1 }; // warning @@ -93,8 +93,8 @@ pub mod a { pub mod d { pub mod e { pub mod f {} - } - } + } // not here + } // only warning should be here } } } @@ -139,6 +139,7 @@ fn main() { let boo = true; !{boo as u32 + !{boo as u32 + !{boo as u32}}}; + // this is a mess, but that's intentional let mut y = 1; y += {{{{{5}}}}}; let z = y + {{{{{{{{{5}}}}}}}}}; diff --git a/tests/ui-toml/excessive_nesting/excessive_nesting.stderr b/tests/ui-toml/excessive_nesting/excessive_nesting.stderr index 0bd43da21e2..c98c6fefe01 100644 --- a/tests/ui-toml/excessive_nesting/excessive_nesting.stderr +++ b/tests/ui-toml/excessive_nesting/excessive_nesting.stderr @@ -8,7 +8,7 @@ LL | | w LL | | }; | |_____________^ | - = help: try refactoring your code, extraction is often both easier to read and less nested + = help: try refactoring your code to minimize nesting = note: `-D clippy::excessive-nesting` implied by `-D warnings` error: this block is too nested @@ -24,26 +24,18 @@ LL | | } LL | | } | |_____________^ | - = help: try refactoring your code, extraction is often both easier to read and less nested - -error: this block is too nested - --> $DIR/excessive_nesting.rs:67:32 - | -LL | pub fn c() {} - | ^^ - | - = help: try refactoring your code, extraction is often both easier to read and less nested + = help: try refactoring your code to minimize nesting error: this block is too nested --> $DIR/excessive_nesting.rs:79:21 | LL | fn cc() { | _____________________^ -LL | | let x = { 1 }; // not a warning +LL | | let x = { 1 }; // not a warning, but cc is LL | | } | |_____________^ | - = help: try refactoring your code, extraction is often both easier to read and less nested + = help: try refactoring your code to minimize nesting error: this block is too nested --> $DIR/excessive_nesting.rs:83:21 @@ -51,7 +43,19 @@ error: this block is too nested LL | let x = { 1 }; // warning | ^^^^^ | - = help: try refactoring your code, extraction is often both easier to read and less nested + = help: try refactoring your code to minimize nesting + +error: this block is too nested + --> $DIR/excessive_nesting.rs:93:13 + | +LL | / pub mod d { +LL | | pub mod e { +LL | | pub mod f {} +LL | | } // not here +LL | | } // only warning should be here + | |_____________^ + | + = help: try refactoring your code to minimize nesting error: this block is too nested --> $DIR/excessive_nesting.rs:107:17 @@ -59,7 +63,7 @@ error: this block is too nested LL | a_but_not({{{{{{{{0}}}}}}}}); | ^^^^^^^^^^^^^ | - = help: try refactoring your code, extraction is often both easier to read and less nested + = help: try refactoring your code to minimize nesting error: this block is too nested --> $DIR/excessive_nesting.rs:108:11 @@ -67,7 +71,7 @@ error: this block is too nested LL | a.a({{{{{{{{{0}}}}}}}}}); | ^^^^^^^^^^^^^^^ | - = help: try refactoring your code, extraction is often both easier to read and less nested + = help: try refactoring your code to minimize nesting error: this block is too nested --> $DIR/excessive_nesting.rs:109:11 @@ -75,7 +79,7 @@ error: this block is too nested LL | (0, {{{{{{{1}}}}}}}); | ^^^^^^^^^^^ | - = help: try refactoring your code, extraction is often both easier to read and less nested + = help: try refactoring your code to minimize nesting error: this block is too nested --> $DIR/excessive_nesting.rs:113:21 @@ -90,7 +94,22 @@ LL | | } LL | | } | |_____________^ | - = help: try refactoring your code, extraction is often both easier to read and less nested + = help: try refactoring your code to minimize nesting + +error: this block is too nested + --> $DIR/excessive_nesting.rs:125:25 + | +LL | let y = (|| { + | _________________________^ +LL | | let z = (|| { +LL | | let w = { 3 }; +LL | | w +LL | | })(); +LL | | z +LL | | })(); + | |_____________^ + | + = help: try refactoring your code to minimize nesting error: this block is too nested --> $DIR/excessive_nesting.rs:33:13 @@ -107,7 +126,7 @@ LL | | } LL | xx!(); | ----- in this macro invocation | - = help: try refactoring your code, extraction is often both easier to read and less nested + = help: try refactoring your code to minimize nesting = note: this error originates in the macro `xx` (in Nightly builds, run with -Z macro-backtrace for more info) error: this block is too nested @@ -116,210 +135,210 @@ error: this block is too nested LL | !{boo as u32 + !{boo as u32 + !{boo as u32}}}; | ^^^^^^^^^^^^ | - = help: try refactoring your code, extraction is often both easier to read and less nested + = help: try refactoring your code to minimize nesting error: this block is too nested - --> $DIR/excessive_nesting.rs:143:12 + --> $DIR/excessive_nesting.rs:144:12 | LL | y += {{{{{5}}}}}; | ^^^^^^^ | - = help: try refactoring your code, extraction is often both easier to read and less nested + = help: try refactoring your code to minimize nesting error: this block is too nested - --> $DIR/excessive_nesting.rs:144:19 + --> $DIR/excessive_nesting.rs:145:19 | LL | let z = y + {{{{{{{{{5}}}}}}}}}; | ^^^^^^^^^^^^^^^ | - = help: try refactoring your code, extraction is often both easier to read and less nested + = help: try refactoring your code to minimize nesting error: this block is too nested - --> $DIR/excessive_nesting.rs:145:11 + --> $DIR/excessive_nesting.rs:146:11 | LL | [0, {{{{{{{{{{0}}}}}}}}}}]; | ^^^^^^^^^^^^^^^^^ | - = help: try refactoring your code, extraction is often both easier to read and less nested + = help: try refactoring your code to minimize nesting error: this block is too nested - --> $DIR/excessive_nesting.rs:146:24 + --> $DIR/excessive_nesting.rs:147:24 | LL | let mut xx = [0; {{{{{{{{100}}}}}}}}]; | ^^^^^^^^^^^^^^^ | - = help: try refactoring your code, extraction is often both easier to read and less nested + = help: try refactoring your code to minimize nesting error: this block is too nested - --> $DIR/excessive_nesting.rs:147:10 + --> $DIR/excessive_nesting.rs:148:10 | LL | xx[{{{{{{{{{{{{{{{{{{{{{{{{3}}}}}}}}}}}}}}}}}}}}}}}}]; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | - = help: try refactoring your code, extraction is often both easier to read and less nested + = help: try refactoring your code to minimize nesting error: this block is too nested - --> $DIR/excessive_nesting.rs:148:12 + --> $DIR/excessive_nesting.rs:149:12 | LL | &mut {{{{{{{{{{y}}}}}}}}}}; | ^^^^^^^^^^^^^^^^^ | - = help: try refactoring your code, extraction is often both easier to read and less nested + = help: try refactoring your code to minimize nesting error: this block is too nested - --> $DIR/excessive_nesting.rs:150:16 + --> $DIR/excessive_nesting.rs:151:16 | LL | for i in {{{{xx}}}} {{{{{{{{}}}}}}}} | ^^^^^^ | - = help: try refactoring your code, extraction is often both easier to read and less nested + = help: try refactoring your code to minimize nesting error: this block is too nested - --> $DIR/excessive_nesting.rs:150:27 + --> $DIR/excessive_nesting.rs:151:27 | LL | for i in {{{{xx}}}} {{{{{{{{}}}}}}}} | ^^^^^^^^^^^^ | - = help: try refactoring your code, extraction is often both easier to read and less nested + = help: try refactoring your code to minimize nesting error: this block is too nested - --> $DIR/excessive_nesting.rs:152:27 + --> $DIR/excessive_nesting.rs:153:27 | LL | while let Some(i) = {{{{{{Some(1)}}}}}} {{{{{{{}}}}}}} | ^^^^^^^^^^^^^^^ | - = help: try refactoring your code, extraction is often both easier to read and less nested + = help: try refactoring your code to minimize nesting error: this block is too nested - --> $DIR/excessive_nesting.rs:152:47 + --> $DIR/excessive_nesting.rs:153:47 | LL | while let Some(i) = {{{{{{Some(1)}}}}}} {{{{{{{}}}}}}} | ^^^^^^^^^^ | - = help: try refactoring your code, extraction is often both easier to read and less nested + = help: try refactoring your code to minimize nesting error: this block is too nested - --> $DIR/excessive_nesting.rs:154:13 + --> $DIR/excessive_nesting.rs:155:13 | LL | while {{{{{{{{true}}}}}}}} {{{{{{{{{}}}}}}}}} | ^^^^^^^^^^^^^^^^ | - = help: try refactoring your code, extraction is often both easier to read and less nested + = help: try refactoring your code to minimize nesting error: this block is too nested - --> $DIR/excessive_nesting.rs:154:34 + --> $DIR/excessive_nesting.rs:155:34 | LL | while {{{{{{{{true}}}}}}}} {{{{{{{{{}}}}}}}}} | ^^^^^^^^^^^^^^ | - = help: try refactoring your code, extraction is often both easier to read and less nested + = help: try refactoring your code to minimize nesting error: this block is too nested - --> $DIR/excessive_nesting.rs:156:22 + --> $DIR/excessive_nesting.rs:157:22 | LL | let d = D { d: {{{{{{{{{{{{{{{{{{{{{{{3}}}}}}}}}}}}}}}}}}}}}}} }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | - = help: try refactoring your code, extraction is often both easier to read and less nested - -error: this block is too nested - --> $DIR/excessive_nesting.rs:158:7 - | -LL | {{{{1;}}}}..{{{{{{3}}}}}}; - | ^^^^^^ - | - = help: try refactoring your code, extraction is often both easier to read and less nested - -error: this block is too nested - --> $DIR/excessive_nesting.rs:158:19 - | -LL | {{{{1;}}}}..{{{{{{3}}}}}}; - | ^^^^^^^^^ - | - = help: try refactoring your code, extraction is often both easier to read and less nested + = help: try refactoring your code to minimize nesting error: this block is too nested --> $DIR/excessive_nesting.rs:159:7 | +LL | {{{{1;}}}}..{{{{{{3}}}}}}; + | ^^^^^^ + | + = help: try refactoring your code to minimize nesting + +error: this block is too nested + --> $DIR/excessive_nesting.rs:159:19 + | +LL | {{{{1;}}}}..{{{{{{3}}}}}}; + | ^^^^^^^^^ + | + = help: try refactoring your code to minimize nesting + +error: this block is too nested + --> $DIR/excessive_nesting.rs:160:7 + | LL | {{{{1;}}}}..={{{{{{{{{{{{{{{{{{{{{{{{{{6}}}}}}}}}}}}}}}}}}}}}}}}}}; | ^^^^^^ | - = help: try refactoring your code, extraction is often both easier to read and less nested + = help: try refactoring your code to minimize nesting error: this block is too nested - --> $DIR/excessive_nesting.rs:159:20 + --> $DIR/excessive_nesting.rs:160:20 | LL | {{{{1;}}}}..={{{{{{{{{{{{{{{{{{{{{{{{{{6}}}}}}}}}}}}}}}}}}}}}}}}}}; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | - = help: try refactoring your code, extraction is often both easier to read and less nested + = help: try refactoring your code to minimize nesting error: this block is too nested - --> $DIR/excessive_nesting.rs:160:9 + --> $DIR/excessive_nesting.rs:161:9 | LL | ..{{{{{{{5}}}}}}}; | ^^^^^^^^^^^ | - = help: try refactoring your code, extraction is often both easier to read and less nested + = help: try refactoring your code to minimize nesting error: this block is too nested - --> $DIR/excessive_nesting.rs:161:10 + --> $DIR/excessive_nesting.rs:162:10 | LL | ..={{{{{3}}}}}; | ^^^^^^^ | - = help: try refactoring your code, extraction is often both easier to read and less nested + = help: try refactoring your code to minimize nesting error: this block is too nested - --> $DIR/excessive_nesting.rs:162:7 + --> $DIR/excessive_nesting.rs:163:7 | LL | {{{{{1;}}}}}..; | ^^^^^^^^ | - = help: try refactoring your code, extraction is often both easier to read and less nested + = help: try refactoring your code to minimize nesting error: this block is too nested - --> $DIR/excessive_nesting.rs:164:19 + --> $DIR/excessive_nesting.rs:165:19 | LL | loop { break {{{{1}}}} }; | ^^^^^^^ | - = help: try refactoring your code, extraction is often both easier to read and less nested + = help: try refactoring your code to minimize nesting error: this block is too nested - --> $DIR/excessive_nesting.rs:165:12 + --> $DIR/excessive_nesting.rs:166:12 | LL | loop {{{{{{}}}}}} | ^^^^^^^^ | - = help: try refactoring your code, extraction is often both easier to read and less nested + = help: try refactoring your code to minimize nesting error: this block is too nested - --> $DIR/excessive_nesting.rs:167:13 + --> $DIR/excessive_nesting.rs:168:13 | LL | match {{{{{{true}}}}}} { | ^^^^^^^^^^^^ | - = help: try refactoring your code, extraction is often both easier to read and less nested + = help: try refactoring your code to minimize nesting error: this block is too nested - --> $DIR/excessive_nesting.rs:168:19 + --> $DIR/excessive_nesting.rs:169:19 | LL | true => {{{{}}}}, | ^^^^ | - = help: try refactoring your code, extraction is often both easier to read and less nested + = help: try refactoring your code to minimize nesting error: this block is too nested - --> $DIR/excessive_nesting.rs:169:20 + --> $DIR/excessive_nesting.rs:170:20 | LL | false => {{{{}}}}, | ^^^^ | - = help: try refactoring your code, extraction is often both easier to read and less nested + = help: try refactoring your code to minimize nesting error: this block is too nested - --> $DIR/excessive_nesting.rs:174:13 + --> $DIR/excessive_nesting.rs:175:13 | LL | / { LL | | { @@ -328,31 +347,23 @@ LL | | } LL | | } | |_____________^ | - = help: try refactoring your code, extraction is often both easier to read and less nested + = help: try refactoring your code to minimize nesting error: this block is too nested - --> $DIR/excessive_nesting.rs:184:27 + --> $DIR/excessive_nesting.rs:185:27 | LL | async fn c() -> u32 {{{{{{{0}}}}}}} | ^^^^^^^^^^^ | - = help: try refactoring your code, extraction is often both easier to read and less nested + = help: try refactoring your code to minimize nesting error: this block is too nested - --> $DIR/excessive_nesting.rs:184:28 - | -LL | async fn c() -> u32 {{{{{{{0}}}}}}} - | ^^^^^^^^^ - | - = help: try refactoring your code, extraction is often both easier to read and less nested - -error: this block is too nested - --> $DIR/excessive_nesting.rs:190:7 + --> $DIR/excessive_nesting.rs:191:7 | LL | {{{{b().await}}}}; | ^^^^^^^^^^^^^ | - = help: try refactoring your code, extraction is often both easier to read and less nested + = help: try refactoring your code to minimize nesting error: aborting due to 40 previous errors From 493a23e957f9d639c13bddb19937bd19cbc6cfe2 Mon Sep 17 00:00:00 2001 From: Centri3 <114838443+Centri3@users.noreply.github.com> Date: Sat, 6 May 2023 18:43:53 -0500 Subject: [PATCH 091/310] check non-inline modules, ignore all macros --- clippy_lints/src/excessive_nesting.rs | 24 +++- .../excessive_nesting/auxiliary/mod.rs | 16 +++ .../excessive_nesting/excessive_nesting.rs | 6 +- .../excessive_nesting.stderr | 118 +++++++++--------- 4 files changed, 98 insertions(+), 66 deletions(-) create mode 100644 tests/ui-toml/excessive_nesting/auxiliary/mod.rs diff --git a/clippy_lints/src/excessive_nesting.rs b/clippy_lints/src/excessive_nesting.rs index a133bdc2edf..5ade713f816 100644 --- a/clippy_lints/src/excessive_nesting.rs +++ b/clippy_lints/src/excessive_nesting.rs @@ -11,7 +11,7 @@ use rustc_span::Span; declare_clippy_lint! { /// ### What it does /// - /// Checks for blocks which are indented beyond a certain threshold. + /// Checks for blocks which are nested beyond a certain threshold. /// /// ### Why is this bad? /// @@ -106,6 +106,11 @@ impl NestingVisitor<'_, '_> { impl<'conf, 'cx> Visitor<'_> for NestingVisitor<'conf, 'cx> { fn visit_block(&mut self, block: &Block) { + // TODO: Probably not necessary, since any block would already be ignored by the check in visit_item + if block.span.from_expansion() { + return; + } + self.nest_level += 1; if !self.check_indent(block.span) { @@ -116,6 +121,10 @@ impl<'conf, 'cx> Visitor<'_> for NestingVisitor<'conf, 'cx> { } fn visit_item(&mut self, item: &Item) { + if item.span.from_expansion() { + return; + } + match &item.kind { ItemKind::Trait(_) | ItemKind::Impl(_) | ItemKind::Mod(.., ModKind::Loaded(_, Inline::Yes, _)) => { self.nest_level += 1; @@ -126,10 +135,15 @@ impl<'conf, 'cx> Visitor<'_> for NestingVisitor<'conf, 'cx> { self.nest_level -= 1; }, - // Mod: Don't visit non-inline modules - // ForeignMod: I don't think this is necessary, but just incase let's not take any chances (don't want to - // cause any false positives) - ItemKind::Mod(..) | ItemKind::ForeignMod(..) => {}, + // Reset nesting level for non-inline modules (since these are in another file) + ItemKind::Mod(..) => walk_item( + &mut NestingVisitor { + conf: self.conf, + cx: self.cx, + nest_level: 0, + }, + item, + ), _ => walk_item(self, item), } } diff --git a/tests/ui-toml/excessive_nesting/auxiliary/mod.rs b/tests/ui-toml/excessive_nesting/auxiliary/mod.rs new file mode 100644 index 00000000000..967b3af3bca --- /dev/null +++ b/tests/ui-toml/excessive_nesting/auxiliary/mod.rs @@ -0,0 +1,16 @@ +#![rustfmt::skip] + +mod a { + mod b { + mod c { + mod d { + mod e {} + } + } + } +} + +fn main() { + // this should lint + {{{}}} +} diff --git a/tests/ui-toml/excessive_nesting/excessive_nesting.rs b/tests/ui-toml/excessive_nesting/excessive_nesting.rs index 62cf5125816..3e3ac7c923a 100644 --- a/tests/ui-toml/excessive_nesting/excessive_nesting.rs +++ b/tests/ui-toml/excessive_nesting/excessive_nesting.rs @@ -10,6 +10,8 @@ #![warn(clippy::excessive_nesting)] #![allow(clippy::collapsible_if)] +mod auxiliary; + #[macro_use] extern crate macro_rules; @@ -39,7 +41,7 @@ macro_rules! xx { { { { - println!("ehe"); + println!("ehe"); // should not lint } } } @@ -135,7 +137,7 @@ fn main() { })(); excessive_nesting!(); // ensure this isn't linted in external macros - xx!(); + xx!(); // ensure this is never linted let boo = true; !{boo as u32 + !{boo as u32 + !{boo as u32}}}; diff --git a/tests/ui-toml/excessive_nesting/excessive_nesting.stderr b/tests/ui-toml/excessive_nesting/excessive_nesting.stderr index c98c6fefe01..524282d11f7 100644 --- a/tests/ui-toml/excessive_nesting/excessive_nesting.stderr +++ b/tests/ui-toml/excessive_nesting/excessive_nesting.stderr @@ -1,5 +1,24 @@ error: this block is too nested - --> $DIR/excessive_nesting.rs:19:21 + --> $DIR/auxiliary/mod.rs:6:13 + | +LL | / mod d { +LL | | mod e {} +LL | | } + | |_____________^ + | + = help: try refactoring your code to minimize nesting + = note: `-D clippy::excessive-nesting` implied by `-D warnings` + +error: this block is too nested + --> $DIR/auxiliary/mod.rs:15:7 + | +LL | {{{}}} + | ^^ + | + = help: try refactoring your code to minimize nesting + +error: this block is too nested + --> $DIR/excessive_nesting.rs:21:21 | LL | let z = { | _____________________^ @@ -9,10 +28,9 @@ LL | | }; | |_____________^ | = help: try refactoring your code to minimize nesting - = note: `-D clippy::excessive-nesting` implied by `-D warnings` error: this block is too nested - --> $DIR/excessive_nesting.rs:63:24 + --> $DIR/excessive_nesting.rs:65:24 | LL | pub fn b() { | ________________________^ @@ -27,7 +45,7 @@ LL | | } = help: try refactoring your code to minimize nesting error: this block is too nested - --> $DIR/excessive_nesting.rs:79:21 + --> $DIR/excessive_nesting.rs:81:21 | LL | fn cc() { | _____________________^ @@ -38,7 +56,7 @@ LL | | } = help: try refactoring your code to minimize nesting error: this block is too nested - --> $DIR/excessive_nesting.rs:83:21 + --> $DIR/excessive_nesting.rs:85:21 | LL | let x = { 1 }; // warning | ^^^^^ @@ -46,7 +64,7 @@ LL | let x = { 1 }; // warning = help: try refactoring your code to minimize nesting error: this block is too nested - --> $DIR/excessive_nesting.rs:93:13 + --> $DIR/excessive_nesting.rs:95:13 | LL | / pub mod d { LL | | pub mod e { @@ -58,7 +76,7 @@ LL | | } // only warning should be here = help: try refactoring your code to minimize nesting error: this block is too nested - --> $DIR/excessive_nesting.rs:107:17 + --> $DIR/excessive_nesting.rs:109:17 | LL | a_but_not({{{{{{{{0}}}}}}}}); | ^^^^^^^^^^^^^ @@ -66,7 +84,7 @@ LL | a_but_not({{{{{{{{0}}}}}}}}); = help: try refactoring your code to minimize nesting error: this block is too nested - --> $DIR/excessive_nesting.rs:108:11 + --> $DIR/excessive_nesting.rs:110:11 | LL | a.a({{{{{{{{{0}}}}}}}}}); | ^^^^^^^^^^^^^^^ @@ -74,7 +92,7 @@ LL | a.a({{{{{{{{{0}}}}}}}}}); = help: try refactoring your code to minimize nesting error: this block is too nested - --> $DIR/excessive_nesting.rs:109:11 + --> $DIR/excessive_nesting.rs:111:11 | LL | (0, {{{{{{{1}}}}}}}); | ^^^^^^^^^^^ @@ -82,7 +100,7 @@ LL | (0, {{{{{{{1}}}}}}}); = help: try refactoring your code to minimize nesting error: this block is too nested - --> $DIR/excessive_nesting.rs:113:21 + --> $DIR/excessive_nesting.rs:115:21 | LL | if true { | _____________________^ @@ -97,7 +115,7 @@ LL | | } = help: try refactoring your code to minimize nesting error: this block is too nested - --> $DIR/excessive_nesting.rs:125:25 + --> $DIR/excessive_nesting.rs:127:25 | LL | let y = (|| { | _________________________^ @@ -112,25 +130,7 @@ LL | | })(); = help: try refactoring your code to minimize nesting error: this block is too nested - --> $DIR/excessive_nesting.rs:33:13 - | -LL | / { -LL | | { -LL | | { -LL | | { -... | -LL | | } -LL | | } - | |_____________^ -... -LL | xx!(); - | ----- in this macro invocation - | - = help: try refactoring your code to minimize nesting - = note: this error originates in the macro `xx` (in Nightly builds, run with -Z macro-backtrace for more info) - -error: this block is too nested - --> $DIR/excessive_nesting.rs:140:36 + --> $DIR/excessive_nesting.rs:142:36 | LL | !{boo as u32 + !{boo as u32 + !{boo as u32}}}; | ^^^^^^^^^^^^ @@ -138,7 +138,7 @@ LL | !{boo as u32 + !{boo as u32 + !{boo as u32}}}; = help: try refactoring your code to minimize nesting error: this block is too nested - --> $DIR/excessive_nesting.rs:144:12 + --> $DIR/excessive_nesting.rs:146:12 | LL | y += {{{{{5}}}}}; | ^^^^^^^ @@ -146,7 +146,7 @@ LL | y += {{{{{5}}}}}; = help: try refactoring your code to minimize nesting error: this block is too nested - --> $DIR/excessive_nesting.rs:145:19 + --> $DIR/excessive_nesting.rs:147:19 | LL | let z = y + {{{{{{{{{5}}}}}}}}}; | ^^^^^^^^^^^^^^^ @@ -154,7 +154,7 @@ LL | let z = y + {{{{{{{{{5}}}}}}}}}; = help: try refactoring your code to minimize nesting error: this block is too nested - --> $DIR/excessive_nesting.rs:146:11 + --> $DIR/excessive_nesting.rs:148:11 | LL | [0, {{{{{{{{{{0}}}}}}}}}}]; | ^^^^^^^^^^^^^^^^^ @@ -162,7 +162,7 @@ LL | [0, {{{{{{{{{{0}}}}}}}}}}]; = help: try refactoring your code to minimize nesting error: this block is too nested - --> $DIR/excessive_nesting.rs:147:24 + --> $DIR/excessive_nesting.rs:149:24 | LL | let mut xx = [0; {{{{{{{{100}}}}}}}}]; | ^^^^^^^^^^^^^^^ @@ -170,7 +170,7 @@ LL | let mut xx = [0; {{{{{{{{100}}}}}}}}]; = help: try refactoring your code to minimize nesting error: this block is too nested - --> $DIR/excessive_nesting.rs:148:10 + --> $DIR/excessive_nesting.rs:150:10 | LL | xx[{{{{{{{{{{{{{{{{{{{{{{{{3}}}}}}}}}}}}}}}}}}}}}}}}]; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -178,7 +178,7 @@ LL | xx[{{{{{{{{{{{{{{{{{{{{{{{{3}}}}}}}}}}}}}}}}}}}}}}}}]; = help: try refactoring your code to minimize nesting error: this block is too nested - --> $DIR/excessive_nesting.rs:149:12 + --> $DIR/excessive_nesting.rs:151:12 | LL | &mut {{{{{{{{{{y}}}}}}}}}}; | ^^^^^^^^^^^^^^^^^ @@ -186,7 +186,7 @@ LL | &mut {{{{{{{{{{y}}}}}}}}}}; = help: try refactoring your code to minimize nesting error: this block is too nested - --> $DIR/excessive_nesting.rs:151:16 + --> $DIR/excessive_nesting.rs:153:16 | LL | for i in {{{{xx}}}} {{{{{{{{}}}}}}}} | ^^^^^^ @@ -194,7 +194,7 @@ LL | for i in {{{{xx}}}} {{{{{{{{}}}}}}}} = help: try refactoring your code to minimize nesting error: this block is too nested - --> $DIR/excessive_nesting.rs:151:27 + --> $DIR/excessive_nesting.rs:153:27 | LL | for i in {{{{xx}}}} {{{{{{{{}}}}}}}} | ^^^^^^^^^^^^ @@ -202,7 +202,7 @@ LL | for i in {{{{xx}}}} {{{{{{{{}}}}}}}} = help: try refactoring your code to minimize nesting error: this block is too nested - --> $DIR/excessive_nesting.rs:153:27 + --> $DIR/excessive_nesting.rs:155:27 | LL | while let Some(i) = {{{{{{Some(1)}}}}}} {{{{{{{}}}}}}} | ^^^^^^^^^^^^^^^ @@ -210,7 +210,7 @@ LL | while let Some(i) = {{{{{{Some(1)}}}}}} {{{{{{{}}}}}}} = help: try refactoring your code to minimize nesting error: this block is too nested - --> $DIR/excessive_nesting.rs:153:47 + --> $DIR/excessive_nesting.rs:155:47 | LL | while let Some(i) = {{{{{{Some(1)}}}}}} {{{{{{{}}}}}}} | ^^^^^^^^^^ @@ -218,7 +218,7 @@ LL | while let Some(i) = {{{{{{Some(1)}}}}}} {{{{{{{}}}}}}} = help: try refactoring your code to minimize nesting error: this block is too nested - --> $DIR/excessive_nesting.rs:155:13 + --> $DIR/excessive_nesting.rs:157:13 | LL | while {{{{{{{{true}}}}}}}} {{{{{{{{{}}}}}}}}} | ^^^^^^^^^^^^^^^^ @@ -226,7 +226,7 @@ LL | while {{{{{{{{true}}}}}}}} {{{{{{{{{}}}}}}}}} = help: try refactoring your code to minimize nesting error: this block is too nested - --> $DIR/excessive_nesting.rs:155:34 + --> $DIR/excessive_nesting.rs:157:34 | LL | while {{{{{{{{true}}}}}}}} {{{{{{{{{}}}}}}}}} | ^^^^^^^^^^^^^^ @@ -234,7 +234,7 @@ LL | while {{{{{{{{true}}}}}}}} {{{{{{{{{}}}}}}}}} = help: try refactoring your code to minimize nesting error: this block is too nested - --> $DIR/excessive_nesting.rs:157:22 + --> $DIR/excessive_nesting.rs:159:22 | LL | let d = D { d: {{{{{{{{{{{{{{{{{{{{{{{3}}}}}}}}}}}}}}}}}}}}}}} }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -242,7 +242,7 @@ LL | let d = D { d: {{{{{{{{{{{{{{{{{{{{{{{3}}}}}}}}}}}}}}}}}}}}}}} }; = help: try refactoring your code to minimize nesting error: this block is too nested - --> $DIR/excessive_nesting.rs:159:7 + --> $DIR/excessive_nesting.rs:161:7 | LL | {{{{1;}}}}..{{{{{{3}}}}}}; | ^^^^^^ @@ -250,7 +250,7 @@ LL | {{{{1;}}}}..{{{{{{3}}}}}}; = help: try refactoring your code to minimize nesting error: this block is too nested - --> $DIR/excessive_nesting.rs:159:19 + --> $DIR/excessive_nesting.rs:161:19 | LL | {{{{1;}}}}..{{{{{{3}}}}}}; | ^^^^^^^^^ @@ -258,7 +258,7 @@ LL | {{{{1;}}}}..{{{{{{3}}}}}}; = help: try refactoring your code to minimize nesting error: this block is too nested - --> $DIR/excessive_nesting.rs:160:7 + --> $DIR/excessive_nesting.rs:162:7 | LL | {{{{1;}}}}..={{{{{{{{{{{{{{{{{{{{{{{{{{6}}}}}}}}}}}}}}}}}}}}}}}}}}; | ^^^^^^ @@ -266,7 +266,7 @@ LL | {{{{1;}}}}..={{{{{{{{{{{{{{{{{{{{{{{{{{6}}}}}}}}}}}}}}}}}}}}}}}}}}; = help: try refactoring your code to minimize nesting error: this block is too nested - --> $DIR/excessive_nesting.rs:160:20 + --> $DIR/excessive_nesting.rs:162:20 | LL | {{{{1;}}}}..={{{{{{{{{{{{{{{{{{{{{{{{{{6}}}}}}}}}}}}}}}}}}}}}}}}}}; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -274,7 +274,7 @@ LL | {{{{1;}}}}..={{{{{{{{{{{{{{{{{{{{{{{{{{6}}}}}}}}}}}}}}}}}}}}}}}}}}; = help: try refactoring your code to minimize nesting error: this block is too nested - --> $DIR/excessive_nesting.rs:161:9 + --> $DIR/excessive_nesting.rs:163:9 | LL | ..{{{{{{{5}}}}}}}; | ^^^^^^^^^^^ @@ -282,7 +282,7 @@ LL | ..{{{{{{{5}}}}}}}; = help: try refactoring your code to minimize nesting error: this block is too nested - --> $DIR/excessive_nesting.rs:162:10 + --> $DIR/excessive_nesting.rs:164:10 | LL | ..={{{{{3}}}}}; | ^^^^^^^ @@ -290,7 +290,7 @@ LL | ..={{{{{3}}}}}; = help: try refactoring your code to minimize nesting error: this block is too nested - --> $DIR/excessive_nesting.rs:163:7 + --> $DIR/excessive_nesting.rs:165:7 | LL | {{{{{1;}}}}}..; | ^^^^^^^^ @@ -298,7 +298,7 @@ LL | {{{{{1;}}}}}..; = help: try refactoring your code to minimize nesting error: this block is too nested - --> $DIR/excessive_nesting.rs:165:19 + --> $DIR/excessive_nesting.rs:167:19 | LL | loop { break {{{{1}}}} }; | ^^^^^^^ @@ -306,7 +306,7 @@ LL | loop { break {{{{1}}}} }; = help: try refactoring your code to minimize nesting error: this block is too nested - --> $DIR/excessive_nesting.rs:166:12 + --> $DIR/excessive_nesting.rs:168:12 | LL | loop {{{{{{}}}}}} | ^^^^^^^^ @@ -314,7 +314,7 @@ LL | loop {{{{{{}}}}}} = help: try refactoring your code to minimize nesting error: this block is too nested - --> $DIR/excessive_nesting.rs:168:13 + --> $DIR/excessive_nesting.rs:170:13 | LL | match {{{{{{true}}}}}} { | ^^^^^^^^^^^^ @@ -322,7 +322,7 @@ LL | match {{{{{{true}}}}}} { = help: try refactoring your code to minimize nesting error: this block is too nested - --> $DIR/excessive_nesting.rs:169:19 + --> $DIR/excessive_nesting.rs:171:19 | LL | true => {{{{}}}}, | ^^^^ @@ -330,7 +330,7 @@ LL | true => {{{{}}}}, = help: try refactoring your code to minimize nesting error: this block is too nested - --> $DIR/excessive_nesting.rs:170:20 + --> $DIR/excessive_nesting.rs:172:20 | LL | false => {{{{}}}}, | ^^^^ @@ -338,7 +338,7 @@ LL | false => {{{{}}}}, = help: try refactoring your code to minimize nesting error: this block is too nested - --> $DIR/excessive_nesting.rs:175:13 + --> $DIR/excessive_nesting.rs:177:13 | LL | / { LL | | { @@ -350,7 +350,7 @@ LL | | } = help: try refactoring your code to minimize nesting error: this block is too nested - --> $DIR/excessive_nesting.rs:185:27 + --> $DIR/excessive_nesting.rs:187:27 | LL | async fn c() -> u32 {{{{{{{0}}}}}}} | ^^^^^^^^^^^ @@ -358,12 +358,12 @@ LL | async fn c() -> u32 {{{{{{{0}}}}}}} = help: try refactoring your code to minimize nesting error: this block is too nested - --> $DIR/excessive_nesting.rs:191:7 + --> $DIR/excessive_nesting.rs:193:7 | LL | {{{{b().await}}}}; | ^^^^^^^^^^^^^ | = help: try refactoring your code to minimize nesting -error: aborting due to 40 previous errors +error: aborting due to 41 previous errors From 378d77584acdd4864bf495ce67c932c0f422e6f4 Mon Sep 17 00:00:00 2001 From: Centri3 <114838443+Centri3@users.noreply.github.com> Date: Mon, 15 May 2023 15:22:59 -0500 Subject: [PATCH 092/310] work with lint attributes --- clippy_lints/src/excessive_nesting.rs | 54 ++- clippy_lints/src/lib.rs | 1 + .../excessive_nesting/{ => below}/clippy.toml | 0 .../excessive_nesting/default/clippy.toml | 1 + .../excessive_nesting.below.stderr | 369 ++++++++++++++++++ .../excessive_nesting.default.stderr | 43 ++ .../excessive_nesting/excessive_nesting.rs | 6 + .../excessive_nesting.stderr | 70 ++-- 8 files changed, 492 insertions(+), 52 deletions(-) rename tests/ui-toml/excessive_nesting/{ => below}/clippy.toml (100%) create mode 100644 tests/ui-toml/excessive_nesting/default/clippy.toml create mode 100644 tests/ui-toml/excessive_nesting/excessive_nesting.below.stderr create mode 100644 tests/ui-toml/excessive_nesting/excessive_nesting.default.stderr diff --git a/clippy_lints/src/excessive_nesting.rs b/clippy_lints/src/excessive_nesting.rs index 5ade713f816..f1aafa3cbc3 100644 --- a/clippy_lints/src/excessive_nesting.rs +++ b/clippy_lints/src/excessive_nesting.rs @@ -1,7 +1,8 @@ use clippy_utils::diagnostics::span_lint_and_help; use rustc_ast::{ + node_id::NodeSet, visit::{walk_block, walk_item, Visitor}, - Block, Crate, Inline, Item, ItemKind, ModKind, + Block, Crate, Inline, Item, ItemKind, ModKind, NodeId, }; use rustc_lint::{EarlyContext, EarlyLintPass, LintContext}; use rustc_middle::lint::in_external_macro; @@ -52,6 +53,10 @@ declare_clippy_lint! { /// } /// } /// ``` + /// lib.rs: + /// ```rust,ignore + /// pub mod a; + /// ``` #[clippy::version = "1.70.0"] pub EXCESSIVE_NESTING, restriction, @@ -59,16 +64,31 @@ declare_clippy_lint! { } impl_lint_pass!(ExcessiveNesting => [EXCESSIVE_NESTING]); -#[derive(Clone, Copy)] +#[derive(Clone)] pub struct ExcessiveNesting { pub excessive_nesting_threshold: u64, + pub nodes: NodeSet, +} + +impl ExcessiveNesting { + pub fn check_node_id(&self, cx: &EarlyContext<'_>, span: Span, node_id: NodeId) { + if self.nodes.contains(&node_id) { + span_lint_and_help( + cx, + EXCESSIVE_NESTING, + span, + "this block is too nested", + None, + "try refactoring your code to minimize nesting", + ); + } + } } impl EarlyLintPass for ExcessiveNesting { fn check_crate(&mut self, cx: &EarlyContext<'_>, krate: &Crate) { - let conf = self; let mut visitor = NestingVisitor { - conf, + conf: self, cx, nest_level: 0, }; @@ -77,25 +97,26 @@ impl EarlyLintPass for ExcessiveNesting { visitor.visit_item(item); } } + + fn check_block(&mut self, cx: &EarlyContext<'_>, block: &Block) { + self.check_node_id(cx, block.span, block.id); + } + + fn check_item(&mut self, cx: &EarlyContext<'_>, item: &Item) { + self.check_node_id(cx, item.span, item.id); + } } struct NestingVisitor<'conf, 'cx> { - conf: &'conf ExcessiveNesting, + conf: &'conf mut ExcessiveNesting, cx: &'cx EarlyContext<'cx>, nest_level: u64, } impl NestingVisitor<'_, '_> { - fn check_indent(&self, span: Span) -> bool { + fn check_indent(&mut self, span: Span, id: NodeId) -> bool { if self.nest_level > self.conf.excessive_nesting_threshold && !in_external_macro(self.cx.sess(), span) { - span_lint_and_help( - self.cx, - EXCESSIVE_NESTING, - span, - "this block is too nested", - None, - "try refactoring your code to minimize nesting", - ); + self.conf.nodes.insert(id); return true; } @@ -106,14 +127,13 @@ impl NestingVisitor<'_, '_> { impl<'conf, 'cx> Visitor<'_> for NestingVisitor<'conf, 'cx> { fn visit_block(&mut self, block: &Block) { - // TODO: Probably not necessary, since any block would already be ignored by the check in visit_item if block.span.from_expansion() { return; } self.nest_level += 1; - if !self.check_indent(block.span) { + if !self.check_indent(block.span, block.id) { walk_block(self, block); } @@ -129,7 +149,7 @@ impl<'conf, 'cx> Visitor<'_> for NestingVisitor<'conf, 'cx> { ItemKind::Trait(_) | ItemKind::Impl(_) | ItemKind::Mod(.., ModKind::Loaded(_, Inline::Yes, _)) => { self.nest_level += 1; - if !self.check_indent(item.span) { + if !self.check_indent(item.span, item.id) { walk_item(self, item); } diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index 202b4709ad4..189096d7ba9 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -1012,6 +1012,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: store.register_early_pass(move || { Box::new(excessive_nesting::ExcessiveNesting { excessive_nesting_threshold, + nodes: rustc_ast::node_id::NodeSet::new(), }) }); store.register_late_pass(|_| Box::new(items_after_test_module::ItemsAfterTestModule)); diff --git a/tests/ui-toml/excessive_nesting/clippy.toml b/tests/ui-toml/excessive_nesting/below/clippy.toml similarity index 100% rename from tests/ui-toml/excessive_nesting/clippy.toml rename to tests/ui-toml/excessive_nesting/below/clippy.toml diff --git a/tests/ui-toml/excessive_nesting/default/clippy.toml b/tests/ui-toml/excessive_nesting/default/clippy.toml new file mode 100644 index 00000000000..b01e482e485 --- /dev/null +++ b/tests/ui-toml/excessive_nesting/default/clippy.toml @@ -0,0 +1 @@ +excessive-nesting-threshold = 10 diff --git a/tests/ui-toml/excessive_nesting/excessive_nesting.below.stderr b/tests/ui-toml/excessive_nesting/excessive_nesting.below.stderr new file mode 100644 index 00000000000..1f069437dfe --- /dev/null +++ b/tests/ui-toml/excessive_nesting/excessive_nesting.below.stderr @@ -0,0 +1,369 @@ +error: this block is too nested + --> $DIR/auxiliary/mod.rs:6:13 + | +LL | / mod d { +LL | | mod e {} +LL | | } + | |_____________^ + | + = help: try refactoring your code to minimize nesting + = note: `-D clippy::excessive-nesting` implied by `-D warnings` + +error: this block is too nested + --> $DIR/auxiliary/mod.rs:15:7 + | +LL | {{{}}} + | ^^ + | + = help: try refactoring your code to minimize nesting + +error: this block is too nested + --> $DIR/excessive_nesting.rs:24:21 + | +LL | let z = { + | _____________________^ +LL | | let w = { 3 }; +LL | | w +LL | | }; + | |_____________^ + | + = help: try refactoring your code to minimize nesting + +error: this block is too nested + --> $DIR/excessive_nesting.rs:68:24 + | +LL | pub fn b() { + | ________________________^ +LL | | struct C; +LL | | +LL | | impl C { +LL | | pub fn c() {} +LL | | } +LL | | } + | |_____________^ + | + = help: try refactoring your code to minimize nesting + +error: this block is too nested + --> $DIR/excessive_nesting.rs:84:21 + | +LL | fn cc() { + | _____________________^ +LL | | let x = { 1 }; // not a warning, but cc is +LL | | } + | |_____________^ + | + = help: try refactoring your code to minimize nesting + +error: this block is too nested + --> $DIR/excessive_nesting.rs:88:21 + | +LL | let x = { 1 }; // warning + | ^^^^^ + | + = help: try refactoring your code to minimize nesting + +error: this block is too nested + --> $DIR/excessive_nesting.rs:101:13 + | +LL | / pub mod d { +LL | | pub mod e { +LL | | pub mod f {} +LL | | } // not here +LL | | } // only warning should be here + | |_____________^ + | + = help: try refactoring your code to minimize nesting + +error: this block is too nested + --> $DIR/excessive_nesting.rs:115:17 + | +LL | a_but_not({{{{{{{{0}}}}}}}}); + | ^^^^^^^^^^^^^ + | + = help: try refactoring your code to minimize nesting + +error: this block is too nested + --> $DIR/excessive_nesting.rs:116:11 + | +LL | a.a({{{{{{{{{0}}}}}}}}}); + | ^^^^^^^^^^^^^^^ + | + = help: try refactoring your code to minimize nesting + +error: this block is too nested + --> $DIR/excessive_nesting.rs:117:11 + | +LL | (0, {{{{{{{1}}}}}}}); + | ^^^^^^^^^^^ + | + = help: try refactoring your code to minimize nesting + +error: this block is too nested + --> $DIR/excessive_nesting.rs:121:21 + | +LL | if true { + | _____________________^ +LL | | if true { +LL | | if true { +LL | | +LL | | } +LL | | } +LL | | } + | |_____________^ + | + = help: try refactoring your code to minimize nesting + +error: this block is too nested + --> $DIR/excessive_nesting.rs:133:25 + | +LL | let y = (|| { + | _________________________^ +LL | | let z = (|| { +LL | | let w = { 3 }; +LL | | w +LL | | })(); +LL | | z +LL | | })(); + | |_____________^ + | + = help: try refactoring your code to minimize nesting + +error: this block is too nested + --> $DIR/excessive_nesting.rs:148:36 + | +LL | !{boo as u32 + !{boo as u32 + !{boo as u32}}}; + | ^^^^^^^^^^^^ + | + = help: try refactoring your code to minimize nesting + +error: this block is too nested + --> $DIR/excessive_nesting.rs:152:12 + | +LL | y += {{{{{5}}}}}; + | ^^^^^^^ + | + = help: try refactoring your code to minimize nesting + +error: this block is too nested + --> $DIR/excessive_nesting.rs:153:19 + | +LL | let z = y + {{{{{{{{{5}}}}}}}}}; + | ^^^^^^^^^^^^^^^ + | + = help: try refactoring your code to minimize nesting + +error: this block is too nested + --> $DIR/excessive_nesting.rs:154:11 + | +LL | [0, {{{{{{{{{{0}}}}}}}}}}]; + | ^^^^^^^^^^^^^^^^^ + | + = help: try refactoring your code to minimize nesting + +error: this block is too nested + --> $DIR/excessive_nesting.rs:155:24 + | +LL | let mut xx = [0; {{{{{{{{100}}}}}}}}]; + | ^^^^^^^^^^^^^^^ + | + = help: try refactoring your code to minimize nesting + +error: this block is too nested + --> $DIR/excessive_nesting.rs:156:10 + | +LL | xx[{{{{{{{{{{{{{{{{{{{{{{{{3}}}}}}}}}}}}}}}}}}}}}}}}]; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: try refactoring your code to minimize nesting + +error: this block is too nested + --> $DIR/excessive_nesting.rs:157:12 + | +LL | &mut {{{{{{{{{{y}}}}}}}}}}; + | ^^^^^^^^^^^^^^^^^ + | + = help: try refactoring your code to minimize nesting + +error: this block is too nested + --> $DIR/excessive_nesting.rs:159:16 + | +LL | for i in {{{{xx}}}} {{{{{{{{}}}}}}}} + | ^^^^^^ + | + = help: try refactoring your code to minimize nesting + +error: this block is too nested + --> $DIR/excessive_nesting.rs:159:27 + | +LL | for i in {{{{xx}}}} {{{{{{{{}}}}}}}} + | ^^^^^^^^^^^^ + | + = help: try refactoring your code to minimize nesting + +error: this block is too nested + --> $DIR/excessive_nesting.rs:161:27 + | +LL | while let Some(i) = {{{{{{Some(1)}}}}}} {{{{{{{}}}}}}} + | ^^^^^^^^^^^^^^^ + | + = help: try refactoring your code to minimize nesting + +error: this block is too nested + --> $DIR/excessive_nesting.rs:161:47 + | +LL | while let Some(i) = {{{{{{Some(1)}}}}}} {{{{{{{}}}}}}} + | ^^^^^^^^^^ + | + = help: try refactoring your code to minimize nesting + +error: this block is too nested + --> $DIR/excessive_nesting.rs:163:13 + | +LL | while {{{{{{{{true}}}}}}}} {{{{{{{{{}}}}}}}}} + | ^^^^^^^^^^^^^^^^ + | + = help: try refactoring your code to minimize nesting + +error: this block is too nested + --> $DIR/excessive_nesting.rs:163:34 + | +LL | while {{{{{{{{true}}}}}}}} {{{{{{{{{}}}}}}}}} + | ^^^^^^^^^^^^^^ + | + = help: try refactoring your code to minimize nesting + +error: this block is too nested + --> $DIR/excessive_nesting.rs:165:22 + | +LL | let d = D { d: {{{{{{{{{{{{{{{{{{{{{{{3}}}}}}}}}}}}}}}}}}}}}}} }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: try refactoring your code to minimize nesting + +error: this block is too nested + --> $DIR/excessive_nesting.rs:167:7 + | +LL | {{{{1;}}}}..{{{{{{3}}}}}}; + | ^^^^^^ + | + = help: try refactoring your code to minimize nesting + +error: this block is too nested + --> $DIR/excessive_nesting.rs:167:19 + | +LL | {{{{1;}}}}..{{{{{{3}}}}}}; + | ^^^^^^^^^ + | + = help: try refactoring your code to minimize nesting + +error: this block is too nested + --> $DIR/excessive_nesting.rs:168:7 + | +LL | {{{{1;}}}}..={{{{{{{{{{{{{{{{{{{{{{{{{{6}}}}}}}}}}}}}}}}}}}}}}}}}}; + | ^^^^^^ + | + = help: try refactoring your code to minimize nesting + +error: this block is too nested + --> $DIR/excessive_nesting.rs:168:20 + | +LL | {{{{1;}}}}..={{{{{{{{{{{{{{{{{{{{{{{{{{6}}}}}}}}}}}}}}}}}}}}}}}}}}; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: try refactoring your code to minimize nesting + +error: this block is too nested + --> $DIR/excessive_nesting.rs:169:9 + | +LL | ..{{{{{{{5}}}}}}}; + | ^^^^^^^^^^^ + | + = help: try refactoring your code to minimize nesting + +error: this block is too nested + --> $DIR/excessive_nesting.rs:170:10 + | +LL | ..={{{{{3}}}}}; + | ^^^^^^^ + | + = help: try refactoring your code to minimize nesting + +error: this block is too nested + --> $DIR/excessive_nesting.rs:171:7 + | +LL | {{{{{1;}}}}}..; + | ^^^^^^^^ + | + = help: try refactoring your code to minimize nesting + +error: this block is too nested + --> $DIR/excessive_nesting.rs:173:19 + | +LL | loop { break {{{{1}}}} }; + | ^^^^^^^ + | + = help: try refactoring your code to minimize nesting + +error: this block is too nested + --> $DIR/excessive_nesting.rs:174:12 + | +LL | loop {{{{{{}}}}}} + | ^^^^^^^^ + | + = help: try refactoring your code to minimize nesting + +error: this block is too nested + --> $DIR/excessive_nesting.rs:176:13 + | +LL | match {{{{{{true}}}}}} { + | ^^^^^^^^^^^^ + | + = help: try refactoring your code to minimize nesting + +error: this block is too nested + --> $DIR/excessive_nesting.rs:177:19 + | +LL | true => {{{{}}}}, + | ^^^^ + | + = help: try refactoring your code to minimize nesting + +error: this block is too nested + --> $DIR/excessive_nesting.rs:178:20 + | +LL | false => {{{{}}}}, + | ^^^^ + | + = help: try refactoring your code to minimize nesting + +error: this block is too nested + --> $DIR/excessive_nesting.rs:183:13 + | +LL | / { +LL | | { +LL | | println!("warning! :)"); +LL | | } +LL | | } + | |_____________^ + | + = help: try refactoring your code to minimize nesting + +error: this block is too nested + --> $DIR/excessive_nesting.rs:193:27 + | +LL | async fn c() -> u32 {{{{{{{0}}}}}}} + | ^^^^^^^^^^^ + | + = help: try refactoring your code to minimize nesting + +error: this block is too nested + --> $DIR/excessive_nesting.rs:199:7 + | +LL | {{{{b().await}}}}; + | ^^^^^^^^^^^^^ + | + = help: try refactoring your code to minimize nesting + +error: aborting due to 41 previous errors + diff --git a/tests/ui-toml/excessive_nesting/excessive_nesting.default.stderr b/tests/ui-toml/excessive_nesting/excessive_nesting.default.stderr new file mode 100644 index 00000000000..02fa2cdcf9f --- /dev/null +++ b/tests/ui-toml/excessive_nesting/excessive_nesting.default.stderr @@ -0,0 +1,43 @@ +error: this block is too nested + --> $DIR/excessive_nesting.rs:154:18 + | +LL | [0, {{{{{{{{{{0}}}}}}}}}}]; + | ^^^ + | + = help: try refactoring your code to minimize nesting + = note: `-D clippy::excessive-nesting` implied by `-D warnings` + +error: this block is too nested + --> $DIR/excessive_nesting.rs:156:17 + | +LL | xx[{{{{{{{{{{{{{{{{{{{{{{{{3}}}}}}}}}}}}}}}}}}}}}}}}]; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: try refactoring your code to minimize nesting + +error: this block is too nested + --> $DIR/excessive_nesting.rs:157:19 + | +LL | &mut {{{{{{{{{{y}}}}}}}}}}; + | ^^^ + | + = help: try refactoring your code to minimize nesting + +error: this block is too nested + --> $DIR/excessive_nesting.rs:165:29 + | +LL | let d = D { d: {{{{{{{{{{{{{{{{{{{{{{{3}}}}}}}}}}}}}}}}}}}}}}} }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: try refactoring your code to minimize nesting + +error: this block is too nested + --> $DIR/excessive_nesting.rs:168:27 + | +LL | {{{{1;}}}}..={{{{{{{{{{{{{{{{{{{{{{{{{{6}}}}}}}}}}}}}}}}}}}}}}}}}}; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: try refactoring your code to minimize nesting + +error: aborting due to 5 previous errors + diff --git a/tests/ui-toml/excessive_nesting/excessive_nesting.rs b/tests/ui-toml/excessive_nesting/excessive_nesting.rs index 3e3ac7c923a..745031db1eb 100644 --- a/tests/ui-toml/excessive_nesting/excessive_nesting.rs +++ b/tests/ui-toml/excessive_nesting/excessive_nesting.rs @@ -1,4 +1,7 @@ //@aux-build:macro_rules.rs +//@revisions: below default +//@[below] rustc-env:CLIPPY_CONF_DIR=tests/ui-toml/excessive_nesting/below +//@[default] rustc-env:CLIPPY_CONF_DIR=tests/ui-toml/excessive_nesting/default #![rustfmt::skip] #![feature(custom_inner_attributes)] #![allow(unused)] @@ -87,6 +90,9 @@ trait Lol { } } +#[allow(clippy::excessive_nesting)] +fn l() {{{{{{{{{}}}}}}}}} + use a::{b::{c::{d::{e::{f::{}}}}}}; // should not lint pub mod a { diff --git a/tests/ui-toml/excessive_nesting/excessive_nesting.stderr b/tests/ui-toml/excessive_nesting/excessive_nesting.stderr index 524282d11f7..f1db396fe48 100644 --- a/tests/ui-toml/excessive_nesting/excessive_nesting.stderr +++ b/tests/ui-toml/excessive_nesting/excessive_nesting.stderr @@ -64,7 +64,7 @@ LL | let x = { 1 }; // warning = help: try refactoring your code to minimize nesting error: this block is too nested - --> $DIR/excessive_nesting.rs:95:13 + --> $DIR/excessive_nesting.rs:98:13 | LL | / pub mod d { LL | | pub mod e { @@ -76,7 +76,7 @@ LL | | } // only warning should be here = help: try refactoring your code to minimize nesting error: this block is too nested - --> $DIR/excessive_nesting.rs:109:17 + --> $DIR/excessive_nesting.rs:112:17 | LL | a_but_not({{{{{{{{0}}}}}}}}); | ^^^^^^^^^^^^^ @@ -84,7 +84,7 @@ LL | a_but_not({{{{{{{{0}}}}}}}}); = help: try refactoring your code to minimize nesting error: this block is too nested - --> $DIR/excessive_nesting.rs:110:11 + --> $DIR/excessive_nesting.rs:113:11 | LL | a.a({{{{{{{{{0}}}}}}}}}); | ^^^^^^^^^^^^^^^ @@ -92,7 +92,7 @@ LL | a.a({{{{{{{{{0}}}}}}}}}); = help: try refactoring your code to minimize nesting error: this block is too nested - --> $DIR/excessive_nesting.rs:111:11 + --> $DIR/excessive_nesting.rs:114:11 | LL | (0, {{{{{{{1}}}}}}}); | ^^^^^^^^^^^ @@ -100,7 +100,7 @@ LL | (0, {{{{{{{1}}}}}}}); = help: try refactoring your code to minimize nesting error: this block is too nested - --> $DIR/excessive_nesting.rs:115:21 + --> $DIR/excessive_nesting.rs:118:21 | LL | if true { | _____________________^ @@ -115,7 +115,7 @@ LL | | } = help: try refactoring your code to minimize nesting error: this block is too nested - --> $DIR/excessive_nesting.rs:127:25 + --> $DIR/excessive_nesting.rs:130:25 | LL | let y = (|| { | _________________________^ @@ -130,7 +130,7 @@ LL | | })(); = help: try refactoring your code to minimize nesting error: this block is too nested - --> $DIR/excessive_nesting.rs:142:36 + --> $DIR/excessive_nesting.rs:145:36 | LL | !{boo as u32 + !{boo as u32 + !{boo as u32}}}; | ^^^^^^^^^^^^ @@ -138,7 +138,7 @@ LL | !{boo as u32 + !{boo as u32 + !{boo as u32}}}; = help: try refactoring your code to minimize nesting error: this block is too nested - --> $DIR/excessive_nesting.rs:146:12 + --> $DIR/excessive_nesting.rs:149:12 | LL | y += {{{{{5}}}}}; | ^^^^^^^ @@ -146,7 +146,7 @@ LL | y += {{{{{5}}}}}; = help: try refactoring your code to minimize nesting error: this block is too nested - --> $DIR/excessive_nesting.rs:147:19 + --> $DIR/excessive_nesting.rs:150:19 | LL | let z = y + {{{{{{{{{5}}}}}}}}}; | ^^^^^^^^^^^^^^^ @@ -154,7 +154,7 @@ LL | let z = y + {{{{{{{{{5}}}}}}}}}; = help: try refactoring your code to minimize nesting error: this block is too nested - --> $DIR/excessive_nesting.rs:148:11 + --> $DIR/excessive_nesting.rs:151:11 | LL | [0, {{{{{{{{{{0}}}}}}}}}}]; | ^^^^^^^^^^^^^^^^^ @@ -162,7 +162,7 @@ LL | [0, {{{{{{{{{{0}}}}}}}}}}]; = help: try refactoring your code to minimize nesting error: this block is too nested - --> $DIR/excessive_nesting.rs:149:24 + --> $DIR/excessive_nesting.rs:152:24 | LL | let mut xx = [0; {{{{{{{{100}}}}}}}}]; | ^^^^^^^^^^^^^^^ @@ -170,7 +170,7 @@ LL | let mut xx = [0; {{{{{{{{100}}}}}}}}]; = help: try refactoring your code to minimize nesting error: this block is too nested - --> $DIR/excessive_nesting.rs:150:10 + --> $DIR/excessive_nesting.rs:153:10 | LL | xx[{{{{{{{{{{{{{{{{{{{{{{{{3}}}}}}}}}}}}}}}}}}}}}}}}]; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -178,7 +178,7 @@ LL | xx[{{{{{{{{{{{{{{{{{{{{{{{{3}}}}}}}}}}}}}}}}}}}}}}}}]; = help: try refactoring your code to minimize nesting error: this block is too nested - --> $DIR/excessive_nesting.rs:151:12 + --> $DIR/excessive_nesting.rs:154:12 | LL | &mut {{{{{{{{{{y}}}}}}}}}}; | ^^^^^^^^^^^^^^^^^ @@ -186,7 +186,7 @@ LL | &mut {{{{{{{{{{y}}}}}}}}}}; = help: try refactoring your code to minimize nesting error: this block is too nested - --> $DIR/excessive_nesting.rs:153:16 + --> $DIR/excessive_nesting.rs:156:16 | LL | for i in {{{{xx}}}} {{{{{{{{}}}}}}}} | ^^^^^^ @@ -194,7 +194,7 @@ LL | for i in {{{{xx}}}} {{{{{{{{}}}}}}}} = help: try refactoring your code to minimize nesting error: this block is too nested - --> $DIR/excessive_nesting.rs:153:27 + --> $DIR/excessive_nesting.rs:156:27 | LL | for i in {{{{xx}}}} {{{{{{{{}}}}}}}} | ^^^^^^^^^^^^ @@ -202,7 +202,7 @@ LL | for i in {{{{xx}}}} {{{{{{{{}}}}}}}} = help: try refactoring your code to minimize nesting error: this block is too nested - --> $DIR/excessive_nesting.rs:155:27 + --> $DIR/excessive_nesting.rs:158:27 | LL | while let Some(i) = {{{{{{Some(1)}}}}}} {{{{{{{}}}}}}} | ^^^^^^^^^^^^^^^ @@ -210,7 +210,7 @@ LL | while let Some(i) = {{{{{{Some(1)}}}}}} {{{{{{{}}}}}}} = help: try refactoring your code to minimize nesting error: this block is too nested - --> $DIR/excessive_nesting.rs:155:47 + --> $DIR/excessive_nesting.rs:158:47 | LL | while let Some(i) = {{{{{{Some(1)}}}}}} {{{{{{{}}}}}}} | ^^^^^^^^^^ @@ -218,7 +218,7 @@ LL | while let Some(i) = {{{{{{Some(1)}}}}}} {{{{{{{}}}}}}} = help: try refactoring your code to minimize nesting error: this block is too nested - --> $DIR/excessive_nesting.rs:157:13 + --> $DIR/excessive_nesting.rs:160:13 | LL | while {{{{{{{{true}}}}}}}} {{{{{{{{{}}}}}}}}} | ^^^^^^^^^^^^^^^^ @@ -226,7 +226,7 @@ LL | while {{{{{{{{true}}}}}}}} {{{{{{{{{}}}}}}}}} = help: try refactoring your code to minimize nesting error: this block is too nested - --> $DIR/excessive_nesting.rs:157:34 + --> $DIR/excessive_nesting.rs:160:34 | LL | while {{{{{{{{true}}}}}}}} {{{{{{{{{}}}}}}}}} | ^^^^^^^^^^^^^^ @@ -234,7 +234,7 @@ LL | while {{{{{{{{true}}}}}}}} {{{{{{{{{}}}}}}}}} = help: try refactoring your code to minimize nesting error: this block is too nested - --> $DIR/excessive_nesting.rs:159:22 + --> $DIR/excessive_nesting.rs:162:22 | LL | let d = D { d: {{{{{{{{{{{{{{{{{{{{{{{3}}}}}}}}}}}}}}}}}}}}}}} }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -242,7 +242,7 @@ LL | let d = D { d: {{{{{{{{{{{{{{{{{{{{{{{3}}}}}}}}}}}}}}}}}}}}}}} }; = help: try refactoring your code to minimize nesting error: this block is too nested - --> $DIR/excessive_nesting.rs:161:7 + --> $DIR/excessive_nesting.rs:164:7 | LL | {{{{1;}}}}..{{{{{{3}}}}}}; | ^^^^^^ @@ -250,7 +250,7 @@ LL | {{{{1;}}}}..{{{{{{3}}}}}}; = help: try refactoring your code to minimize nesting error: this block is too nested - --> $DIR/excessive_nesting.rs:161:19 + --> $DIR/excessive_nesting.rs:164:19 | LL | {{{{1;}}}}..{{{{{{3}}}}}}; | ^^^^^^^^^ @@ -258,7 +258,7 @@ LL | {{{{1;}}}}..{{{{{{3}}}}}}; = help: try refactoring your code to minimize nesting error: this block is too nested - --> $DIR/excessive_nesting.rs:162:7 + --> $DIR/excessive_nesting.rs:165:7 | LL | {{{{1;}}}}..={{{{{{{{{{{{{{{{{{{{{{{{{{6}}}}}}}}}}}}}}}}}}}}}}}}}}; | ^^^^^^ @@ -266,7 +266,7 @@ LL | {{{{1;}}}}..={{{{{{{{{{{{{{{{{{{{{{{{{{6}}}}}}}}}}}}}}}}}}}}}}}}}}; = help: try refactoring your code to minimize nesting error: this block is too nested - --> $DIR/excessive_nesting.rs:162:20 + --> $DIR/excessive_nesting.rs:165:20 | LL | {{{{1;}}}}..={{{{{{{{{{{{{{{{{{{{{{{{{{6}}}}}}}}}}}}}}}}}}}}}}}}}}; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -274,7 +274,7 @@ LL | {{{{1;}}}}..={{{{{{{{{{{{{{{{{{{{{{{{{{6}}}}}}}}}}}}}}}}}}}}}}}}}}; = help: try refactoring your code to minimize nesting error: this block is too nested - --> $DIR/excessive_nesting.rs:163:9 + --> $DIR/excessive_nesting.rs:166:9 | LL | ..{{{{{{{5}}}}}}}; | ^^^^^^^^^^^ @@ -282,7 +282,7 @@ LL | ..{{{{{{{5}}}}}}}; = help: try refactoring your code to minimize nesting error: this block is too nested - --> $DIR/excessive_nesting.rs:164:10 + --> $DIR/excessive_nesting.rs:167:10 | LL | ..={{{{{3}}}}}; | ^^^^^^^ @@ -290,7 +290,7 @@ LL | ..={{{{{3}}}}}; = help: try refactoring your code to minimize nesting error: this block is too nested - --> $DIR/excessive_nesting.rs:165:7 + --> $DIR/excessive_nesting.rs:168:7 | LL | {{{{{1;}}}}}..; | ^^^^^^^^ @@ -298,7 +298,7 @@ LL | {{{{{1;}}}}}..; = help: try refactoring your code to minimize nesting error: this block is too nested - --> $DIR/excessive_nesting.rs:167:19 + --> $DIR/excessive_nesting.rs:170:19 | LL | loop { break {{{{1}}}} }; | ^^^^^^^ @@ -306,7 +306,7 @@ LL | loop { break {{{{1}}}} }; = help: try refactoring your code to minimize nesting error: this block is too nested - --> $DIR/excessive_nesting.rs:168:12 + --> $DIR/excessive_nesting.rs:171:12 | LL | loop {{{{{{}}}}}} | ^^^^^^^^ @@ -314,7 +314,7 @@ LL | loop {{{{{{}}}}}} = help: try refactoring your code to minimize nesting error: this block is too nested - --> $DIR/excessive_nesting.rs:170:13 + --> $DIR/excessive_nesting.rs:173:13 | LL | match {{{{{{true}}}}}} { | ^^^^^^^^^^^^ @@ -322,7 +322,7 @@ LL | match {{{{{{true}}}}}} { = help: try refactoring your code to minimize nesting error: this block is too nested - --> $DIR/excessive_nesting.rs:171:19 + --> $DIR/excessive_nesting.rs:174:19 | LL | true => {{{{}}}}, | ^^^^ @@ -330,7 +330,7 @@ LL | true => {{{{}}}}, = help: try refactoring your code to minimize nesting error: this block is too nested - --> $DIR/excessive_nesting.rs:172:20 + --> $DIR/excessive_nesting.rs:175:20 | LL | false => {{{{}}}}, | ^^^^ @@ -338,7 +338,7 @@ LL | false => {{{{}}}}, = help: try refactoring your code to minimize nesting error: this block is too nested - --> $DIR/excessive_nesting.rs:177:13 + --> $DIR/excessive_nesting.rs:180:13 | LL | / { LL | | { @@ -350,7 +350,7 @@ LL | | } = help: try refactoring your code to minimize nesting error: this block is too nested - --> $DIR/excessive_nesting.rs:187:27 + --> $DIR/excessive_nesting.rs:190:27 | LL | async fn c() -> u32 {{{{{{{0}}}}}}} | ^^^^^^^^^^^ @@ -358,7 +358,7 @@ LL | async fn c() -> u32 {{{{{{{0}}}}}}} = help: try refactoring your code to minimize nesting error: this block is too nested - --> $DIR/excessive_nesting.rs:193:7 + --> $DIR/excessive_nesting.rs:196:7 | LL | {{{{b().await}}}}; | ^^^^^^^^^^^^^ From 725399a178158be33f0754c423b95b5f7f8b53ac Mon Sep 17 00:00:00 2001 From: Centri3 <114838443+Centri3@users.noreply.github.com> Date: Tue, 30 May 2023 12:40:40 -0500 Subject: [PATCH 093/310] move to `complexity` but don't lint by default --- book/src/lint_configuration.md | 2 +- clippy_lints/src/excessive_nesting.rs | 13 +++--- clippy_lints/src/utils/conf.rs | 2 +- .../excessive_nesting/default/clippy.toml | 2 +- .../excessive_nesting.default.stderr | 43 ------------------- .../excessive_nesting/excessive_nesting.rs | 4 +- ...ow.stderr => excessive_nesting.set.stderr} | 0 .../{below => set}/clippy.toml | 0 8 files changed, 12 insertions(+), 54 deletions(-) rename tests/ui-toml/excessive_nesting/{excessive_nesting.below.stderr => excessive_nesting.set.stderr} (100%) rename tests/ui-toml/excessive_nesting/{below => set}/clippy.toml (100%) diff --git a/book/src/lint_configuration.md b/book/src/lint_configuration.md index 4fa6b81c002..3c955c9e574 100644 --- a/book/src/lint_configuration.md +++ b/book/src/lint_configuration.md @@ -161,7 +161,7 @@ The maximum cognitive complexity a function can have ## `excessive-nesting-threshold` The maximum amount of nesting a block can reside in -**Default Value:** `10` (`u64`) +**Default Value:** `0` (`u64`) --- **Affected lints:** diff --git a/clippy_lints/src/excessive_nesting.rs b/clippy_lints/src/excessive_nesting.rs index f1aafa3cbc3..1d68d7f9478 100644 --- a/clippy_lints/src/excessive_nesting.rs +++ b/clippy_lints/src/excessive_nesting.rs @@ -11,13 +11,12 @@ use rustc_span::Span; declare_clippy_lint! { /// ### What it does - /// /// Checks for blocks which are nested beyond a certain threshold. /// - /// ### Why is this bad? + /// Note: Even though this lint is warn-by-default, it will only trigger if a maximum nesting level is defined in the clippy.toml file. /// - /// It can severely hinder readability. The default is very generous; if you - /// exceed this, it's a sign you should refactor. + /// ### Why is this bad? + /// It can severely hinder readability. /// /// ### Example /// An example clippy.toml configuration: @@ -59,7 +58,7 @@ declare_clippy_lint! { /// ``` #[clippy::version = "1.70.0"] pub EXCESSIVE_NESTING, - restriction, + complexity, "checks for blocks nested beyond a certain threshold" } impl_lint_pass!(ExcessiveNesting => [EXCESSIVE_NESTING]); @@ -115,7 +114,9 @@ struct NestingVisitor<'conf, 'cx> { impl NestingVisitor<'_, '_> { fn check_indent(&mut self, span: Span, id: NodeId) -> bool { - if self.nest_level > self.conf.excessive_nesting_threshold && !in_external_macro(self.cx.sess(), span) { + let threshold = self.conf.excessive_nesting_threshold; + + if threshold != 0 && self.nest_level > threshold && !in_external_macro(self.cx.sess(), span) { self.conf.nodes.insert(id); return true; diff --git a/clippy_lints/src/utils/conf.rs b/clippy_lints/src/utils/conf.rs index cf0da266dc9..69143c3c726 100644 --- a/clippy_lints/src/utils/conf.rs +++ b/clippy_lints/src/utils/conf.rs @@ -308,7 +308,7 @@ define_Conf! { /// Lint: EXCESSIVE_NESTING. /// /// The maximum amount of nesting a block can reside in - (excessive_nesting_threshold: u64 = 10), + (excessive_nesting_threshold: u64 = 0), /// DEPRECATED LINT: CYCLOMATIC_COMPLEXITY. /// /// Use the Cognitive Complexity lint instead. diff --git a/tests/ui-toml/excessive_nesting/default/clippy.toml b/tests/ui-toml/excessive_nesting/default/clippy.toml index b01e482e485..e8b115a0f7c 100644 --- a/tests/ui-toml/excessive_nesting/default/clippy.toml +++ b/tests/ui-toml/excessive_nesting/default/clippy.toml @@ -1 +1 @@ -excessive-nesting-threshold = 10 +excessive-nesting-threshold = 0 diff --git a/tests/ui-toml/excessive_nesting/excessive_nesting.default.stderr b/tests/ui-toml/excessive_nesting/excessive_nesting.default.stderr index 02fa2cdcf9f..e69de29bb2d 100644 --- a/tests/ui-toml/excessive_nesting/excessive_nesting.default.stderr +++ b/tests/ui-toml/excessive_nesting/excessive_nesting.default.stderr @@ -1,43 +0,0 @@ -error: this block is too nested - --> $DIR/excessive_nesting.rs:154:18 - | -LL | [0, {{{{{{{{{{0}}}}}}}}}}]; - | ^^^ - | - = help: try refactoring your code to minimize nesting - = note: `-D clippy::excessive-nesting` implied by `-D warnings` - -error: this block is too nested - --> $DIR/excessive_nesting.rs:156:17 - | -LL | xx[{{{{{{{{{{{{{{{{{{{{{{{{3}}}}}}}}}}}}}}}}}}}}}}}}]; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = help: try refactoring your code to minimize nesting - -error: this block is too nested - --> $DIR/excessive_nesting.rs:157:19 - | -LL | &mut {{{{{{{{{{y}}}}}}}}}}; - | ^^^ - | - = help: try refactoring your code to minimize nesting - -error: this block is too nested - --> $DIR/excessive_nesting.rs:165:29 - | -LL | let d = D { d: {{{{{{{{{{{{{{{{{{{{{{{3}}}}}}}}}}}}}}}}}}}}}}} }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = help: try refactoring your code to minimize nesting - -error: this block is too nested - --> $DIR/excessive_nesting.rs:168:27 - | -LL | {{{{1;}}}}..={{{{{{{{{{{{{{{{{{{{{{{{{{6}}}}}}}}}}}}}}}}}}}}}}}}}}; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = help: try refactoring your code to minimize nesting - -error: aborting due to 5 previous errors - diff --git a/tests/ui-toml/excessive_nesting/excessive_nesting.rs b/tests/ui-toml/excessive_nesting/excessive_nesting.rs index 745031db1eb..5e436b97ee8 100644 --- a/tests/ui-toml/excessive_nesting/excessive_nesting.rs +++ b/tests/ui-toml/excessive_nesting/excessive_nesting.rs @@ -1,6 +1,6 @@ //@aux-build:macro_rules.rs -//@revisions: below default -//@[below] rustc-env:CLIPPY_CONF_DIR=tests/ui-toml/excessive_nesting/below +//@revisions: set default +//@[set] rustc-env:CLIPPY_CONF_DIR=tests/ui-toml/excessive_nesting/set //@[default] rustc-env:CLIPPY_CONF_DIR=tests/ui-toml/excessive_nesting/default #![rustfmt::skip] #![feature(custom_inner_attributes)] diff --git a/tests/ui-toml/excessive_nesting/excessive_nesting.below.stderr b/tests/ui-toml/excessive_nesting/excessive_nesting.set.stderr similarity index 100% rename from tests/ui-toml/excessive_nesting/excessive_nesting.below.stderr rename to tests/ui-toml/excessive_nesting/excessive_nesting.set.stderr diff --git a/tests/ui-toml/excessive_nesting/below/clippy.toml b/tests/ui-toml/excessive_nesting/set/clippy.toml similarity index 100% rename from tests/ui-toml/excessive_nesting/below/clippy.toml rename to tests/ui-toml/excessive_nesting/set/clippy.toml From 5da34559ee6a1cf34ddfc889513f205c819bc112 Mon Sep 17 00:00:00 2001 From: Centri3 <114838443+Centri3@users.noreply.github.com> Date: Wed, 7 Jun 2023 18:22:17 -0500 Subject: [PATCH 094/310] Check if from proc macro and better tests --- clippy_lints/src/excessive_nesting.rs | 17 +- .../excessive_nesting/above/clippy.toml | 1 + .../auxiliary/macro_rules.rs | 7 - .../excessive_nesting/auxiliary/mod.rs | 16 - .../auxiliary/proc_macros.rs | 476 ++++++++++++++++++ .../excessive_nesting/default/clippy.toml | 1 - ....stderr => excessive_nesting.above.stderr} | 235 ++++----- .../excessive_nesting.default.stderr | 0 .../excessive_nesting/excessive_nesting.rs | 13 +- .../excessive_nesting.set.stderr | 100 ++-- .../toml_unknown_key/conf_unknown_key.stderr | 1 + 11 files changed, 628 insertions(+), 239 deletions(-) create mode 100644 tests/ui-toml/excessive_nesting/above/clippy.toml delete mode 100644 tests/ui-toml/excessive_nesting/auxiliary/macro_rules.rs delete mode 100644 tests/ui-toml/excessive_nesting/auxiliary/mod.rs create mode 100644 tests/ui-toml/excessive_nesting/auxiliary/proc_macros.rs delete mode 100644 tests/ui-toml/excessive_nesting/default/clippy.toml rename tests/ui-toml/excessive_nesting/{excessive_nesting.stderr => excessive_nesting.above.stderr} (55%) delete mode 100644 tests/ui-toml/excessive_nesting/excessive_nesting.default.stderr diff --git a/clippy_lints/src/excessive_nesting.rs b/clippy_lints/src/excessive_nesting.rs index 1d68d7f9478..1c6cd27789d 100644 --- a/clippy_lints/src/excessive_nesting.rs +++ b/clippy_lints/src/excessive_nesting.rs @@ -1,4 +1,4 @@ -use clippy_utils::diagnostics::span_lint_and_help; +use clippy_utils::{diagnostics::span_lint_and_help, source::snippet}; use rustc_ast::{ node_id::NodeSet, visit::{walk_block, walk_item, Visitor}, @@ -86,6 +86,10 @@ impl ExcessiveNesting { impl EarlyLintPass for ExcessiveNesting { fn check_crate(&mut self, cx: &EarlyContext<'_>, krate: &Crate) { + if self.excessive_nesting_threshold == 0 { + return; + } + let mut visitor = NestingVisitor { conf: self, cx, @@ -114,9 +118,7 @@ struct NestingVisitor<'conf, 'cx> { impl NestingVisitor<'_, '_> { fn check_indent(&mut self, span: Span, id: NodeId) -> bool { - let threshold = self.conf.excessive_nesting_threshold; - - if threshold != 0 && self.nest_level > threshold && !in_external_macro(self.cx.sess(), span) { + if self.nest_level > self.conf.excessive_nesting_threshold && !in_external_macro(self.cx.sess(), span) { self.conf.nodes.insert(id); return true; @@ -132,6 +134,13 @@ impl<'conf, 'cx> Visitor<'_> for NestingVisitor<'conf, 'cx> { return; } + // TODO: This should be rewritten using `LateLintPass` so we can use `is_from_proc_macro` instead, + // but for now, this is fine. + let snippet = snippet(self.cx, block.span, "{}").trim().to_owned(); + if !snippet.starts_with('{') || !snippet.ends_with('}') { + return; + } + self.nest_level += 1; if !self.check_indent(block.span, block.id) { diff --git a/tests/ui-toml/excessive_nesting/above/clippy.toml b/tests/ui-toml/excessive_nesting/above/clippy.toml new file mode 100644 index 00000000000..e60ac978cac --- /dev/null +++ b/tests/ui-toml/excessive_nesting/above/clippy.toml @@ -0,0 +1 @@ +excessive-nesting-threshold = 4 diff --git a/tests/ui-toml/excessive_nesting/auxiliary/macro_rules.rs b/tests/ui-toml/excessive_nesting/auxiliary/macro_rules.rs deleted file mode 100644 index 86663db68f2..00000000000 --- a/tests/ui-toml/excessive_nesting/auxiliary/macro_rules.rs +++ /dev/null @@ -1,7 +0,0 @@ -#[rustfmt::skip] -#[macro_export] -macro_rules! excessive_nesting { - () => {{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{ - println!("hi!!") - }}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}} -} diff --git a/tests/ui-toml/excessive_nesting/auxiliary/mod.rs b/tests/ui-toml/excessive_nesting/auxiliary/mod.rs deleted file mode 100644 index 967b3af3bca..00000000000 --- a/tests/ui-toml/excessive_nesting/auxiliary/mod.rs +++ /dev/null @@ -1,16 +0,0 @@ -#![rustfmt::skip] - -mod a { - mod b { - mod c { - mod d { - mod e {} - } - } - } -} - -fn main() { - // this should lint - {{{}}} -} diff --git a/tests/ui-toml/excessive_nesting/auxiliary/proc_macros.rs b/tests/ui-toml/excessive_nesting/auxiliary/proc_macros.rs new file mode 100644 index 00000000000..87620fe91ba --- /dev/null +++ b/tests/ui-toml/excessive_nesting/auxiliary/proc_macros.rs @@ -0,0 +1,476 @@ +//@compile-flags: --emit=link +//@no-prefer-dynamic + +// NOTE: Copied from `ui/auxiliary/proc_macros.rs`, couldn't get `../` to work for some reason + +#![crate_type = "proc-macro"] +#![feature(let_chains)] +#![feature(proc_macro_span)] +#![allow(dead_code)] + +extern crate proc_macro; + +use core::mem; +use proc_macro::{ + token_stream::IntoIter, + Delimiter::{self, Brace, Parenthesis}, + Group, Ident, Literal, Punct, + Spacing::{self, Alone, Joint}, + Span, TokenStream, TokenTree as TT, +}; + +type Result = core::result::Result; + +/// Make a `compile_error!` pointing to the given span. +fn make_error(msg: &str, span: Span) -> TokenStream { + TokenStream::from_iter([ + TT::Ident(Ident::new("compile_error", span)), + TT::Punct(punct_with_span('!', Alone, span)), + TT::Group({ + let mut msg = Literal::string(msg); + msg.set_span(span); + group_with_span(Parenthesis, TokenStream::from_iter([TT::Literal(msg)]), span) + }), + ]) +} + +fn expect_tt(tt: Option, f: impl FnOnce(TT) -> Option, expected: &str, span: Span) -> Result { + match tt { + None => Err(make_error( + &format!("unexpected end of input, expected {expected}"), + span, + )), + Some(tt) => { + let span = tt.span(); + match f(tt) { + Some(x) => Ok(x), + None => Err(make_error(&format!("unexpected token, expected {expected}"), span)), + } + }, + } +} + +fn punct_with_span(c: char, spacing: Spacing, span: Span) -> Punct { + let mut p = Punct::new(c, spacing); + p.set_span(span); + p +} + +fn group_with_span(delimiter: Delimiter, stream: TokenStream, span: Span) -> Group { + let mut g = Group::new(delimiter, stream); + g.set_span(span); + g +} + +/// 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 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 { + let mut iter = input.into_iter(); + let span = iter.next().unwrap().span(); + let mut res = TokenStream::new(); + if let Err(e) = write_with_span(span, iter, &mut res) { + e + } else { + res + } +} + +/// Takes a sequence of tokens and return the tokens with the span set such that they appear to be +/// from an external macro. Tokens may be escaped with either `#ident` or `#(tokens)`. +#[proc_macro] +pub fn external(input: TokenStream) -> TokenStream { + let mut res = TokenStream::new(); + if let Err(e) = write_with_span(Span::mixed_site(), input.into_iter(), &mut res) { + e + } else { + res + } +} + +/// Copies all the tokens, replacing all their spans with the given span. Tokens can be escaped +/// either by `#ident` or `#(tokens)`. +fn write_with_span(s: Span, mut input: IntoIter, out: &mut TokenStream) -> Result<()> { + while let Some(tt) = input.next() { + match tt { + TT::Punct(p) if p.as_char() == ESCAPE_CHAR => { + expect_tt( + input.next(), + |tt| match tt { + tt @ (TT::Ident(_) | TT::Literal(_)) => { + out.extend([tt]); + Some(()) + }, + TT::Punct(mut p) if p.as_char() == ESCAPE_CHAR => { + p.set_span(s); + out.extend([TT::Punct(p)]); + Some(()) + }, + TT::Group(g) if g.delimiter() == Parenthesis => { + out.extend([TT::Group(group_with_span(Delimiter::None, g.stream(), g.span()))]); + Some(()) + }, + _ => None, + }, + "an ident, a literal, or parenthesized tokens", + p.span(), + )?; + }, + TT::Group(g) => { + let mut stream = TokenStream::new(); + write_with_span(s, g.stream().into_iter(), &mut stream)?; + out.extend([TT::Group(group_with_span(g.delimiter(), stream, s))]); + }, + mut tt => { + tt.set_span(s); + out.extend([tt]); + }, + } + } + Ok(()) +} + +/// Within the item this attribute is attached to, an `inline!` macro is available which expands the +/// contained tokens as though they came from a macro expansion. +/// +/// Within the `inline!` macro, any token preceded by `$` is passed as though it were an argument +/// with an automatically chosen fragment specifier. `$ident` will be passed as `ident`, `$1` or +/// `$"literal"` will be passed as `literal`, `$'lt` will be passed as `lifetime`, and `$(...)` will +/// pass the contained tokens as a `tt` sequence (the wrapping parenthesis are removed). If another +/// specifier is required it can be specified within parenthesis like `$(@expr ...)`. This will +/// expand the remaining tokens as a single argument. +/// +/// Multiple `inline!` macros may be nested within each other. This will expand as nested macro +/// calls. However, any arguments will be passed as though they came from the outermost context. +#[proc_macro_attribute] +pub fn inline_macros(args: TokenStream, input: TokenStream) -> TokenStream { + let mut args = args.into_iter(); + let mac_name = match args.next() { + Some(TT::Ident(name)) => Some(name), + Some(tt) => { + return make_error( + "unexpected argument, expected either an ident or no arguments", + tt.span(), + ); + }, + None => None, + }; + if let Some(tt) = args.next() { + return make_error( + "unexpected argument, expected either an ident or no arguments", + tt.span(), + ); + }; + + let mac_name = if let Some(mac_name) = mac_name { + Ident::new(&format!("__inline_mac_{mac_name}"), Span::call_site()) + } else { + let mut input = match LookaheadIter::new(input.clone().into_iter()) { + Some(x) => x, + None => return input, + }; + loop { + match input.next() { + None => break Ident::new("__inline_mac", Span::call_site()), + Some(TT::Ident(kind)) => match &*kind.to_string() { + "impl" => break Ident::new("__inline_mac_impl", Span::call_site()), + kind @ ("struct" | "enum" | "union" | "fn" | "mod" | "trait" | "type" | "const" | "static") => { + if let TT::Ident(name) = &input.tt { + break Ident::new(&format!("__inline_mac_{kind}_{name}"), Span::call_site()); + } else { + break Ident::new(&format!("__inline_mac_{kind}"), Span::call_site()); + } + }, + _ => {}, + }, + _ => {}, + } + } + }; + + let mut expander = Expander::default(); + let mut mac = MacWriter::new(mac_name); + if let Err(e) = expander.expand(input.into_iter(), &mut mac) { + return e; + } + let mut out = TokenStream::new(); + mac.finish(&mut out); + out.extend(expander.expn); + out +} + +/// Wraps a `TokenStream` iterator with a single token lookahead. +struct LookaheadIter { + tt: TT, + iter: IntoIter, +} +impl LookaheadIter { + fn new(mut iter: IntoIter) -> Option { + iter.next().map(|tt| Self { tt, iter }) + } + + /// Get's the lookahead token, replacing it with the next token in the stream. + /// Note: If there isn't a next token, this will not return the lookahead token. + fn next(&mut self) -> Option { + self.iter.next().map(|tt| mem::replace(&mut self.tt, tt)) + } +} + +/// Builds the macro used to implement all the `inline!` macro calls. +struct MacWriter { + name: Ident, + macros: TokenStream, + next_idx: usize, +} +impl MacWriter { + fn new(name: Ident) -> Self { + Self { + name, + macros: TokenStream::new(), + next_idx: 0, + } + } + + /// Inserts a new `inline!` call. + fn insert(&mut self, name_span: Span, bang_span: Span, body: Group, expander: &mut Expander) -> Result<()> { + let idx = self.next_idx; + self.next_idx += 1; + + let mut inner = Expander::for_arm(idx); + inner.expand(body.stream().into_iter(), self)?; + let new_arm = inner.arm.unwrap(); + + self.macros.extend([ + TT::Group(Group::new(Parenthesis, new_arm.args_def)), + TT::Punct(Punct::new('=', Joint)), + TT::Punct(Punct::new('>', Alone)), + TT::Group(Group::new(Parenthesis, inner.expn)), + TT::Punct(Punct::new(';', Alone)), + ]); + + expander.expn.extend([ + TT::Ident({ + let mut name = self.name.clone(); + name.set_span(name_span); + name + }), + TT::Punct(punct_with_span('!', Alone, bang_span)), + ]); + let mut call_body = TokenStream::from_iter([TT::Literal(Literal::usize_unsuffixed(idx))]); + if let Some(arm) = expander.arm.as_mut() { + if !new_arm.args.is_empty() { + arm.add_sub_args(new_arm.args, &mut call_body); + } + } else { + call_body.extend(new_arm.args); + } + let mut g = Group::new(body.delimiter(), call_body); + g.set_span(body.span()); + expander.expn.extend([TT::Group(g)]); + Ok(()) + } + + /// Creates the macro definition. + fn finish(self, out: &mut TokenStream) { + if self.next_idx != 0 { + out.extend([ + TT::Ident(Ident::new("macro_rules", Span::call_site())), + TT::Punct(Punct::new('!', Alone)), + TT::Ident(self.name), + TT::Group(Group::new(Brace, self.macros)), + ]) + } + } +} + +struct MacroArm { + args_def: TokenStream, + args: Vec, +} +impl MacroArm { + fn add_single_arg_def(&mut self, kind: &str, dollar_span: Span, arg_span: Span, out: &mut TokenStream) { + let mut name = Ident::new(&format!("_{}", self.args.len()), Span::call_site()); + self.args_def.extend([ + TT::Punct(Punct::new('$', Alone)), + TT::Ident(name.clone()), + TT::Punct(Punct::new(':', Alone)), + TT::Ident(Ident::new(kind, Span::call_site())), + ]); + name.set_span(arg_span); + out.extend([TT::Punct(punct_with_span('$', Alone, dollar_span)), TT::Ident(name)]); + } + + fn add_parenthesized_arg_def(&mut self, kind: Ident, dollar_span: Span, arg_span: Span, out: &mut TokenStream) { + let mut name = Ident::new(&format!("_{}", self.args.len()), Span::call_site()); + self.args_def.extend([TT::Group(Group::new( + Parenthesis, + TokenStream::from_iter([ + TT::Punct(Punct::new('$', Alone)), + TT::Ident(name.clone()), + TT::Punct(Punct::new(':', Alone)), + TT::Ident(kind), + ]), + ))]); + name.set_span(arg_span); + out.extend([TT::Punct(punct_with_span('$', Alone, dollar_span)), TT::Ident(name)]); + } + + fn add_multi_arg_def(&mut self, dollar_span: Span, arg_span: Span, out: &mut TokenStream) { + let mut name = Ident::new(&format!("_{}", self.args.len()), Span::call_site()); + self.args_def.extend([TT::Group(Group::new( + Parenthesis, + TokenStream::from_iter([ + TT::Punct(Punct::new('$', Alone)), + TT::Group(Group::new( + Parenthesis, + TokenStream::from_iter([ + TT::Punct(Punct::new('$', Alone)), + TT::Ident(name.clone()), + TT::Punct(Punct::new(':', Alone)), + TT::Ident(Ident::new("tt", Span::call_site())), + ]), + )), + TT::Punct(Punct::new('*', Alone)), + ]), + ))]); + name.set_span(arg_span); + out.extend([ + TT::Punct(punct_with_span('$', Alone, dollar_span)), + TT::Group(group_with_span( + Parenthesis, + TokenStream::from_iter([TT::Punct(punct_with_span('$', Alone, dollar_span)), TT::Ident(name)]), + dollar_span, + )), + TT::Punct(punct_with_span('*', Alone, dollar_span)), + ]); + } + + fn add_arg(&mut self, dollar_span: Span, tt: TT, input: &mut IntoIter, out: &mut TokenStream) -> Result<()> { + match tt { + TT::Punct(p) if p.as_char() == ESCAPE_CHAR => out.extend([TT::Punct(p)]), + TT::Punct(p) if p.as_char() == '\'' && p.spacing() == Joint => { + let lt_name = expect_tt( + input.next(), + |tt| match tt { + TT::Ident(x) => Some(x), + _ => None, + }, + "lifetime name", + p.span(), + )?; + let arg_span = p.span().join(lt_name.span()).unwrap_or(p.span()); + self.add_single_arg_def("lifetime", dollar_span, arg_span, out); + self.args.extend([TT::Punct(p), TT::Ident(lt_name)]); + }, + TT::Ident(x) => { + self.add_single_arg_def("ident", dollar_span, x.span(), out); + self.args.push(TT::Ident(x)); + }, + TT::Literal(x) => { + self.add_single_arg_def("literal", dollar_span, x.span(), out); + self.args.push(TT::Literal(x)); + }, + TT::Group(g) if g.delimiter() == Parenthesis => { + let mut inner = g.stream().into_iter(); + if let Some(TT::Punct(p)) = inner.next() + && p.as_char() == '@' + { + let kind = expect_tt( + inner.next(), + |tt| match tt { + TT::Ident(kind) => Some(kind), + _ => None, + }, + "a macro fragment specifier", + p.span(), + )?; + self.add_parenthesized_arg_def(kind, dollar_span, g.span(), out); + self.args.push(TT::Group(group_with_span(Parenthesis, inner.collect(), g.span()))) + } else { + self.add_multi_arg_def(dollar_span, g.span(), out); + self.args.push(TT::Group(g)); + } + }, + tt => return Err(make_error("unsupported escape", tt.span())), + }; + Ok(()) + } + + fn add_sub_args(&mut self, args: Vec, out: &mut TokenStream) { + self.add_multi_arg_def(Span::call_site(), Span::call_site(), out); + self.args + .extend([TT::Group(Group::new(Parenthesis, TokenStream::from_iter(args)))]); + } +} + +#[derive(Default)] +struct Expander { + arm: Option, + expn: TokenStream, +} +impl Expander { + fn for_arm(idx: usize) -> Self { + Self { + arm: Some(MacroArm { + args_def: TokenStream::from_iter([TT::Literal(Literal::usize_unsuffixed(idx))]), + args: Vec::new(), + }), + expn: TokenStream::new(), + } + } + + fn write_tt(&mut self, tt: TT, mac: &mut MacWriter) -> Result<()> { + match tt { + TT::Group(g) => { + let outer = mem::take(&mut self.expn); + self.expand(g.stream().into_iter(), mac)?; + let inner = mem::replace(&mut self.expn, outer); + self.expn + .extend([TT::Group(group_with_span(g.delimiter(), inner, g.span()))]); + }, + tt => self.expn.extend([tt]), + } + Ok(()) + } + + fn expand(&mut self, input: IntoIter, mac: &mut MacWriter) -> Result<()> { + let Some(mut input) = LookaheadIter::new(input) else { + return Ok(()); + }; + while let Some(tt) = input.next() { + if let TT::Punct(p) = &tt + && p.as_char() == ESCAPE_CHAR + && let Some(arm) = self.arm.as_mut() + { + arm.add_arg(p.span(), mem::replace(&mut input.tt, tt), &mut input.iter, &mut self.expn)?; + if input.next().is_none() { + return Ok(()); + } + } else if let TT::Punct(p) = &input.tt + && p.as_char() == '!' + && let TT::Ident(name) = &tt + && name.to_string() == "inline" + { + let g = expect_tt( + input.iter.next(), + |tt| match tt { + TT::Group(g) => Some(g), + _ => None, + }, + "macro arguments", + p.span(), + )?; + mac.insert(name.span(), p.span(), g, self)?; + if input.next().is_none() { + return Ok(()); + } + } else { + self.write_tt(tt, mac)?; + } + } + self.write_tt(input.tt, mac) + } +} diff --git a/tests/ui-toml/excessive_nesting/default/clippy.toml b/tests/ui-toml/excessive_nesting/default/clippy.toml deleted file mode 100644 index e8b115a0f7c..00000000000 --- a/tests/ui-toml/excessive_nesting/default/clippy.toml +++ /dev/null @@ -1 +0,0 @@ -excessive-nesting-threshold = 0 diff --git a/tests/ui-toml/excessive_nesting/excessive_nesting.stderr b/tests/ui-toml/excessive_nesting/excessive_nesting.above.stderr similarity index 55% rename from tests/ui-toml/excessive_nesting/excessive_nesting.stderr rename to tests/ui-toml/excessive_nesting/excessive_nesting.above.stderr index f1db396fe48..0ec41fbaa07 100644 --- a/tests/ui-toml/excessive_nesting/excessive_nesting.stderr +++ b/tests/ui-toml/excessive_nesting/excessive_nesting.above.stderr @@ -1,369 +1,314 @@ error: this block is too nested - --> $DIR/auxiliary/mod.rs:6:13 + --> $DIR/excessive_nesting.rs:23:25 | -LL | / mod d { -LL | | mod e {} -LL | | } - | |_____________^ +LL | let w = { 3 }; + | ^^^^^ | = help: try refactoring your code to minimize nesting = note: `-D clippy::excessive-nesting` implied by `-D warnings` error: this block is too nested - --> $DIR/auxiliary/mod.rs:15:7 + --> $DIR/excessive_nesting.rs:69:17 | -LL | {{{}}} - | ^^ - | - = help: try refactoring your code to minimize nesting - -error: this block is too nested - --> $DIR/excessive_nesting.rs:21:21 - | -LL | let z = { - | _____________________^ -LL | | let w = { 3 }; -LL | | w -LL | | }; - | |_____________^ - | - = help: try refactoring your code to minimize nesting - -error: this block is too nested - --> $DIR/excessive_nesting.rs:65:24 - | -LL | pub fn b() { - | ________________________^ -LL | | struct C; -LL | | -LL | | impl C { +LL | / impl C { LL | | pub fn c() {} LL | | } -LL | | } - | |_____________^ + | |_________________^ | = help: try refactoring your code to minimize nesting error: this block is too nested - --> $DIR/excessive_nesting.rs:81:21 + --> $DIR/excessive_nesting.rs:83:25 | -LL | fn cc() { - | _____________________^ -LL | | let x = { 1 }; // not a warning, but cc is -LL | | } - | |_____________^ +LL | let x = { 1 }; // not a warning, but cc is + | ^^^^^ | = help: try refactoring your code to minimize nesting error: this block is too nested - --> $DIR/excessive_nesting.rs:85:21 + --> $DIR/excessive_nesting.rs:100:17 | -LL | let x = { 1 }; // warning - | ^^^^^ - | - = help: try refactoring your code to minimize nesting - -error: this block is too nested - --> $DIR/excessive_nesting.rs:98:13 - | -LL | / pub mod d { -LL | | pub mod e { +LL | / pub mod e { LL | | pub mod f {} LL | | } // not here -LL | | } // only warning should be here - | |_____________^ + | |_________________^ | = help: try refactoring your code to minimize nesting error: this block is too nested - --> $DIR/excessive_nesting.rs:112:17 + --> $DIR/excessive_nesting.rs:113:18 | LL | a_but_not({{{{{{{{0}}}}}}}}); - | ^^^^^^^^^^^^^ + | ^^^^^^^^^^^ | = help: try refactoring your code to minimize nesting error: this block is too nested - --> $DIR/excessive_nesting.rs:113:11 + --> $DIR/excessive_nesting.rs:114:12 | LL | a.a({{{{{{{{{0}}}}}}}}}); - | ^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^ | = help: try refactoring your code to minimize nesting error: this block is too nested - --> $DIR/excessive_nesting.rs:114:11 + --> $DIR/excessive_nesting.rs:115:12 | LL | (0, {{{{{{{1}}}}}}}); - | ^^^^^^^^^^^ + | ^^^^^^^^^ | = help: try refactoring your code to minimize nesting error: this block is too nested - --> $DIR/excessive_nesting.rs:118:21 + --> $DIR/excessive_nesting.rs:120:25 | -LL | if true { - | _____________________^ -LL | | if true { +LL | if true { + | _________________________^ LL | | if true { LL | | LL | | } LL | | } -LL | | } - | |_____________^ + | |_________________^ | = help: try refactoring your code to minimize nesting error: this block is too nested - --> $DIR/excessive_nesting.rs:130:25 + --> $DIR/excessive_nesting.rs:132:29 | -LL | let y = (|| { - | _________________________^ -LL | | let z = (|| { +LL | let z = (|| { + | _____________________________^ LL | | let w = { 3 }; LL | | w LL | | })(); -LL | | z -LL | | })(); - | |_____________^ + | |_________________^ | = help: try refactoring your code to minimize nesting error: this block is too nested - --> $DIR/excessive_nesting.rs:145:36 - | -LL | !{boo as u32 + !{boo as u32 + !{boo as u32}}}; - | ^^^^^^^^^^^^ - | - = help: try refactoring your code to minimize nesting - -error: this block is too nested - --> $DIR/excessive_nesting.rs:149:12 + --> $DIR/excessive_nesting.rs:151:13 | LL | y += {{{{{5}}}}}; - | ^^^^^^^ + | ^^^^^ | = help: try refactoring your code to minimize nesting error: this block is too nested - --> $DIR/excessive_nesting.rs:150:19 + --> $DIR/excessive_nesting.rs:152:20 | LL | let z = y + {{{{{{{{{5}}}}}}}}}; - | ^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^ | = help: try refactoring your code to minimize nesting error: this block is too nested - --> $DIR/excessive_nesting.rs:151:11 + --> $DIR/excessive_nesting.rs:153:12 | LL | [0, {{{{{{{{{{0}}}}}}}}}}]; - | ^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^ | = help: try refactoring your code to minimize nesting error: this block is too nested - --> $DIR/excessive_nesting.rs:152:24 + --> $DIR/excessive_nesting.rs:154:25 | LL | let mut xx = [0; {{{{{{{{100}}}}}}}}]; - | ^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^ | = help: try refactoring your code to minimize nesting error: this block is too nested - --> $DIR/excessive_nesting.rs:153:10 + --> $DIR/excessive_nesting.rs:155:11 | LL | xx[{{{{{{{{{{{{{{{{{{{{{{{{3}}}}}}}}}}}}}}}}}}}}}}}}]; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = help: try refactoring your code to minimize nesting error: this block is too nested - --> $DIR/excessive_nesting.rs:154:12 + --> $DIR/excessive_nesting.rs:156:13 | LL | &mut {{{{{{{{{{y}}}}}}}}}}; - | ^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^ | = help: try refactoring your code to minimize nesting error: this block is too nested - --> $DIR/excessive_nesting.rs:156:16 + --> $DIR/excessive_nesting.rs:158:17 | LL | for i in {{{{xx}}}} {{{{{{{{}}}}}}}} - | ^^^^^^ + | ^^^^ | = help: try refactoring your code to minimize nesting error: this block is too nested - --> $DIR/excessive_nesting.rs:156:27 + --> $DIR/excessive_nesting.rs:158:28 | LL | for i in {{{{xx}}}} {{{{{{{{}}}}}}}} - | ^^^^^^^^^^^^ + | ^^^^^^^^^^ | = help: try refactoring your code to minimize nesting error: this block is too nested - --> $DIR/excessive_nesting.rs:158:27 + --> $DIR/excessive_nesting.rs:160:28 | LL | while let Some(i) = {{{{{{Some(1)}}}}}} {{{{{{{}}}}}}} - | ^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^ | = help: try refactoring your code to minimize nesting error: this block is too nested - --> $DIR/excessive_nesting.rs:158:47 + --> $DIR/excessive_nesting.rs:160:48 | LL | while let Some(i) = {{{{{{Some(1)}}}}}} {{{{{{{}}}}}}} - | ^^^^^^^^^^ + | ^^^^^^^^ | = help: try refactoring your code to minimize nesting error: this block is too nested - --> $DIR/excessive_nesting.rs:160:13 + --> $DIR/excessive_nesting.rs:162:14 | LL | while {{{{{{{{true}}}}}}}} {{{{{{{{{}}}}}}}}} - | ^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^ | = help: try refactoring your code to minimize nesting error: this block is too nested - --> $DIR/excessive_nesting.rs:160:34 + --> $DIR/excessive_nesting.rs:162:35 | LL | while {{{{{{{{true}}}}}}}} {{{{{{{{{}}}}}}}}} - | ^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^ | = help: try refactoring your code to minimize nesting error: this block is too nested - --> $DIR/excessive_nesting.rs:162:22 + --> $DIR/excessive_nesting.rs:164:23 | LL | let d = D { d: {{{{{{{{{{{{{{{{{{{{{{{3}}}}}}}}}}}}}}}}}}}}}}} }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = help: try refactoring your code to minimize nesting error: this block is too nested - --> $DIR/excessive_nesting.rs:164:7 + --> $DIR/excessive_nesting.rs:166:8 | LL | {{{{1;}}}}..{{{{{{3}}}}}}; - | ^^^^^^ + | ^^^^ | = help: try refactoring your code to minimize nesting error: this block is too nested - --> $DIR/excessive_nesting.rs:164:19 + --> $DIR/excessive_nesting.rs:166:20 | LL | {{{{1;}}}}..{{{{{{3}}}}}}; - | ^^^^^^^^^ + | ^^^^^^^ | = help: try refactoring your code to minimize nesting error: this block is too nested - --> $DIR/excessive_nesting.rs:165:7 + --> $DIR/excessive_nesting.rs:167:8 | LL | {{{{1;}}}}..={{{{{{{{{{{{{{{{{{{{{{{{{{6}}}}}}}}}}}}}}}}}}}}}}}}}}; - | ^^^^^^ + | ^^^^ | = help: try refactoring your code to minimize nesting error: this block is too nested - --> $DIR/excessive_nesting.rs:165:20 + --> $DIR/excessive_nesting.rs:167:21 | LL | {{{{1;}}}}..={{{{{{{{{{{{{{{{{{{{{{{{{{6}}}}}}}}}}}}}}}}}}}}}}}}}}; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = help: try refactoring your code to minimize nesting error: this block is too nested - --> $DIR/excessive_nesting.rs:166:9 + --> $DIR/excessive_nesting.rs:168:10 | LL | ..{{{{{{{5}}}}}}}; - | ^^^^^^^^^^^ + | ^^^^^^^^^ | = help: try refactoring your code to minimize nesting error: this block is too nested - --> $DIR/excessive_nesting.rs:167:10 + --> $DIR/excessive_nesting.rs:169:11 | LL | ..={{{{{3}}}}}; - | ^^^^^^^ + | ^^^^^ | = help: try refactoring your code to minimize nesting error: this block is too nested - --> $DIR/excessive_nesting.rs:168:7 + --> $DIR/excessive_nesting.rs:170:8 | LL | {{{{{1;}}}}}..; - | ^^^^^^^^ + | ^^^^^^ | = help: try refactoring your code to minimize nesting error: this block is too nested - --> $DIR/excessive_nesting.rs:170:19 + --> $DIR/excessive_nesting.rs:172:20 | LL | loop { break {{{{1}}}} }; - | ^^^^^^^ - | - = help: try refactoring your code to minimize nesting - -error: this block is too nested - --> $DIR/excessive_nesting.rs:171:12 - | -LL | loop {{{{{{}}}}}} - | ^^^^^^^^ + | ^^^^^ | = help: try refactoring your code to minimize nesting error: this block is too nested --> $DIR/excessive_nesting.rs:173:13 | -LL | match {{{{{{true}}}}}} { - | ^^^^^^^^^^^^ +LL | loop {{{{{{}}}}}} + | ^^^^^^ | = help: try refactoring your code to minimize nesting error: this block is too nested - --> $DIR/excessive_nesting.rs:174:19 + --> $DIR/excessive_nesting.rs:175:14 + | +LL | match {{{{{{true}}}}}} { + | ^^^^^^^^^^ + | + = help: try refactoring your code to minimize nesting + +error: this block is too nested + --> $DIR/excessive_nesting.rs:176:20 | LL | true => {{{{}}}}, - | ^^^^ + | ^^ | = help: try refactoring your code to minimize nesting error: this block is too nested - --> $DIR/excessive_nesting.rs:175:20 + --> $DIR/excessive_nesting.rs:177:21 | LL | false => {{{{}}}}, - | ^^^^ + | ^^ | = help: try refactoring your code to minimize nesting error: this block is too nested - --> $DIR/excessive_nesting.rs:180:13 + --> $DIR/excessive_nesting.rs:183:17 | -LL | / { -LL | | { +LL | / { LL | | println!("warning! :)"); LL | | } -LL | | } - | |_____________^ + | |_________________^ | = help: try refactoring your code to minimize nesting error: this block is too nested - --> $DIR/excessive_nesting.rs:190:27 + --> $DIR/excessive_nesting.rs:192:28 | LL | async fn c() -> u32 {{{{{{{0}}}}}}} - | ^^^^^^^^^^^ + | ^^^^^^^^^ | = help: try refactoring your code to minimize nesting error: this block is too nested - --> $DIR/excessive_nesting.rs:196:7 + --> $DIR/excessive_nesting.rs:198:8 | LL | {{{{b().await}}}}; - | ^^^^^^^^^^^^^ + | ^^^^^^^^^^^ | = help: try refactoring your code to minimize nesting -error: aborting due to 41 previous errors +error: aborting due to 37 previous errors diff --git a/tests/ui-toml/excessive_nesting/excessive_nesting.default.stderr b/tests/ui-toml/excessive_nesting/excessive_nesting.default.stderr deleted file mode 100644 index e69de29bb2d..00000000000 diff --git a/tests/ui-toml/excessive_nesting/excessive_nesting.rs b/tests/ui-toml/excessive_nesting/excessive_nesting.rs index 5e436b97ee8..432c4132b57 100644 --- a/tests/ui-toml/excessive_nesting/excessive_nesting.rs +++ b/tests/ui-toml/excessive_nesting/excessive_nesting.rs @@ -1,7 +1,7 @@ -//@aux-build:macro_rules.rs -//@revisions: set default +//@aux-build:proc_macros.rs +//@revisions: set above //@[set] rustc-env:CLIPPY_CONF_DIR=tests/ui-toml/excessive_nesting/set -//@[default] rustc-env:CLIPPY_CONF_DIR=tests/ui-toml/excessive_nesting/default +//@[above] rustc-env:CLIPPY_CONF_DIR=tests/ui-toml/excessive_nesting/above #![rustfmt::skip] #![feature(custom_inner_attributes)] #![allow(unused)] @@ -13,10 +13,8 @@ #![warn(clippy::excessive_nesting)] #![allow(clippy::collapsible_if)] -mod auxiliary; - #[macro_use] -extern crate macro_rules; +extern crate proc_macros; static X: u32 = { let x = { @@ -142,7 +140,8 @@ fn main() { x })(); - excessive_nesting!(); // ensure this isn't linted in external macros + external! { {{{{{{{{{{{{{{{{}}}}}}}}}}}}}}}} }; // ensure this isn't linted in external macros + with_span! { span {{{{{{{{{{{{}}}}}}}}}}}} }; // don't lint for proc macros xx!(); // ensure this is never linted let boo = true; !{boo as u32 + !{boo as u32 + !{boo as u32}}}; diff --git a/tests/ui-toml/excessive_nesting/excessive_nesting.set.stderr b/tests/ui-toml/excessive_nesting/excessive_nesting.set.stderr index 1f069437dfe..237cc6c4a90 100644 --- a/tests/ui-toml/excessive_nesting/excessive_nesting.set.stderr +++ b/tests/ui-toml/excessive_nesting/excessive_nesting.set.stderr @@ -1,24 +1,5 @@ error: this block is too nested - --> $DIR/auxiliary/mod.rs:6:13 - | -LL | / mod d { -LL | | mod e {} -LL | | } - | |_____________^ - | - = help: try refactoring your code to minimize nesting - = note: `-D clippy::excessive-nesting` implied by `-D warnings` - -error: this block is too nested - --> $DIR/auxiliary/mod.rs:15:7 - | -LL | {{{}}} - | ^^ - | - = help: try refactoring your code to minimize nesting - -error: this block is too nested - --> $DIR/excessive_nesting.rs:24:21 + --> $DIR/excessive_nesting.rs:22:21 | LL | let z = { | _____________________^ @@ -28,9 +9,10 @@ LL | | }; | |_____________^ | = help: try refactoring your code to minimize nesting + = note: `-D clippy::excessive-nesting` implied by `-D warnings` error: this block is too nested - --> $DIR/excessive_nesting.rs:68:24 + --> $DIR/excessive_nesting.rs:66:24 | LL | pub fn b() { | ________________________^ @@ -45,7 +27,7 @@ LL | | } = help: try refactoring your code to minimize nesting error: this block is too nested - --> $DIR/excessive_nesting.rs:84:21 + --> $DIR/excessive_nesting.rs:82:21 | LL | fn cc() { | _____________________^ @@ -56,7 +38,7 @@ LL | | } = help: try refactoring your code to minimize nesting error: this block is too nested - --> $DIR/excessive_nesting.rs:88:21 + --> $DIR/excessive_nesting.rs:86:21 | LL | let x = { 1 }; // warning | ^^^^^ @@ -64,7 +46,7 @@ LL | let x = { 1 }; // warning = help: try refactoring your code to minimize nesting error: this block is too nested - --> $DIR/excessive_nesting.rs:101:13 + --> $DIR/excessive_nesting.rs:99:13 | LL | / pub mod d { LL | | pub mod e { @@ -76,7 +58,7 @@ LL | | } // only warning should be here = help: try refactoring your code to minimize nesting error: this block is too nested - --> $DIR/excessive_nesting.rs:115:17 + --> $DIR/excessive_nesting.rs:113:17 | LL | a_but_not({{{{{{{{0}}}}}}}}); | ^^^^^^^^^^^^^ @@ -84,7 +66,7 @@ LL | a_but_not({{{{{{{{0}}}}}}}}); = help: try refactoring your code to minimize nesting error: this block is too nested - --> $DIR/excessive_nesting.rs:116:11 + --> $DIR/excessive_nesting.rs:114:11 | LL | a.a({{{{{{{{{0}}}}}}}}}); | ^^^^^^^^^^^^^^^ @@ -92,7 +74,7 @@ LL | a.a({{{{{{{{{0}}}}}}}}}); = help: try refactoring your code to minimize nesting error: this block is too nested - --> $DIR/excessive_nesting.rs:117:11 + --> $DIR/excessive_nesting.rs:115:11 | LL | (0, {{{{{{{1}}}}}}}); | ^^^^^^^^^^^ @@ -100,7 +82,7 @@ LL | (0, {{{{{{{1}}}}}}}); = help: try refactoring your code to minimize nesting error: this block is too nested - --> $DIR/excessive_nesting.rs:121:21 + --> $DIR/excessive_nesting.rs:119:21 | LL | if true { | _____________________^ @@ -115,7 +97,7 @@ LL | | } = help: try refactoring your code to minimize nesting error: this block is too nested - --> $DIR/excessive_nesting.rs:133:25 + --> $DIR/excessive_nesting.rs:131:25 | LL | let y = (|| { | _________________________^ @@ -130,7 +112,7 @@ LL | | })(); = help: try refactoring your code to minimize nesting error: this block is too nested - --> $DIR/excessive_nesting.rs:148:36 + --> $DIR/excessive_nesting.rs:147:36 | LL | !{boo as u32 + !{boo as u32 + !{boo as u32}}}; | ^^^^^^^^^^^^ @@ -138,7 +120,7 @@ LL | !{boo as u32 + !{boo as u32 + !{boo as u32}}}; = help: try refactoring your code to minimize nesting error: this block is too nested - --> $DIR/excessive_nesting.rs:152:12 + --> $DIR/excessive_nesting.rs:151:12 | LL | y += {{{{{5}}}}}; | ^^^^^^^ @@ -146,7 +128,7 @@ LL | y += {{{{{5}}}}}; = help: try refactoring your code to minimize nesting error: this block is too nested - --> $DIR/excessive_nesting.rs:153:19 + --> $DIR/excessive_nesting.rs:152:19 | LL | let z = y + {{{{{{{{{5}}}}}}}}}; | ^^^^^^^^^^^^^^^ @@ -154,7 +136,7 @@ LL | let z = y + {{{{{{{{{5}}}}}}}}}; = help: try refactoring your code to minimize nesting error: this block is too nested - --> $DIR/excessive_nesting.rs:154:11 + --> $DIR/excessive_nesting.rs:153:11 | LL | [0, {{{{{{{{{{0}}}}}}}}}}]; | ^^^^^^^^^^^^^^^^^ @@ -162,7 +144,7 @@ LL | [0, {{{{{{{{{{0}}}}}}}}}}]; = help: try refactoring your code to minimize nesting error: this block is too nested - --> $DIR/excessive_nesting.rs:155:24 + --> $DIR/excessive_nesting.rs:154:24 | LL | let mut xx = [0; {{{{{{{{100}}}}}}}}]; | ^^^^^^^^^^^^^^^ @@ -170,7 +152,7 @@ LL | let mut xx = [0; {{{{{{{{100}}}}}}}}]; = help: try refactoring your code to minimize nesting error: this block is too nested - --> $DIR/excessive_nesting.rs:156:10 + --> $DIR/excessive_nesting.rs:155:10 | LL | xx[{{{{{{{{{{{{{{{{{{{{{{{{3}}}}}}}}}}}}}}}}}}}}}}}}]; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -178,7 +160,7 @@ LL | xx[{{{{{{{{{{{{{{{{{{{{{{{{3}}}}}}}}}}}}}}}}}}}}}}}}]; = help: try refactoring your code to minimize nesting error: this block is too nested - --> $DIR/excessive_nesting.rs:157:12 + --> $DIR/excessive_nesting.rs:156:12 | LL | &mut {{{{{{{{{{y}}}}}}}}}}; | ^^^^^^^^^^^^^^^^^ @@ -186,7 +168,7 @@ LL | &mut {{{{{{{{{{y}}}}}}}}}}; = help: try refactoring your code to minimize nesting error: this block is too nested - --> $DIR/excessive_nesting.rs:159:16 + --> $DIR/excessive_nesting.rs:158:16 | LL | for i in {{{{xx}}}} {{{{{{{{}}}}}}}} | ^^^^^^ @@ -194,7 +176,7 @@ LL | for i in {{{{xx}}}} {{{{{{{{}}}}}}}} = help: try refactoring your code to minimize nesting error: this block is too nested - --> $DIR/excessive_nesting.rs:159:27 + --> $DIR/excessive_nesting.rs:158:27 | LL | for i in {{{{xx}}}} {{{{{{{{}}}}}}}} | ^^^^^^^^^^^^ @@ -202,7 +184,7 @@ LL | for i in {{{{xx}}}} {{{{{{{{}}}}}}}} = help: try refactoring your code to minimize nesting error: this block is too nested - --> $DIR/excessive_nesting.rs:161:27 + --> $DIR/excessive_nesting.rs:160:27 | LL | while let Some(i) = {{{{{{Some(1)}}}}}} {{{{{{{}}}}}}} | ^^^^^^^^^^^^^^^ @@ -210,7 +192,7 @@ LL | while let Some(i) = {{{{{{Some(1)}}}}}} {{{{{{{}}}}}}} = help: try refactoring your code to minimize nesting error: this block is too nested - --> $DIR/excessive_nesting.rs:161:47 + --> $DIR/excessive_nesting.rs:160:47 | LL | while let Some(i) = {{{{{{Some(1)}}}}}} {{{{{{{}}}}}}} | ^^^^^^^^^^ @@ -218,7 +200,7 @@ LL | while let Some(i) = {{{{{{Some(1)}}}}}} {{{{{{{}}}}}}} = help: try refactoring your code to minimize nesting error: this block is too nested - --> $DIR/excessive_nesting.rs:163:13 + --> $DIR/excessive_nesting.rs:162:13 | LL | while {{{{{{{{true}}}}}}}} {{{{{{{{{}}}}}}}}} | ^^^^^^^^^^^^^^^^ @@ -226,7 +208,7 @@ LL | while {{{{{{{{true}}}}}}}} {{{{{{{{{}}}}}}}}} = help: try refactoring your code to minimize nesting error: this block is too nested - --> $DIR/excessive_nesting.rs:163:34 + --> $DIR/excessive_nesting.rs:162:34 | LL | while {{{{{{{{true}}}}}}}} {{{{{{{{{}}}}}}}}} | ^^^^^^^^^^^^^^ @@ -234,7 +216,7 @@ LL | while {{{{{{{{true}}}}}}}} {{{{{{{{{}}}}}}}}} = help: try refactoring your code to minimize nesting error: this block is too nested - --> $DIR/excessive_nesting.rs:165:22 + --> $DIR/excessive_nesting.rs:164:22 | LL | let d = D { d: {{{{{{{{{{{{{{{{{{{{{{{3}}}}}}}}}}}}}}}}}}}}}}} }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -242,7 +224,7 @@ LL | let d = D { d: {{{{{{{{{{{{{{{{{{{{{{{3}}}}}}}}}}}}}}}}}}}}}}} }; = help: try refactoring your code to minimize nesting error: this block is too nested - --> $DIR/excessive_nesting.rs:167:7 + --> $DIR/excessive_nesting.rs:166:7 | LL | {{{{1;}}}}..{{{{{{3}}}}}}; | ^^^^^^ @@ -250,7 +232,7 @@ LL | {{{{1;}}}}..{{{{{{3}}}}}}; = help: try refactoring your code to minimize nesting error: this block is too nested - --> $DIR/excessive_nesting.rs:167:19 + --> $DIR/excessive_nesting.rs:166:19 | LL | {{{{1;}}}}..{{{{{{3}}}}}}; | ^^^^^^^^^ @@ -258,7 +240,7 @@ LL | {{{{1;}}}}..{{{{{{3}}}}}}; = help: try refactoring your code to minimize nesting error: this block is too nested - --> $DIR/excessive_nesting.rs:168:7 + --> $DIR/excessive_nesting.rs:167:7 | LL | {{{{1;}}}}..={{{{{{{{{{{{{{{{{{{{{{{{{{6}}}}}}}}}}}}}}}}}}}}}}}}}}; | ^^^^^^ @@ -266,7 +248,7 @@ LL | {{{{1;}}}}..={{{{{{{{{{{{{{{{{{{{{{{{{{6}}}}}}}}}}}}}}}}}}}}}}}}}}; = help: try refactoring your code to minimize nesting error: this block is too nested - --> $DIR/excessive_nesting.rs:168:20 + --> $DIR/excessive_nesting.rs:167:20 | LL | {{{{1;}}}}..={{{{{{{{{{{{{{{{{{{{{{{{{{6}}}}}}}}}}}}}}}}}}}}}}}}}}; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -274,7 +256,7 @@ LL | {{{{1;}}}}..={{{{{{{{{{{{{{{{{{{{{{{{{{6}}}}}}}}}}}}}}}}}}}}}}}}}}; = help: try refactoring your code to minimize nesting error: this block is too nested - --> $DIR/excessive_nesting.rs:169:9 + --> $DIR/excessive_nesting.rs:168:9 | LL | ..{{{{{{{5}}}}}}}; | ^^^^^^^^^^^ @@ -282,7 +264,7 @@ LL | ..{{{{{{{5}}}}}}}; = help: try refactoring your code to minimize nesting error: this block is too nested - --> $DIR/excessive_nesting.rs:170:10 + --> $DIR/excessive_nesting.rs:169:10 | LL | ..={{{{{3}}}}}; | ^^^^^^^ @@ -290,7 +272,7 @@ LL | ..={{{{{3}}}}}; = help: try refactoring your code to minimize nesting error: this block is too nested - --> $DIR/excessive_nesting.rs:171:7 + --> $DIR/excessive_nesting.rs:170:7 | LL | {{{{{1;}}}}}..; | ^^^^^^^^ @@ -298,7 +280,7 @@ LL | {{{{{1;}}}}}..; = help: try refactoring your code to minimize nesting error: this block is too nested - --> $DIR/excessive_nesting.rs:173:19 + --> $DIR/excessive_nesting.rs:172:19 | LL | loop { break {{{{1}}}} }; | ^^^^^^^ @@ -306,7 +288,7 @@ LL | loop { break {{{{1}}}} }; = help: try refactoring your code to minimize nesting error: this block is too nested - --> $DIR/excessive_nesting.rs:174:12 + --> $DIR/excessive_nesting.rs:173:12 | LL | loop {{{{{{}}}}}} | ^^^^^^^^ @@ -314,7 +296,7 @@ LL | loop {{{{{{}}}}}} = help: try refactoring your code to minimize nesting error: this block is too nested - --> $DIR/excessive_nesting.rs:176:13 + --> $DIR/excessive_nesting.rs:175:13 | LL | match {{{{{{true}}}}}} { | ^^^^^^^^^^^^ @@ -322,7 +304,7 @@ LL | match {{{{{{true}}}}}} { = help: try refactoring your code to minimize nesting error: this block is too nested - --> $DIR/excessive_nesting.rs:177:19 + --> $DIR/excessive_nesting.rs:176:19 | LL | true => {{{{}}}}, | ^^^^ @@ -330,7 +312,7 @@ LL | true => {{{{}}}}, = help: try refactoring your code to minimize nesting error: this block is too nested - --> $DIR/excessive_nesting.rs:178:20 + --> $DIR/excessive_nesting.rs:177:20 | LL | false => {{{{}}}}, | ^^^^ @@ -338,7 +320,7 @@ LL | false => {{{{}}}}, = help: try refactoring your code to minimize nesting error: this block is too nested - --> $DIR/excessive_nesting.rs:183:13 + --> $DIR/excessive_nesting.rs:182:13 | LL | / { LL | | { @@ -350,7 +332,7 @@ LL | | } = help: try refactoring your code to minimize nesting error: this block is too nested - --> $DIR/excessive_nesting.rs:193:27 + --> $DIR/excessive_nesting.rs:192:27 | LL | async fn c() -> u32 {{{{{{{0}}}}}}} | ^^^^^^^^^^^ @@ -358,12 +340,12 @@ LL | async fn c() -> u32 {{{{{{{0}}}}}}} = help: try refactoring your code to minimize nesting error: this block is too nested - --> $DIR/excessive_nesting.rs:199:7 + --> $DIR/excessive_nesting.rs:198:7 | LL | {{{{b().await}}}}; | ^^^^^^^^^^^^^ | = help: try refactoring your code to minimize nesting -error: aborting due to 41 previous errors +error: aborting due to 39 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 28b6e7aa824..5ec6f3decc3 100644 --- a/tests/ui-toml/toml_unknown_key/conf_unknown_key.stderr +++ b/tests/ui-toml/toml_unknown_key/conf_unknown_key.stderr @@ -86,6 +86,7 @@ error: error reading Clippy's configuration file: unknown field `barfoo`, expect enforced-import-renames enum-variant-name-threshold enum-variant-size-threshold + excessive-nesting-threshold future-size-threshold ignore-interior-mutability large-error-threshold From 0e233492d31cd0e213f284414fc4bdc1372df777 Mon Sep 17 00:00:00 2001 From: Centri3 <114838443+Centri3@users.noreply.github.com> Date: Wed, 7 Jun 2023 21:43:28 -0500 Subject: [PATCH 095/310] use trait solver instead; created spaghetti code --- clippy_utils/src/lib.rs | 1 + clippy_utils/src/qualify_min_const_fn.rs | 80 +++++++++++-------- .../ui/missing_const_for_fn/cant_be_const.rs | 4 +- 3 files changed, 50 insertions(+), 35 deletions(-) diff --git a/clippy_utils/src/lib.rs b/clippy_utils/src/lib.rs index 8c883445a79..e600dc58c9d 100644 --- a/clippy_utils/src/lib.rs +++ b/clippy_utils/src/lib.rs @@ -21,6 +21,7 @@ extern crate rustc_ast; extern crate rustc_ast_pretty; extern crate rustc_attr; extern crate rustc_data_structures; +extern crate rustc_const_eval; // The `rustc_driver` crate seems to be required in order to use the `rust_ast` crate. #[allow(unused_extern_crates)] extern crate rustc_driver; diff --git a/clippy_utils/src/qualify_min_const_fn.rs b/clippy_utils/src/qualify_min_const_fn.rs index a38045cdcd1..cdaf8985d5e 100644 --- a/clippy_utils/src/qualify_min_const_fn.rs +++ b/clippy_utils/src/qualify_min_const_fn.rs @@ -4,17 +4,24 @@ // differ from the time of `rustc` even if the name stays the same. use crate::msrvs::Msrv; +use hir::{Constness, LangItem}; +use rustc_const_eval::transform::check_consts::ConstCx; use rustc_hir as hir; use rustc_hir::def_id::DefId; +use rustc_infer::infer::TyCtxtInferExt; +use rustc_infer::traits::Obligation; use rustc_middle::mir::{ Body, CastKind, NonDivergingIntrinsic, NullOp, Operand, Place, ProjectionElem, Rvalue, Statement, StatementKind, Terminator, TerminatorKind, }; +use rustc_middle::traits::ObligationCause; use rustc_middle::ty::subst::GenericArgKind; use rustc_middle::ty::{self, adjustment::PointerCast, Ty, TyCtxt}; +use rustc_middle::ty::{BoundConstness, TraitRef}; use rustc_semver::RustcVersion; use rustc_span::symbol::sym; use rustc_span::Span; +use rustc_trait_selection::traits::SelectionContext; use std::borrow::Cow; type McfResult = Result<(), (Span, Cow<'static, str>)>; @@ -52,14 +59,13 @@ pub fn is_min_const_fn<'tcx>(tcx: TyCtxt<'tcx>, body: &Body<'tcx>, msrv: &Msrv) } for local in &body.local_decls { - check_ty(tcx, local.ty, local.source_info.span, false)?; + check_ty(tcx, local.ty, local.source_info.span)?; } // impl trait is gone in MIR, so check the return type manually check_ty( tcx, tcx.fn_sig(def_id).subst_identity().output().skip_binder(), body.local_decls.iter().next().unwrap().source_info.span, - false, )?; for bb in body.basic_blocks.iter() { @@ -71,7 +77,7 @@ pub fn is_min_const_fn<'tcx>(tcx: TyCtxt<'tcx>, body: &Body<'tcx>, msrv: &Msrv) Ok(()) } -fn check_ty<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>, span: Span, in_drop: bool) -> McfResult { +fn check_ty<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>, span: Span) -> McfResult { for arg in ty.walk() { let ty = match arg.unpack() { GenericArgKind::Type(ty) => ty, @@ -81,27 +87,6 @@ fn check_ty<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>, span: Span, in_drop: bool) -> GenericArgKind::Lifetime(_) | GenericArgKind::Const(_) => continue, }; - // Only do this check if we're in `TerminatorKind::Drop`, otherwise rustc will sometimes overflow - // its stack. This check is unnecessary outside of a `Drop` anyway so it's faster regardless - if in_drop && let ty::Adt(def, subst) = ty.kind() { - if def.has_non_const_dtor(tcx) && in_drop { - return Err(( - span, - "cannot drop locals with a non constant destructor in const fn".into(), - )); - } - - for fields in def.variants().iter().map(|v| &v.fields) { - for field in fields { - check_ty(tcx, field.ty(tcx, subst), span, in_drop)?; - } - } - - for field in def.all_fields() { - check_ty(tcx, field.ty(tcx, subst), span, in_drop)?; - } - } - match ty.kind() { ty::Ref(_, _, hir::Mutability::Mut) => { return Err((span, "mutable references in const fn are unstable".into())); @@ -288,6 +273,7 @@ fn check_operand<'tcx>(tcx: TyCtxt<'tcx>, operand: &Operand<'tcx>, span: Span, b fn check_place<'tcx>(tcx: TyCtxt<'tcx>, place: Place<'tcx>, span: Span, body: &Body<'tcx>) -> McfResult { let mut cursor = place.projection.as_ref(); + while let [ref proj_base @ .., elem] = *cursor { cursor = proj_base; match elem { @@ -327,20 +313,19 @@ fn check_terminator<'tcx>( | TerminatorKind::Resume | TerminatorKind::Terminate | TerminatorKind::Unreachable => Ok(()), - TerminatorKind::Drop { place, .. } => { - for local in &body.local_decls { - check_ty(tcx, local.ty, span, true)?; + if !is_ty_const_destruct(tcx, place.ty(&body.local_decls, tcx).ty, body) { + return Err(( + span, + "cannot drop locals with a non constant destructor in const fn".into(), + )); } check_place(tcx, *place, span, body) }, - TerminatorKind::SwitchInt { discr, targets: _ } => check_operand(tcx, discr, span, body), - TerminatorKind::GeneratorDrop | TerminatorKind::Yield { .. } => { Err((span, "const fn generators are unstable".into())) }, - TerminatorKind::Call { func, args, @@ -384,7 +369,6 @@ fn check_terminator<'tcx>( Err((span, "can only call other const fns within const fn".into())) } }, - TerminatorKind::Assert { cond, expected: _, @@ -392,7 +376,6 @@ fn check_terminator<'tcx>( target: _, unwind: _, } => check_operand(tcx, cond, span, body), - TerminatorKind::InlineAsm { .. } => Err((span, "cannot use inline assembly in const fn".into())), } } @@ -406,8 +389,7 @@ fn is_const_fn(tcx: TyCtxt<'_>, def_id: DefId, msrv: &Msrv) -> bool { // as a part of an unimplemented MSRV check https://github.com/rust-lang/rust/issues/65262. // HACK(nilstrieb): CURRENT_RUSTC_VERSION can return versions like 1.66.0-dev. `rustc-semver` - // doesn't accept the `-dev` version number so we have to strip it - // off. + // doesn't accept the `-dev` version number so we have to strip it off. let short_version = since .as_str() .split('-') @@ -425,3 +407,33 @@ fn is_const_fn(tcx: TyCtxt<'_>, def_id: DefId, msrv: &Msrv) -> bool { } }) } + +fn is_ty_const_destruct<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>, body: &Body<'tcx>) -> bool { + // Avoid selecting for simple cases, such as builtin types. + if ty::util::is_trivially_const_drop(ty) { + return true; + } + + let obligation = Obligation::new( + tcx, + ObligationCause::dummy_with_span(body.span), + ConstCx::new(tcx, body).param_env.with_constness(Constness::Const), + TraitRef::from_lang_item(tcx, LangItem::Destruct, body.span, [ty]).with_constness(BoundConstness::ConstIfConst), + ); + + let fields_all_const_destruct = if let ty::Adt(def, subst) = ty.kind() && !ty.is_union() { + // This is such a mess even rustfmt doesn't wanna touch it + def.all_fields() + .map(|field| is_ty_const_destruct(tcx, field.ty(tcx, subst), body)) + .all(|f| f) + && def.variants().iter() + .map(|variant| variant.fields.iter().map(|field| is_ty_const_destruct(tcx, field.ty(tcx, subst), body))) + .all(|mut fs| fs.all(|f| f)) + } else { + true + }; + + let infcx = tcx.infer_ctxt().build(); + let mut selcx = SelectionContext::new(&infcx); + selcx.select(&obligation).is_ok() && fields_all_const_destruct +} 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 dffc23177d1..4fe02a9cef8 100644 --- a/tests/ui/missing_const_for_fn/cant_be_const.rs +++ b/tests/ui/missing_const_for_fn/cant_be_const.rs @@ -13,7 +13,7 @@ extern crate proc_macros; use proc_macros::with_span; -struct Game; +struct Game; // You just lost. // This should not be linted because it's already const const fn already_const() -> i32 { @@ -135,3 +135,5 @@ enum A { } fn b(this: A) {} + +fn c(this: Vec) {} From 339cd14f27e9db4f7b040068abad8a20a0034fa8 Mon Sep 17 00:00:00 2001 From: avborhanian Date: Sun, 4 Jun 2023 10:33:13 -0700 Subject: [PATCH 096/310] Adds new lint `arc_with_non_send_or_sync` --- CHANGELOG.md | 1 + clippy_lints/src/arc_with_non_send_sync.rs | 71 ++++++++++++++++++++++ clippy_lints/src/declared_lints.rs | 1 + clippy_lints/src/lib.rs | 2 + tests/ui/arc_with_non_send_sync.rs | 12 ++++ tests/ui/arc_with_non_send_sync.stderr | 11 ++++ 6 files changed, 98 insertions(+) create mode 100644 clippy_lints/src/arc_with_non_send_sync.rs create mode 100644 tests/ui/arc_with_non_send_sync.rs create mode 100644 tests/ui/arc_with_non_send_sync.stderr diff --git a/CHANGELOG.md b/CHANGELOG.md index a65ac4d46de..a53567f25c4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4628,6 +4628,7 @@ Released 2018-09-13 [`almost_complete_range`]: https://rust-lang.github.io/rust-clippy/master/index.html#almost_complete_range [`almost_swapped`]: https://rust-lang.github.io/rust-clippy/master/index.html#almost_swapped [`approx_constant`]: https://rust-lang.github.io/rust-clippy/master/index.html#approx_constant +[`arc_with_non_send_sync`]: https://rust-lang.github.io/rust-clippy/master/index.html#arc_with_non_send_sync [`arithmetic_side_effects`]: https://rust-lang.github.io/rust-clippy/master/index.html#arithmetic_side_effects [`as_conversions`]: https://rust-lang.github.io/rust-clippy/master/index.html#as_conversions [`as_ptr_cast_mut`]: https://rust-lang.github.io/rust-clippy/master/index.html#as_ptr_cast_mut diff --git a/clippy_lints/src/arc_with_non_send_sync.rs b/clippy_lints/src/arc_with_non_send_sync.rs new file mode 100644 index 00000000000..2e14f81f8e4 --- /dev/null +++ b/clippy_lints/src/arc_with_non_send_sync.rs @@ -0,0 +1,71 @@ +use clippy_utils::diagnostics::span_lint_and_help; +use clippy_utils::last_path_segment; +use clippy_utils::ty::{implements_trait, is_type_diagnostic_item}; +use if_chain::if_chain; + +use rustc_hir::{Expr, ExprKind}; +use rustc_lint::LateContext; +use rustc_lint::LateLintPass; +use rustc_session::{declare_lint_pass, declare_tool_lint}; +use rustc_span::symbol::sym; + +declare_clippy_lint! { + /// ### What it does. + /// This lint warns when you use `Arc` with a type that does not implement `Send` or `Sync`. + /// + /// ### Why is this bad? + /// Wrapping a type in Arc doesn't add thread safety to the underlying data, so data races + /// could occur when touching the underlying data. + /// + /// ### Example. + /// ```rust + /// use std::cell::RefCell; + /// use std::sync::Arc; + /// + /// fn main() { + /// // This is safe, as `i32` implements `Send` and `Sync`. + /// let a = Arc::new(42); + /// + /// // This is not safe, as `RefCell` does not implement `Sync`. + /// let b = Arc::new(RefCell::new(42)); + /// } + /// ``` + /// ``` + #[clippy::version = "1.72.0"] + pub ARC_WITH_NON_SEND_SYNC, + correctness, + "using `Arc` with a type that does not implement `Send` or `Sync`" +} +declare_lint_pass!(ArcWithNonSendSync => [ARC_WITH_NON_SEND_SYNC]); + +impl LateLintPass<'_> for ArcWithNonSendSync { + fn check_expr(&mut self, cx: &LateContext<'_>, expr: &Expr<'_>) { + let ty = cx.typeck_results().expr_ty(expr); + if_chain! { + if is_type_diagnostic_item(cx, ty, sym::Arc); + if let ExprKind::Call(func, [arg]) = expr.kind; + if let ExprKind::Path(func_path) = func.kind; + if last_path_segment(&func_path).ident.name == sym::new; + if let arg_ty = cx.typeck_results().expr_ty(arg); + if !cx.tcx + .lang_items() + .sync_trait() + .map_or(false, |id| implements_trait(cx, arg_ty, id, &[])) || + !cx.tcx + .get_diagnostic_item(sym::Send) + .map_or(false, |id| implements_trait(cx, arg_ty, id, &[])); + + then { + span_lint_and_help( + cx, + ARC_WITH_NON_SEND_SYNC, + expr.span, + "usage of `Arc` where `T` is not `Send` or `Sync`", + None, + "consider using `Rc` instead or wrapping `T` in a std::sync type like \ + Mutex", + ); + } + } + } +} diff --git a/clippy_lints/src/declared_lints.rs b/clippy_lints/src/declared_lints.rs index d014534cee9..f82118e569f 100644 --- a/clippy_lints/src/declared_lints.rs +++ b/clippy_lints/src/declared_lints.rs @@ -40,6 +40,7 @@ pub(crate) static LINTS: &[&crate::LintInfo] = &[ crate::allow_attributes::ALLOW_ATTRIBUTES_INFO, crate::almost_complete_range::ALMOST_COMPLETE_RANGE_INFO, crate::approx_const::APPROX_CONSTANT_INFO, + crate::arc_with_non_send_sync::ARC_WITH_NON_SEND_SYNC_INFO, crate::as_conversions::AS_CONVERSIONS_INFO, crate::asm_syntax::INLINE_ASM_X86_ATT_SYNTAX_INFO, crate::asm_syntax::INLINE_ASM_X86_INTEL_SYNTAX_INFO, diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index d53c6de5451..2f5932104c1 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -68,6 +68,7 @@ mod renamed_lints; mod allow_attributes; mod almost_complete_range; mod approx_const; +mod arc_with_non_send_sync; mod as_conversions; mod asm_syntax; mod assertions_on_constants; @@ -1014,6 +1015,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: store.register_late_pass(|_| Box::new(missing_fields_in_debug::MissingFieldsInDebug)); store.register_late_pass(|_| Box::new(endian_bytes::EndianBytes)); store.register_late_pass(|_| Box::new(redundant_type_annotations::RedundantTypeAnnotations)); + store.register_late_pass(|_| Box::new(arc_with_non_send_sync::ArcWithNonSendSync)); // add lints here, do not remove this comment, it's used in `new_lint` } diff --git a/tests/ui/arc_with_non_send_sync.rs b/tests/ui/arc_with_non_send_sync.rs new file mode 100644 index 00000000000..4c2d84be5db --- /dev/null +++ b/tests/ui/arc_with_non_send_sync.rs @@ -0,0 +1,12 @@ +#![warn(clippy::arc_with_non_send_sync)] +#![allow(unused_variables)] +use std::cell::RefCell; +use std::sync::{Arc, Mutex}; + +fn main() { + // This is safe, as `i32` implements `Send` and `Sync`. + let a = Arc::new(42); + + // This is not safe, as `RefCell` does not implement `Sync`. + let b = Arc::new(RefCell::new(42)); +} diff --git a/tests/ui/arc_with_non_send_sync.stderr b/tests/ui/arc_with_non_send_sync.stderr new file mode 100644 index 00000000000..99e38bcc1a2 --- /dev/null +++ b/tests/ui/arc_with_non_send_sync.stderr @@ -0,0 +1,11 @@ +error: usage of `Arc` where `T` is not `Send` or `Sync` + --> $DIR/arc_with_non_send_sync.rs:11:13 + | +LL | let b = Arc::new(RefCell::new(42)); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: consider using `Rc` instead or wrapping `T` in a std::sync type like Mutex + = note: `-D clippy::arc-with-non-send-sync` implied by `-D warnings` + +error: aborting due to previous error + From 8330887e1b2272b14e334cb28fb85ccf0859f183 Mon Sep 17 00:00:00 2001 From: avborhanian Date: Wed, 7 Jun 2023 20:52:42 -0700 Subject: [PATCH 097/310] Updating documentation and lint formatting. --- clippy_lints/src/arc_with_non_send_sync.rs | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/clippy_lints/src/arc_with_non_send_sync.rs b/clippy_lints/src/arc_with_non_send_sync.rs index 2e14f81f8e4..ca2023ee0be 100644 --- a/clippy_lints/src/arc_with_non_send_sync.rs +++ b/clippy_lints/src/arc_with_non_send_sync.rs @@ -17,10 +17,10 @@ declare_clippy_lint! { /// Wrapping a type in Arc doesn't add thread safety to the underlying data, so data races /// could occur when touching the underlying data. /// - /// ### Example. + /// ### Example /// ```rust - /// use std::cell::RefCell; - /// use std::sync::Arc; + /// # use std::cell::RefCell; + /// # use std::sync::Arc; /// /// fn main() { /// // This is safe, as `i32` implements `Send` and `Sync`. @@ -30,7 +30,6 @@ declare_clippy_lint! { /// let b = Arc::new(RefCell::new(42)); /// } /// ``` - /// ``` #[clippy::version = "1.72.0"] pub ARC_WITH_NON_SEND_SYNC, correctness, @@ -63,7 +62,7 @@ impl LateLintPass<'_> for ArcWithNonSendSync { "usage of `Arc` where `T` is not `Send` or `Sync`", None, "consider using `Rc` instead or wrapping `T` in a std::sync type like \ - Mutex", + `Mutex`", ); } } From f2f342adb4eeead1582470eb410186ef42395e84 Mon Sep 17 00:00:00 2001 From: Andrew Xie Date: Thu, 8 Jun 2023 00:38:50 -0400 Subject: [PATCH 098/310] Removed stable/unstable sort arg from into_sorted_stable_ord, fixed a few misc issues, added collect to UnordItems --- clippy_lints/src/wildcard_imports.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clippy_lints/src/wildcard_imports.rs b/clippy_lints/src/wildcard_imports.rs index b6e4cd22789..2a3d86988bb 100644 --- a/clippy_lints/src/wildcard_imports.rs +++ b/clippy_lints/src/wildcard_imports.rs @@ -160,7 +160,7 @@ impl LateLintPass<'_> for WildcardImports { ) }; - let mut imports = used_imports.items().map(ToString::to_string).into_sorted_stable_ord(false); + let mut imports = used_imports.items().map(ToString::to_string).into_sorted_stable_ord(); let imports_string = if imports.len() == 1 { imports.pop().unwrap() } else if braced_glob { From ecd6afaa129e8cb152d2e3bcbc56fe11ded9fb44 Mon Sep 17 00:00:00 2001 From: Andrew Xie Date: Thu, 8 Jun 2023 00:40:29 -0400 Subject: [PATCH 099/310] fixup! Removed stable/unstable sort arg from into_sorted_stable_ord, fixed a few misc issues, added collect to UnordItems --- clippy_lints/src/wildcard_imports.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clippy_lints/src/wildcard_imports.rs b/clippy_lints/src/wildcard_imports.rs index 2a3d86988bb..b6e4cd22789 100644 --- a/clippy_lints/src/wildcard_imports.rs +++ b/clippy_lints/src/wildcard_imports.rs @@ -160,7 +160,7 @@ impl LateLintPass<'_> for WildcardImports { ) }; - let mut imports = used_imports.items().map(ToString::to_string).into_sorted_stable_ord(); + let mut imports = used_imports.items().map(ToString::to_string).into_sorted_stable_ord(false); let imports_string = if imports.len() == 1 { imports.pop().unwrap() } else if braced_glob { From 737cba0c374eb24c2294d6cc389e5a912f9730d9 Mon Sep 17 00:00:00 2001 From: Andrew Xie Date: Thu, 8 Jun 2023 01:05:38 -0400 Subject: [PATCH 100/310] Whoops, submodule change was actually valid - undoing fixup --- clippy_lints/src/wildcard_imports.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clippy_lints/src/wildcard_imports.rs b/clippy_lints/src/wildcard_imports.rs index b6e4cd22789..2a3d86988bb 100644 --- a/clippy_lints/src/wildcard_imports.rs +++ b/clippy_lints/src/wildcard_imports.rs @@ -160,7 +160,7 @@ impl LateLintPass<'_> for WildcardImports { ) }; - let mut imports = used_imports.items().map(ToString::to_string).into_sorted_stable_ord(false); + let mut imports = used_imports.items().map(ToString::to_string).into_sorted_stable_ord(); let imports_string = if imports.len() == 1 { imports.pop().unwrap() } else if braced_glob { From 2f5d1c748a5447256048267d3fbc3533d6d7e126 Mon Sep 17 00:00:00 2001 From: avborhanian Date: Thu, 8 Jun 2023 00:22:04 -0700 Subject: [PATCH 101/310] Adding extra check to ignore generic args. --- clippy_lints/src/arc_with_non_send_sync.rs | 5 +++++ tests/ui/arc_with_non_send_sync.rs | 5 +++++ tests/ui/arc_with_non_send_sync.stderr | 4 ++-- 3 files changed, 12 insertions(+), 2 deletions(-) diff --git a/clippy_lints/src/arc_with_non_send_sync.rs b/clippy_lints/src/arc_with_non_send_sync.rs index ca2023ee0be..13e938327bb 100644 --- a/clippy_lints/src/arc_with_non_send_sync.rs +++ b/clippy_lints/src/arc_with_non_send_sync.rs @@ -6,6 +6,7 @@ use if_chain::if_chain; use rustc_hir::{Expr, ExprKind}; use rustc_lint::LateContext; use rustc_lint::LateLintPass; +use rustc_middle::ty; use rustc_session::{declare_lint_pass, declare_tool_lint}; use rustc_span::symbol::sym; @@ -46,6 +47,10 @@ impl LateLintPass<'_> for ArcWithNonSendSync { if let ExprKind::Path(func_path) = func.kind; if last_path_segment(&func_path).ident.name == sym::new; if let arg_ty = cx.typeck_results().expr_ty(arg); + if match arg_ty.kind() { + ty::Param(_) => false, + _ => true, + }; if !cx.tcx .lang_items() .sync_trait() diff --git a/tests/ui/arc_with_non_send_sync.rs b/tests/ui/arc_with_non_send_sync.rs index 4c2d84be5db..ac786f68c12 100644 --- a/tests/ui/arc_with_non_send_sync.rs +++ b/tests/ui/arc_with_non_send_sync.rs @@ -3,6 +3,11 @@ use std::cell::RefCell; use std::sync::{Arc, Mutex}; +fn foo(x: T) { + // Should not lint - purposefully ignoring generic args. + let a = Arc::new(x); +} + fn main() { // This is safe, as `i32` implements `Send` and `Sync`. let a = Arc::new(42); diff --git a/tests/ui/arc_with_non_send_sync.stderr b/tests/ui/arc_with_non_send_sync.stderr index 99e38bcc1a2..fc2fc5f93b1 100644 --- a/tests/ui/arc_with_non_send_sync.stderr +++ b/tests/ui/arc_with_non_send_sync.stderr @@ -1,10 +1,10 @@ error: usage of `Arc` where `T` is not `Send` or `Sync` - --> $DIR/arc_with_non_send_sync.rs:11:13 + --> $DIR/arc_with_non_send_sync.rs:16:13 | LL | let b = Arc::new(RefCell::new(42)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ | - = help: consider using `Rc` instead or wrapping `T` in a std::sync type like Mutex + = help: consider using `Rc` instead or wrapping `T` in a std::sync type like `Mutex` = note: `-D clippy::arc-with-non-send-sync` implied by `-D warnings` error: aborting due to previous error From 20548eba6ceda0563b399f54b06d05b71950aa5c Mon Sep 17 00:00:00 2001 From: avborhanian Date: Thu, 8 Jun 2023 00:38:18 -0700 Subject: [PATCH 102/310] Swapping to matches macro. --- clippy_lints/src/arc_with_non_send_sync.rs | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/clippy_lints/src/arc_with_non_send_sync.rs b/clippy_lints/src/arc_with_non_send_sync.rs index 13e938327bb..a1e44668e1a 100644 --- a/clippy_lints/src/arc_with_non_send_sync.rs +++ b/clippy_lints/src/arc_with_non_send_sync.rs @@ -47,10 +47,7 @@ impl LateLintPass<'_> for ArcWithNonSendSync { if let ExprKind::Path(func_path) = func.kind; if last_path_segment(&func_path).ident.name == sym::new; if let arg_ty = cx.typeck_results().expr_ty(arg); - if match arg_ty.kind() { - ty::Param(_) => false, - _ => true, - }; + if !matches!(arg_ty.kind(), ty::Param(_)); if !cx.tcx .lang_items() .sync_trait() From 5692677b3b2c35701e23639c01ce3ed2f82c2a55 Mon Sep 17 00:00:00 2001 From: Centri3 <114838443+Centri3@users.noreply.github.com> Date: Thu, 8 Jun 2023 02:41:51 -0500 Subject: [PATCH 103/310] cleanup spaghetti code --- clippy_utils/src/lib.rs | 2 +- clippy_utils/src/qualify_min_const_fn.rs | 62 +++++++++++-------- .../ui/missing_const_for_fn/cant_be_const.rs | 20 ++++++ .../ui/missing_const_for_fn/could_be_const.rs | 13 ++++ .../could_be_const.stderr | 30 +++++---- 5 files changed, 88 insertions(+), 39 deletions(-) diff --git a/clippy_utils/src/lib.rs b/clippy_utils/src/lib.rs index e600dc58c9d..311f6dbc696 100644 --- a/clippy_utils/src/lib.rs +++ b/clippy_utils/src/lib.rs @@ -20,8 +20,8 @@ extern crate rustc_ast; extern crate rustc_ast_pretty; extern crate rustc_attr; -extern crate rustc_data_structures; extern crate rustc_const_eval; +extern crate rustc_data_structures; // The `rustc_driver` crate seems to be required in order to use the `rust_ast` crate. #[allow(unused_extern_crates)] extern crate rustc_driver; diff --git a/clippy_utils/src/qualify_min_const_fn.rs b/clippy_utils/src/qualify_min_const_fn.rs index cdaf8985d5e..799b6ffeba6 100644 --- a/clippy_utils/src/qualify_min_const_fn.rs +++ b/clippy_utils/src/qualify_min_const_fn.rs @@ -4,7 +4,7 @@ // differ from the time of `rustc` even if the name stays the same. use crate::msrvs::Msrv; -use hir::{Constness, LangItem}; +use hir::LangItem; use rustc_const_eval::transform::check_consts::ConstCx; use rustc_hir as hir; use rustc_hir::def_id::DefId; @@ -14,14 +14,14 @@ use rustc_middle::mir::{ Body, CastKind, NonDivergingIntrinsic, NullOp, Operand, Place, ProjectionElem, Rvalue, Statement, StatementKind, Terminator, TerminatorKind, }; -use rustc_middle::traits::ObligationCause; +use rustc_middle::traits::{ImplSource, ObligationCause}; use rustc_middle::ty::subst::GenericArgKind; use rustc_middle::ty::{self, adjustment::PointerCast, Ty, TyCtxt}; use rustc_middle::ty::{BoundConstness, TraitRef}; use rustc_semver::RustcVersion; use rustc_span::symbol::sym; use rustc_span::Span; -use rustc_trait_selection::traits::SelectionContext; +use rustc_trait_selection::traits::{ObligationCtxt, SelectionContext}; use std::borrow::Cow; type McfResult = Result<(), (Span, Cow<'static, str>)>; @@ -135,9 +135,9 @@ fn check_rvalue<'tcx>( match rvalue { Rvalue::ThreadLocalRef(_) => Err((span, "cannot access thread local storage in const fn".into())), Rvalue::Len(place) | Rvalue::Discriminant(place) | Rvalue::Ref(_, _, place) | Rvalue::AddressOf(_, place) => { - check_place(tcx, *place, span, body) + check_place(tcx, *place, span, body, false) }, - Rvalue::CopyForDeref(place) => check_place(tcx, *place, span, body), + Rvalue::CopyForDeref(place) => check_place(tcx, *place, span, body, false), Rvalue::Repeat(operand, _) | Rvalue::Use(operand) | Rvalue::Cast( @@ -230,14 +230,14 @@ fn check_statement<'tcx>( let span = statement.source_info.span; match &statement.kind { StatementKind::Assign(box (place, rval)) => { - check_place(tcx, *place, span, body)?; + check_place(tcx, *place, span, body, false)?; check_rvalue(tcx, body, def_id, rval, span) }, - StatementKind::FakeRead(box (_, place)) => check_place(tcx, *place, span, body), + StatementKind::FakeRead(box (_, place)) => check_place(tcx, *place, span, body, false), // just an assignment StatementKind::SetDiscriminant { place, .. } | StatementKind::Deinit(place) => { - check_place(tcx, **place, span, body) + check_place(tcx, **place, span, body, false) }, StatementKind::Intrinsic(box NonDivergingIntrinsic::Assume(op)) => check_operand(tcx, op, span, body), @@ -263,7 +263,8 @@ fn check_statement<'tcx>( fn check_operand<'tcx>(tcx: TyCtxt<'tcx>, operand: &Operand<'tcx>, span: Span, body: &Body<'tcx>) -> McfResult { match operand { - Operand::Move(place) | Operand::Copy(place) => check_place(tcx, *place, span, body), + Operand::Move(place) => check_place(tcx, *place, span, body, true), + Operand::Copy(place) => check_place(tcx, *place, span, body, false), Operand::Constant(c) => match c.check_static_ptr(tcx) { Some(_) => Err((span, "cannot access `static` items in const fn".into())), None => Ok(()), @@ -271,13 +272,20 @@ fn check_operand<'tcx>(tcx: TyCtxt<'tcx>, operand: &Operand<'tcx>, span: Span, b } } -fn check_place<'tcx>(tcx: TyCtxt<'tcx>, place: Place<'tcx>, span: Span, body: &Body<'tcx>) -> McfResult { +fn check_place<'tcx>(tcx: TyCtxt<'tcx>, place: Place<'tcx>, span: Span, body: &Body<'tcx>, in_move: bool) -> McfResult { let mut cursor = place.projection.as_ref(); while let [ref proj_base @ .., elem] = *cursor { cursor = proj_base; match elem { - ProjectionElem::Field(..) => { + ProjectionElem::Field(_, ty) => { + if !is_ty_const_destruct(tcx, ty, body) && in_move { + return Err(( + span, + "cannot drop locals with a non constant destructor in const fn".into(), + )); + } + let base_ty = Place::ty_from(place.local, proj_base, body, tcx).ty; if let Some(def) = base_ty.ty_adt_def() { // No union field accesses in `const fn` @@ -320,7 +328,7 @@ fn check_terminator<'tcx>( "cannot drop locals with a non constant destructor in const fn".into(), )); } - check_place(tcx, *place, span, body) + check_place(tcx, *place, span, body, false) }, TerminatorKind::SwitchInt { discr, targets: _ } => check_operand(tcx, discr, span, body), TerminatorKind::GeneratorDrop | TerminatorKind::Yield { .. } => { @@ -408,6 +416,7 @@ fn is_const_fn(tcx: TyCtxt<'_>, def_id: DefId, msrv: &Msrv) -> bool { }) } +#[expect(clippy::similar_names)] // bit too pedantic fn is_ty_const_destruct<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>, body: &Body<'tcx>) -> bool { // Avoid selecting for simple cases, such as builtin types. if ty::util::is_trivially_const_drop(ty) { @@ -417,23 +426,24 @@ fn is_ty_const_destruct<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>, body: &Body<'tcx> let obligation = Obligation::new( tcx, ObligationCause::dummy_with_span(body.span), - ConstCx::new(tcx, body).param_env.with_constness(Constness::Const), + ConstCx::new(tcx, body).param_env.with_const(), TraitRef::from_lang_item(tcx, LangItem::Destruct, body.span, [ty]).with_constness(BoundConstness::ConstIfConst), ); - let fields_all_const_destruct = if let ty::Adt(def, subst) = ty.kind() && !ty.is_union() { - // This is such a mess even rustfmt doesn't wanna touch it - def.all_fields() - .map(|field| is_ty_const_destruct(tcx, field.ty(tcx, subst), body)) - .all(|f| f) - && def.variants().iter() - .map(|variant| variant.fields.iter().map(|field| is_ty_const_destruct(tcx, field.ty(tcx, subst), body))) - .all(|mut fs| fs.all(|f| f)) - } else { - true - }; - let infcx = tcx.infer_ctxt().build(); let mut selcx = SelectionContext::new(&infcx); - selcx.select(&obligation).is_ok() && fields_all_const_destruct + let Some(impl_src) = selcx.select(&obligation).ok().flatten() else { + return false; + }; + + if !matches!( + impl_src, + ImplSource::ConstDestruct(_) | ImplSource::Param(_, ty::BoundConstness::ConstIfConst) + ) { + return false; + } + + let ocx = ObligationCtxt::new(&infcx); + ocx.register_obligations(impl_src.nested_obligations()); + ocx.select_all_or_error().is_empty() } 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 4fe02a9cef8..286d208b25b 100644 --- a/tests/ui/missing_const_for_fn/cant_be_const.rs +++ b/tests/ui/missing_const_for_fn/cant_be_const.rs @@ -127,6 +127,7 @@ with_span! { fn dont_check_in_proc_macro() {} } +// Do not lint `String` has `Vec`, which cannot be dropped in const contexts fn a(this: String) {} enum A { @@ -134,6 +135,25 @@ enum A { N, } +// Same here. fn b(this: A) {} +// Minimized version of `a`. fn c(this: Vec) {} + +struct F(A); + +// Do not lint +fn f(this: F) {} + +// Do not lint +fn g(this: T) {} + +struct Issue10617(String); + +impl Issue10617 { + // Do not lint + pub fn name(self) -> String { + self.0 + } +} diff --git a/tests/ui/missing_const_for_fn/could_be_const.rs b/tests/ui/missing_const_for_fn/could_be_const.rs index 0246c8622ed..b1980b1b523 100644 --- a/tests/ui/missing_const_for_fn/could_be_const.rs +++ b/tests/ui/missing_const_for_fn/could_be_const.rs @@ -1,5 +1,7 @@ #![warn(clippy::missing_const_for_fn)] #![allow(incomplete_features, clippy::let_and_return)] +#![feature(const_mut_refs)] +#![feature(const_trait_impl)] use std::mem::transmute; @@ -87,3 +89,14 @@ fn msrv_1_46() -> i32 { // Should not be const fn main() {} + +struct D; + +impl const Drop for D { + fn drop(&mut self) { + todo!(); + } +} + +// Lint this, since it can be dropped in const contexts +fn d(this: D) {} diff --git a/tests/ui/missing_const_for_fn/could_be_const.stderr b/tests/ui/missing_const_for_fn/could_be_const.stderr index 955e1ed2634..7be2cc0ca93 100644 --- a/tests/ui/missing_const_for_fn/could_be_const.stderr +++ b/tests/ui/missing_const_for_fn/could_be_const.stderr @@ -1,5 +1,5 @@ error: this could be a `const fn` - --> $DIR/could_be_const.rs:12:5 + --> $DIR/could_be_const.rs:14:5 | LL | / pub fn new() -> Self { LL | | Self { guess: 42 } @@ -9,7 +9,7 @@ LL | | } = note: `-D clippy::missing-const-for-fn` implied by `-D warnings` error: this could be a `const fn` - --> $DIR/could_be_const.rs:16:5 + --> $DIR/could_be_const.rs:18:5 | LL | / fn const_generic_params<'a, T, const N: usize>(&self, b: &'a [T; N]) -> &'a [T; N] { LL | | b @@ -17,7 +17,7 @@ LL | | } | |_____^ error: this could be a `const fn` - --> $DIR/could_be_const.rs:22:1 + --> $DIR/could_be_const.rs:24:1 | LL | / fn one() -> i32 { LL | | 1 @@ -25,7 +25,7 @@ LL | | } | |_^ error: this could be a `const fn` - --> $DIR/could_be_const.rs:27:1 + --> $DIR/could_be_const.rs:29:1 | LL | / fn two() -> i32 { LL | | let abc = 2; @@ -34,7 +34,7 @@ LL | | } | |_^ error: this could be a `const fn` - --> $DIR/could_be_const.rs:33:1 + --> $DIR/could_be_const.rs:35:1 | LL | / fn string() -> String { LL | | String::new() @@ -42,7 +42,7 @@ LL | | } | |_^ error: this could be a `const fn` - --> $DIR/could_be_const.rs:38:1 + --> $DIR/could_be_const.rs:40:1 | LL | / unsafe fn four() -> i32 { LL | | 4 @@ -50,7 +50,7 @@ LL | | } | |_^ error: this could be a `const fn` - --> $DIR/could_be_const.rs:43:1 + --> $DIR/could_be_const.rs:45:1 | LL | / fn generic(t: T) -> T { LL | | t @@ -58,7 +58,7 @@ LL | | } | |_^ error: this could be a `const fn` - --> $DIR/could_be_const.rs:51:1 + --> $DIR/could_be_const.rs:53:1 | LL | / fn generic_arr(t: [T; 1]) -> T { LL | | t[0] @@ -66,7 +66,7 @@ LL | | } | |_^ error: this could be a `const fn` - --> $DIR/could_be_const.rs:64:9 + --> $DIR/could_be_const.rs:66:9 | LL | / pub fn b(self, a: &A) -> B { LL | | B @@ -74,7 +74,7 @@ LL | | } | |_________^ error: this could be a `const fn` - --> $DIR/could_be_const.rs:73:5 + --> $DIR/could_be_const.rs:75:5 | LL | / fn const_fn_stabilized_before_msrv(byte: u8) { LL | | byte.is_ascii_digit(); @@ -82,12 +82,18 @@ LL | | } | |_____^ error: this could be a `const fn` - --> $DIR/could_be_const.rs:84:1 + --> $DIR/could_be_const.rs:86:1 | LL | / fn msrv_1_46() -> i32 { LL | | 46 LL | | } | |_^ -error: aborting due to 11 previous errors +error: this could be a `const fn` + --> $DIR/could_be_const.rs:102:1 + | +LL | fn d(this: D) {} + | ^^^^^^^^^^^^^^^^ + +error: aborting due to 12 previous errors From f47e9156a4cc6f4908beb8f2b3564de8c42a56cb Mon Sep 17 00:00:00 2001 From: Urgau Date: Fri, 12 May 2023 20:02:01 +0200 Subject: [PATCH 104/310] Drop uplifted clippy::undropped_manually_drops --- clippy_lints/src/declared_lints.rs | 1 - clippy_lints/src/drop_forget_ref.rs | 44 +-------- clippy_lints/src/renamed_lints.rs | 1 + tests/ui/rename.fixed | 2 + tests/ui/rename.rs | 2 + tests/ui/rename.stderr | 108 ++++++++++++----------- tests/ui/undropped_manually_drops.rs | 26 ------ tests/ui/undropped_manually_drops.stderr | 19 ---- 8 files changed, 64 insertions(+), 139 deletions(-) delete mode 100644 tests/ui/undropped_manually_drops.rs delete mode 100644 tests/ui/undropped_manually_drops.stderr diff --git a/clippy_lints/src/declared_lints.rs b/clippy_lints/src/declared_lints.rs index 15ff8be0fd9..6270d261313 100644 --- a/clippy_lints/src/declared_lints.rs +++ b/clippy_lints/src/declared_lints.rs @@ -136,7 +136,6 @@ pub(crate) static LINTS: &[&crate::LintInfo] = &[ crate::double_parens::DOUBLE_PARENS_INFO, crate::drop_forget_ref::DROP_NON_DROP_INFO, crate::drop_forget_ref::FORGET_NON_DROP_INFO, - crate::drop_forget_ref::UNDROPPED_MANUALLY_DROPS_INFO, crate::duplicate_mod::DUPLICATE_MOD_INFO, crate::else_if_without_else::ELSE_IF_WITHOUT_ELSE_INFO, crate::empty_drop::EMPTY_DROP_INFO, diff --git a/clippy_lints/src/drop_forget_ref.rs b/clippy_lints/src/drop_forget_ref.rs index 9c60edb1794..7a4b9a87aeb 100644 --- a/clippy_lints/src/drop_forget_ref.rs +++ b/clippy_lints/src/drop_forget_ref.rs @@ -1,4 +1,4 @@ -use clippy_utils::diagnostics::{span_lint_and_help, span_lint_and_note}; +use clippy_utils::diagnostics::span_lint_and_note; use clippy_utils::get_parent_node; use clippy_utils::is_must_use_func_call; use clippy_utils::ty::{is_copy, is_must_use_ty, is_type_lang_item}; @@ -47,35 +47,6 @@ declare_clippy_lint! { "call to `std::mem::forget` with a value which does not implement `Drop`" } -declare_clippy_lint! { - /// ### What it does - /// Prevents the safe `std::mem::drop` function from being called on `std::mem::ManuallyDrop`. - /// - /// ### Why is this bad? - /// The safe `drop` function does not drop the inner value of a `ManuallyDrop`. - /// - /// ### Known problems - /// Does not catch cases if the user binds `std::mem::drop` - /// to a different name and calls it that way. - /// - /// ### Example - /// ```rust - /// struct S; - /// drop(std::mem::ManuallyDrop::new(S)); - /// ``` - /// Use instead: - /// ```rust - /// struct S; - /// unsafe { - /// std::mem::ManuallyDrop::drop(&mut std::mem::ManuallyDrop::new(S)); - /// } - /// ``` - #[clippy::version = "1.49.0"] - pub UNDROPPED_MANUALLY_DROPS, - correctness, - "use of safe `std::mem::drop` function to drop a std::mem::ManuallyDrop, which will not drop the inner value" -} - const DROP_NON_DROP_SUMMARY: &str = "call to `std::mem::drop` with a value that does not implement `Drop`. \ Dropping such a type only extends its contained lifetimes"; const FORGET_NON_DROP_SUMMARY: &str = "call to `std::mem::forget` with a value that does not implement `Drop`. \ @@ -84,7 +55,6 @@ const FORGET_NON_DROP_SUMMARY: &str = "call to `std::mem::forget` with a value t declare_lint_pass!(DropForgetRef => [ DROP_NON_DROP, FORGET_NON_DROP, - UNDROPPED_MANUALLY_DROPS ]); impl<'tcx> LateLintPass<'tcx> for DropForgetRef { @@ -103,17 +73,7 @@ impl<'tcx> LateLintPass<'tcx> for DropForgetRef { sym::mem_forget if arg_ty.is_ref() => return, sym::mem_drop if is_copy && !drop_is_single_call_in_arm => return, sym::mem_forget if is_copy => return, - sym::mem_drop if is_type_lang_item(cx, arg_ty, LangItem::ManuallyDrop) => { - span_lint_and_help( - cx, - UNDROPPED_MANUALLY_DROPS, - expr.span, - "the inner value of this ManuallyDrop will not be dropped", - None, - "to drop a `ManuallyDrop`, use std::mem::ManuallyDrop::drop", - ); - return; - } + sym::mem_drop if is_type_lang_item(cx, arg_ty, LangItem::ManuallyDrop) => return, sym::mem_drop if !(arg_ty.needs_drop(cx.tcx, cx.param_env) || is_must_use_func_call(cx, arg) diff --git a/clippy_lints/src/renamed_lints.rs b/clippy_lints/src/renamed_lints.rs index 4cb41830023..f76fa76f076 100644 --- a/clippy_lints/src/renamed_lints.rs +++ b/clippy_lints/src/renamed_lints.rs @@ -50,6 +50,7 @@ pub static RENAMED_LINTS: &[(&str, &str)] = &[ ("clippy::panic_params", "non_fmt_panics"), ("clippy::positional_named_format_parameters", "named_arguments_used_positionally"), ("clippy::temporary_cstring_as_ptr", "temporary_cstring_as_ptr"), + ("clippy::undropped_manually_drops", "undropped_manually_drops"), ("clippy::unknown_clippy_lints", "unknown_lints"), ("clippy::unused_label", "unused_labels"), ]; diff --git a/tests/ui/rename.fixed b/tests/ui/rename.fixed index 30f2bfc8c1a..954145fc4e6 100644 --- a/tests/ui/rename.fixed +++ b/tests/ui/rename.fixed @@ -47,6 +47,7 @@ #![allow(named_arguments_used_positionally)] #![allow(suspicious_double_ref_op)] #![allow(temporary_cstring_as_ptr)] +#![allow(undropped_manually_drops)] #![allow(unknown_lints)] #![allow(unused_labels)] #![warn(clippy::almost_complete_range)] @@ -97,6 +98,7 @@ #![warn(non_fmt_panics)] #![warn(named_arguments_used_positionally)] #![warn(temporary_cstring_as_ptr)] +#![warn(undropped_manually_drops)] #![warn(unknown_lints)] #![warn(unused_labels)] diff --git a/tests/ui/rename.rs b/tests/ui/rename.rs index 3939914d422..067a3109afb 100644 --- a/tests/ui/rename.rs +++ b/tests/ui/rename.rs @@ -47,6 +47,7 @@ #![allow(named_arguments_used_positionally)] #![allow(suspicious_double_ref_op)] #![allow(temporary_cstring_as_ptr)] +#![allow(undropped_manually_drops)] #![allow(unknown_lints)] #![allow(unused_labels)] #![warn(clippy::almost_complete_letter_range)] @@ -97,6 +98,7 @@ #![warn(clippy::panic_params)] #![warn(clippy::positional_named_format_parameters)] #![warn(clippy::temporary_cstring_as_ptr)] +#![warn(clippy::undropped_manually_drops)] #![warn(clippy::unknown_clippy_lints)] #![warn(clippy::unused_label)] diff --git a/tests/ui/rename.stderr b/tests/ui/rename.stderr index 7290cf32e5b..1819d108c57 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:52:9 + --> $DIR/rename.rs:53:9 | LL | #![warn(clippy::almost_complete_letter_range)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::almost_complete_range` @@ -7,298 +7,304 @@ 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:53:9 + --> $DIR/rename.rs:54: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:54:9 + --> $DIR/rename.rs:55: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:55:9 + --> $DIR/rename.rs:56: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:56:9 + --> $DIR/rename.rs:57: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:57:9 + --> $DIR/rename.rs:58: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:58:9 + --> $DIR/rename.rs:59: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:59:9 + --> $DIR/rename.rs:60: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:60:9 + --> $DIR/rename.rs:61: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:61:9 + --> $DIR/rename.rs:62: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:62:9 + --> $DIR/rename.rs:63: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:63:9 + --> $DIR/rename.rs:64: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:64:9 + --> $DIR/rename.rs:65:9 | LL | #![warn(clippy::if_let_some_result)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::match_result_ok` error: lint `clippy::integer_arithmetic` has been renamed to `clippy::arithmetic_side_effects` - --> $DIR/rename.rs:65:9 + --> $DIR/rename.rs:66:9 | LL | #![warn(clippy::integer_arithmetic)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::arithmetic_side_effects` error: lint `clippy::logic_bug` has been renamed to `clippy::overly_complex_bool_expr` - --> $DIR/rename.rs:66:9 + --> $DIR/rename.rs:67: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:67:9 + --> $DIR/rename.rs:68: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:68:9 + --> $DIR/rename.rs:69: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:69:9 + --> $DIR/rename.rs:70: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:70:9 + --> $DIR/rename.rs:71: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:71:9 + --> $DIR/rename.rs:72: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:72:9 + --> $DIR/rename.rs:73: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:73:9 + --> $DIR/rename.rs:74: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:74:9 + --> $DIR/rename.rs:75: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:75:9 + --> $DIR/rename.rs:76: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:76:9 + --> $DIR/rename.rs:77: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:77:9 + --> $DIR/rename.rs:78: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:78:9 + --> $DIR/rename.rs:79: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:79:9 + --> $DIR/rename.rs:80: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:80:9 + --> $DIR/rename.rs:81:9 | LL | #![warn(clippy::zero_width_space)] | ^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::invisible_characters` error: lint `clippy::cast_ref_to_mut` has been renamed to `cast_ref_to_mut` - --> $DIR/rename.rs:81:9 + --> $DIR/rename.rs:82:9 | LL | #![warn(clippy::cast_ref_to_mut)] | ^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `cast_ref_to_mut` error: lint `clippy::clone_double_ref` has been renamed to `suspicious_double_ref_op` - --> $DIR/rename.rs:82:9 + --> $DIR/rename.rs:83: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:83:9 + --> $DIR/rename.rs:84:9 | LL | #![warn(clippy::drop_bounds)] | ^^^^^^^^^^^^^^^^^^^ help: use the new name: `drop_bounds` error: lint `clippy::drop_copy` has been renamed to `dropping_copy_types` - --> $DIR/rename.rs:84:9 + --> $DIR/rename.rs:85:9 | LL | #![warn(clippy::drop_copy)] | ^^^^^^^^^^^^^^^^^ help: use the new name: `dropping_copy_types` error: lint `clippy::drop_ref` has been renamed to `dropping_references` - --> $DIR/rename.rs:85:9 + --> $DIR/rename.rs:86:9 | LL | #![warn(clippy::drop_ref)] | ^^^^^^^^^^^^^^^^ help: use the new name: `dropping_references` error: lint `clippy::for_loop_over_option` has been renamed to `for_loops_over_fallibles` - --> $DIR/rename.rs:86:9 + --> $DIR/rename.rs:87: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:87:9 + --> $DIR/rename.rs:88: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:88:9 + --> $DIR/rename.rs:89:9 | LL | #![warn(clippy::for_loops_over_fallibles)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `for_loops_over_fallibles` error: lint `clippy::forget_copy` has been renamed to `forgetting_copy_types` - --> $DIR/rename.rs:89:9 + --> $DIR/rename.rs:90:9 | LL | #![warn(clippy::forget_copy)] | ^^^^^^^^^^^^^^^^^^^ help: use the new name: `forgetting_copy_types` error: lint `clippy::forget_ref` has been renamed to `forgetting_references` - --> $DIR/rename.rs:90:9 + --> $DIR/rename.rs:91:9 | LL | #![warn(clippy::forget_ref)] | ^^^^^^^^^^^^^^^^^^ help: use the new name: `forgetting_references` error: lint `clippy::into_iter_on_array` has been renamed to `array_into_iter` - --> $DIR/rename.rs:91:9 + --> $DIR/rename.rs:92: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:92:9 + --> $DIR/rename.rs:93: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:93:9 + --> $DIR/rename.rs:94:9 | LL | #![warn(clippy::invalid_ref)] | ^^^^^^^^^^^^^^^^^^^ help: use the new name: `invalid_value` error: lint `clippy::invalid_utf8_in_unchecked` has been renamed to `invalid_from_utf8_unchecked` - --> $DIR/rename.rs:94:9 + --> $DIR/rename.rs:95:9 | LL | #![warn(clippy::invalid_utf8_in_unchecked)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `invalid_from_utf8_unchecked` error: lint `clippy::let_underscore_drop` has been renamed to `let_underscore_drop` - --> $DIR/rename.rs:95:9 + --> $DIR/rename.rs:96: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:96:9 + --> $DIR/rename.rs:97: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:97:9 + --> $DIR/rename.rs:98: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:98:9 + --> $DIR/rename.rs:99: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:99:9 + --> $DIR/rename.rs:100:9 | LL | #![warn(clippy::temporary_cstring_as_ptr)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `temporary_cstring_as_ptr` +error: lint `clippy::undropped_manually_drops` has been renamed to `undropped_manually_drops` + --> $DIR/rename.rs:101:9 + | +LL | #![warn(clippy::undropped_manually_drops)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `undropped_manually_drops` + error: lint `clippy::unknown_clippy_lints` has been renamed to `unknown_lints` - --> $DIR/rename.rs:100:9 + --> $DIR/rename.rs:102: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:101:9 + --> $DIR/rename.rs:103:9 | LL | #![warn(clippy::unused_label)] | ^^^^^^^^^^^^^^^^^^^^ help: use the new name: `unused_labels` -error: aborting due to 50 previous errors +error: aborting due to 51 previous errors diff --git a/tests/ui/undropped_manually_drops.rs b/tests/ui/undropped_manually_drops.rs deleted file mode 100644 index f4cfc92e1cd..00000000000 --- a/tests/ui/undropped_manually_drops.rs +++ /dev/null @@ -1,26 +0,0 @@ -#![warn(clippy::undropped_manually_drops)] - -struct S; - -fn main() { - let f = std::mem::drop; - let g = std::mem::ManuallyDrop::drop; - let mut manual1 = std::mem::ManuallyDrop::new(S); - let mut manual2 = std::mem::ManuallyDrop::new(S); - let mut manual3 = std::mem::ManuallyDrop::new(S); - let mut manual4 = std::mem::ManuallyDrop::new(S); - - // These lines will not drop `S` and should be linted - drop(std::mem::ManuallyDrop::new(S)); - drop(manual1); - - // FIXME: this line is not linted, though it should be - f(manual2); - - // These lines will drop `S` and should be okay. - unsafe { - std::mem::ManuallyDrop::drop(&mut std::mem::ManuallyDrop::new(S)); - std::mem::ManuallyDrop::drop(&mut manual3); - g(&mut manual4); - } -} diff --git a/tests/ui/undropped_manually_drops.stderr b/tests/ui/undropped_manually_drops.stderr deleted file mode 100644 index 92611a9b7df..00000000000 --- a/tests/ui/undropped_manually_drops.stderr +++ /dev/null @@ -1,19 +0,0 @@ -error: the inner value of this ManuallyDrop will not be dropped - --> $DIR/undropped_manually_drops.rs:14:5 - | -LL | drop(std::mem::ManuallyDrop::new(S)); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = help: to drop a `ManuallyDrop`, use std::mem::ManuallyDrop::drop - = note: `-D clippy::undropped-manually-drops` implied by `-D warnings` - -error: the inner value of this ManuallyDrop will not be dropped - --> $DIR/undropped_manually_drops.rs:15:5 - | -LL | drop(manual1); - | ^^^^^^^^^^^^^ - | - = help: to drop a `ManuallyDrop`, use std::mem::ManuallyDrop::drop - -error: aborting due to 2 previous errors - From 6afb3555d303b0708fc0f687f531c25e47806ce8 Mon Sep 17 00:00:00 2001 From: Centri3 <114838443+Centri3@users.noreply.github.com> Date: Thu, 8 Jun 2023 10:15:58 -0500 Subject: [PATCH 105/310] remove revisions --- .../auxiliary/proc_macros.rs | 2 +- .../excessive_nesting/{above => }/clippy.toml | 0 .../excessive_nesting/excessive_nesting.rs | 3 - .../excessive_nesting.set.stderr | 351 ------------------ ....above.stderr => excessive_nesting.stderr} | 74 ++-- .../ui-toml/excessive_nesting/set/clippy.toml | 1 - 6 files changed, 38 insertions(+), 393 deletions(-) rename tests/ui-toml/excessive_nesting/{above => }/clippy.toml (100%) delete mode 100644 tests/ui-toml/excessive_nesting/excessive_nesting.set.stderr rename tests/ui-toml/excessive_nesting/{excessive_nesting.above.stderr => excessive_nesting.stderr} (83%) delete mode 100644 tests/ui-toml/excessive_nesting/set/clippy.toml diff --git a/tests/ui-toml/excessive_nesting/auxiliary/proc_macros.rs b/tests/ui-toml/excessive_nesting/auxiliary/proc_macros.rs index 87620fe91ba..df17974de03 100644 --- a/tests/ui-toml/excessive_nesting/auxiliary/proc_macros.rs +++ b/tests/ui-toml/excessive_nesting/auxiliary/proc_macros.rs @@ -6,7 +6,7 @@ #![crate_type = "proc-macro"] #![feature(let_chains)] #![feature(proc_macro_span)] -#![allow(dead_code)] +#![allow(clippy::excessive_nesting, dead_code)] extern crate proc_macro; diff --git a/tests/ui-toml/excessive_nesting/above/clippy.toml b/tests/ui-toml/excessive_nesting/clippy.toml similarity index 100% rename from tests/ui-toml/excessive_nesting/above/clippy.toml rename to tests/ui-toml/excessive_nesting/clippy.toml diff --git a/tests/ui-toml/excessive_nesting/excessive_nesting.rs b/tests/ui-toml/excessive_nesting/excessive_nesting.rs index 432c4132b57..d771cb9b55e 100644 --- a/tests/ui-toml/excessive_nesting/excessive_nesting.rs +++ b/tests/ui-toml/excessive_nesting/excessive_nesting.rs @@ -1,7 +1,4 @@ //@aux-build:proc_macros.rs -//@revisions: set above -//@[set] rustc-env:CLIPPY_CONF_DIR=tests/ui-toml/excessive_nesting/set -//@[above] rustc-env:CLIPPY_CONF_DIR=tests/ui-toml/excessive_nesting/above #![rustfmt::skip] #![feature(custom_inner_attributes)] #![allow(unused)] diff --git a/tests/ui-toml/excessive_nesting/excessive_nesting.set.stderr b/tests/ui-toml/excessive_nesting/excessive_nesting.set.stderr deleted file mode 100644 index 237cc6c4a90..00000000000 --- a/tests/ui-toml/excessive_nesting/excessive_nesting.set.stderr +++ /dev/null @@ -1,351 +0,0 @@ -error: this block is too nested - --> $DIR/excessive_nesting.rs:22:21 - | -LL | let z = { - | _____________________^ -LL | | let w = { 3 }; -LL | | w -LL | | }; - | |_____________^ - | - = help: try refactoring your code to minimize nesting - = note: `-D clippy::excessive-nesting` implied by `-D warnings` - -error: this block is too nested - --> $DIR/excessive_nesting.rs:66:24 - | -LL | pub fn b() { - | ________________________^ -LL | | struct C; -LL | | -LL | | impl C { -LL | | pub fn c() {} -LL | | } -LL | | } - | |_____________^ - | - = help: try refactoring your code to minimize nesting - -error: this block is too nested - --> $DIR/excessive_nesting.rs:82:21 - | -LL | fn cc() { - | _____________________^ -LL | | let x = { 1 }; // not a warning, but cc is -LL | | } - | |_____________^ - | - = help: try refactoring your code to minimize nesting - -error: this block is too nested - --> $DIR/excessive_nesting.rs:86:21 - | -LL | let x = { 1 }; // warning - | ^^^^^ - | - = help: try refactoring your code to minimize nesting - -error: this block is too nested - --> $DIR/excessive_nesting.rs:99:13 - | -LL | / pub mod d { -LL | | pub mod e { -LL | | pub mod f {} -LL | | } // not here -LL | | } // only warning should be here - | |_____________^ - | - = help: try refactoring your code to minimize nesting - -error: this block is too nested - --> $DIR/excessive_nesting.rs:113:17 - | -LL | a_but_not({{{{{{{{0}}}}}}}}); - | ^^^^^^^^^^^^^ - | - = help: try refactoring your code to minimize nesting - -error: this block is too nested - --> $DIR/excessive_nesting.rs:114:11 - | -LL | a.a({{{{{{{{{0}}}}}}}}}); - | ^^^^^^^^^^^^^^^ - | - = help: try refactoring your code to minimize nesting - -error: this block is too nested - --> $DIR/excessive_nesting.rs:115:11 - | -LL | (0, {{{{{{{1}}}}}}}); - | ^^^^^^^^^^^ - | - = help: try refactoring your code to minimize nesting - -error: this block is too nested - --> $DIR/excessive_nesting.rs:119:21 - | -LL | if true { - | _____________________^ -LL | | if true { -LL | | if true { -LL | | -LL | | } -LL | | } -LL | | } - | |_____________^ - | - = help: try refactoring your code to minimize nesting - -error: this block is too nested - --> $DIR/excessive_nesting.rs:131:25 - | -LL | let y = (|| { - | _________________________^ -LL | | let z = (|| { -LL | | let w = { 3 }; -LL | | w -LL | | })(); -LL | | z -LL | | })(); - | |_____________^ - | - = help: try refactoring your code to minimize nesting - -error: this block is too nested - --> $DIR/excessive_nesting.rs:147:36 - | -LL | !{boo as u32 + !{boo as u32 + !{boo as u32}}}; - | ^^^^^^^^^^^^ - | - = help: try refactoring your code to minimize nesting - -error: this block is too nested - --> $DIR/excessive_nesting.rs:151:12 - | -LL | y += {{{{{5}}}}}; - | ^^^^^^^ - | - = help: try refactoring your code to minimize nesting - -error: this block is too nested - --> $DIR/excessive_nesting.rs:152:19 - | -LL | let z = y + {{{{{{{{{5}}}}}}}}}; - | ^^^^^^^^^^^^^^^ - | - = help: try refactoring your code to minimize nesting - -error: this block is too nested - --> $DIR/excessive_nesting.rs:153:11 - | -LL | [0, {{{{{{{{{{0}}}}}}}}}}]; - | ^^^^^^^^^^^^^^^^^ - | - = help: try refactoring your code to minimize nesting - -error: this block is too nested - --> $DIR/excessive_nesting.rs:154:24 - | -LL | let mut xx = [0; {{{{{{{{100}}}}}}}}]; - | ^^^^^^^^^^^^^^^ - | - = help: try refactoring your code to minimize nesting - -error: this block is too nested - --> $DIR/excessive_nesting.rs:155:10 - | -LL | xx[{{{{{{{{{{{{{{{{{{{{{{{{3}}}}}}}}}}}}}}}}}}}}}}}}]; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = help: try refactoring your code to minimize nesting - -error: this block is too nested - --> $DIR/excessive_nesting.rs:156:12 - | -LL | &mut {{{{{{{{{{y}}}}}}}}}}; - | ^^^^^^^^^^^^^^^^^ - | - = help: try refactoring your code to minimize nesting - -error: this block is too nested - --> $DIR/excessive_nesting.rs:158:16 - | -LL | for i in {{{{xx}}}} {{{{{{{{}}}}}}}} - | ^^^^^^ - | - = help: try refactoring your code to minimize nesting - -error: this block is too nested - --> $DIR/excessive_nesting.rs:158:27 - | -LL | for i in {{{{xx}}}} {{{{{{{{}}}}}}}} - | ^^^^^^^^^^^^ - | - = help: try refactoring your code to minimize nesting - -error: this block is too nested - --> $DIR/excessive_nesting.rs:160:27 - | -LL | while let Some(i) = {{{{{{Some(1)}}}}}} {{{{{{{}}}}}}} - | ^^^^^^^^^^^^^^^ - | - = help: try refactoring your code to minimize nesting - -error: this block is too nested - --> $DIR/excessive_nesting.rs:160:47 - | -LL | while let Some(i) = {{{{{{Some(1)}}}}}} {{{{{{{}}}}}}} - | ^^^^^^^^^^ - | - = help: try refactoring your code to minimize nesting - -error: this block is too nested - --> $DIR/excessive_nesting.rs:162:13 - | -LL | while {{{{{{{{true}}}}}}}} {{{{{{{{{}}}}}}}}} - | ^^^^^^^^^^^^^^^^ - | - = help: try refactoring your code to minimize nesting - -error: this block is too nested - --> $DIR/excessive_nesting.rs:162:34 - | -LL | while {{{{{{{{true}}}}}}}} {{{{{{{{{}}}}}}}}} - | ^^^^^^^^^^^^^^ - | - = help: try refactoring your code to minimize nesting - -error: this block is too nested - --> $DIR/excessive_nesting.rs:164:22 - | -LL | let d = D { d: {{{{{{{{{{{{{{{{{{{{{{{3}}}}}}}}}}}}}}}}}}}}}}} }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = help: try refactoring your code to minimize nesting - -error: this block is too nested - --> $DIR/excessive_nesting.rs:166:7 - | -LL | {{{{1;}}}}..{{{{{{3}}}}}}; - | ^^^^^^ - | - = help: try refactoring your code to minimize nesting - -error: this block is too nested - --> $DIR/excessive_nesting.rs:166:19 - | -LL | {{{{1;}}}}..{{{{{{3}}}}}}; - | ^^^^^^^^^ - | - = help: try refactoring your code to minimize nesting - -error: this block is too nested - --> $DIR/excessive_nesting.rs:167:7 - | -LL | {{{{1;}}}}..={{{{{{{{{{{{{{{{{{{{{{{{{{6}}}}}}}}}}}}}}}}}}}}}}}}}}; - | ^^^^^^ - | - = help: try refactoring your code to minimize nesting - -error: this block is too nested - --> $DIR/excessive_nesting.rs:167:20 - | -LL | {{{{1;}}}}..={{{{{{{{{{{{{{{{{{{{{{{{{{6}}}}}}}}}}}}}}}}}}}}}}}}}}; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = help: try refactoring your code to minimize nesting - -error: this block is too nested - --> $DIR/excessive_nesting.rs:168:9 - | -LL | ..{{{{{{{5}}}}}}}; - | ^^^^^^^^^^^ - | - = help: try refactoring your code to minimize nesting - -error: this block is too nested - --> $DIR/excessive_nesting.rs:169:10 - | -LL | ..={{{{{3}}}}}; - | ^^^^^^^ - | - = help: try refactoring your code to minimize nesting - -error: this block is too nested - --> $DIR/excessive_nesting.rs:170:7 - | -LL | {{{{{1;}}}}}..; - | ^^^^^^^^ - | - = help: try refactoring your code to minimize nesting - -error: this block is too nested - --> $DIR/excessive_nesting.rs:172:19 - | -LL | loop { break {{{{1}}}} }; - | ^^^^^^^ - | - = help: try refactoring your code to minimize nesting - -error: this block is too nested - --> $DIR/excessive_nesting.rs:173:12 - | -LL | loop {{{{{{}}}}}} - | ^^^^^^^^ - | - = help: try refactoring your code to minimize nesting - -error: this block is too nested - --> $DIR/excessive_nesting.rs:175:13 - | -LL | match {{{{{{true}}}}}} { - | ^^^^^^^^^^^^ - | - = help: try refactoring your code to minimize nesting - -error: this block is too nested - --> $DIR/excessive_nesting.rs:176:19 - | -LL | true => {{{{}}}}, - | ^^^^ - | - = help: try refactoring your code to minimize nesting - -error: this block is too nested - --> $DIR/excessive_nesting.rs:177:20 - | -LL | false => {{{{}}}}, - | ^^^^ - | - = help: try refactoring your code to minimize nesting - -error: this block is too nested - --> $DIR/excessive_nesting.rs:182:13 - | -LL | / { -LL | | { -LL | | println!("warning! :)"); -LL | | } -LL | | } - | |_____________^ - | - = help: try refactoring your code to minimize nesting - -error: this block is too nested - --> $DIR/excessive_nesting.rs:192:27 - | -LL | async fn c() -> u32 {{{{{{{0}}}}}}} - | ^^^^^^^^^^^ - | - = help: try refactoring your code to minimize nesting - -error: this block is too nested - --> $DIR/excessive_nesting.rs:198:7 - | -LL | {{{{b().await}}}}; - | ^^^^^^^^^^^^^ - | - = help: try refactoring your code to minimize nesting - -error: aborting due to 39 previous errors - diff --git a/tests/ui-toml/excessive_nesting/excessive_nesting.above.stderr b/tests/ui-toml/excessive_nesting/excessive_nesting.stderr similarity index 83% rename from tests/ui-toml/excessive_nesting/excessive_nesting.above.stderr rename to tests/ui-toml/excessive_nesting/excessive_nesting.stderr index 0ec41fbaa07..a9fb159ef2a 100644 --- a/tests/ui-toml/excessive_nesting/excessive_nesting.above.stderr +++ b/tests/ui-toml/excessive_nesting/excessive_nesting.stderr @@ -1,5 +1,5 @@ error: this block is too nested - --> $DIR/excessive_nesting.rs:23:25 + --> $DIR/excessive_nesting.rs:20:25 | LL | let w = { 3 }; | ^^^^^ @@ -8,7 +8,7 @@ LL | let w = { 3 }; = note: `-D clippy::excessive-nesting` implied by `-D warnings` error: this block is too nested - --> $DIR/excessive_nesting.rs:69:17 + --> $DIR/excessive_nesting.rs:66:17 | LL | / impl C { LL | | pub fn c() {} @@ -18,7 +18,7 @@ LL | | } = help: try refactoring your code to minimize nesting error: this block is too nested - --> $DIR/excessive_nesting.rs:83:25 + --> $DIR/excessive_nesting.rs:80:25 | LL | let x = { 1 }; // not a warning, but cc is | ^^^^^ @@ -26,7 +26,7 @@ LL | let x = { 1 }; // not a warning, but cc is = help: try refactoring your code to minimize nesting error: this block is too nested - --> $DIR/excessive_nesting.rs:100:17 + --> $DIR/excessive_nesting.rs:97:17 | LL | / pub mod e { LL | | pub mod f {} @@ -36,7 +36,7 @@ LL | | } // not here = help: try refactoring your code to minimize nesting error: this block is too nested - --> $DIR/excessive_nesting.rs:113:18 + --> $DIR/excessive_nesting.rs:110:18 | LL | a_but_not({{{{{{{{0}}}}}}}}); | ^^^^^^^^^^^ @@ -44,7 +44,7 @@ LL | a_but_not({{{{{{{{0}}}}}}}}); = help: try refactoring your code to minimize nesting error: this block is too nested - --> $DIR/excessive_nesting.rs:114:12 + --> $DIR/excessive_nesting.rs:111:12 | LL | a.a({{{{{{{{{0}}}}}}}}}); | ^^^^^^^^^^^^^ @@ -52,7 +52,7 @@ LL | a.a({{{{{{{{{0}}}}}}}}}); = help: try refactoring your code to minimize nesting error: this block is too nested - --> $DIR/excessive_nesting.rs:115:12 + --> $DIR/excessive_nesting.rs:112:12 | LL | (0, {{{{{{{1}}}}}}}); | ^^^^^^^^^ @@ -60,7 +60,7 @@ LL | (0, {{{{{{{1}}}}}}}); = help: try refactoring your code to minimize nesting error: this block is too nested - --> $DIR/excessive_nesting.rs:120:25 + --> $DIR/excessive_nesting.rs:117:25 | LL | if true { | _________________________^ @@ -73,7 +73,7 @@ LL | | } = help: try refactoring your code to minimize nesting error: this block is too nested - --> $DIR/excessive_nesting.rs:132:29 + --> $DIR/excessive_nesting.rs:129:29 | LL | let z = (|| { | _____________________________^ @@ -85,7 +85,7 @@ LL | | })(); = help: try refactoring your code to minimize nesting error: this block is too nested - --> $DIR/excessive_nesting.rs:151:13 + --> $DIR/excessive_nesting.rs:148:13 | LL | y += {{{{{5}}}}}; | ^^^^^ @@ -93,7 +93,7 @@ LL | y += {{{{{5}}}}}; = help: try refactoring your code to minimize nesting error: this block is too nested - --> $DIR/excessive_nesting.rs:152:20 + --> $DIR/excessive_nesting.rs:149:20 | LL | let z = y + {{{{{{{{{5}}}}}}}}}; | ^^^^^^^^^^^^^ @@ -101,7 +101,7 @@ LL | let z = y + {{{{{{{{{5}}}}}}}}}; = help: try refactoring your code to minimize nesting error: this block is too nested - --> $DIR/excessive_nesting.rs:153:12 + --> $DIR/excessive_nesting.rs:150:12 | LL | [0, {{{{{{{{{{0}}}}}}}}}}]; | ^^^^^^^^^^^^^^^ @@ -109,7 +109,7 @@ LL | [0, {{{{{{{{{{0}}}}}}}}}}]; = help: try refactoring your code to minimize nesting error: this block is too nested - --> $DIR/excessive_nesting.rs:154:25 + --> $DIR/excessive_nesting.rs:151:25 | LL | let mut xx = [0; {{{{{{{{100}}}}}}}}]; | ^^^^^^^^^^^^^ @@ -117,7 +117,7 @@ LL | let mut xx = [0; {{{{{{{{100}}}}}}}}]; = help: try refactoring your code to minimize nesting error: this block is too nested - --> $DIR/excessive_nesting.rs:155:11 + --> $DIR/excessive_nesting.rs:152:11 | LL | xx[{{{{{{{{{{{{{{{{{{{{{{{{3}}}}}}}}}}}}}}}}}}}}}}}}]; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -125,7 +125,7 @@ LL | xx[{{{{{{{{{{{{{{{{{{{{{{{{3}}}}}}}}}}}}}}}}}}}}}}}}]; = help: try refactoring your code to minimize nesting error: this block is too nested - --> $DIR/excessive_nesting.rs:156:13 + --> $DIR/excessive_nesting.rs:153:13 | LL | &mut {{{{{{{{{{y}}}}}}}}}}; | ^^^^^^^^^^^^^^^ @@ -133,7 +133,7 @@ LL | &mut {{{{{{{{{{y}}}}}}}}}}; = help: try refactoring your code to minimize nesting error: this block is too nested - --> $DIR/excessive_nesting.rs:158:17 + --> $DIR/excessive_nesting.rs:155:17 | LL | for i in {{{{xx}}}} {{{{{{{{}}}}}}}} | ^^^^ @@ -141,7 +141,7 @@ LL | for i in {{{{xx}}}} {{{{{{{{}}}}}}}} = help: try refactoring your code to minimize nesting error: this block is too nested - --> $DIR/excessive_nesting.rs:158:28 + --> $DIR/excessive_nesting.rs:155:28 | LL | for i in {{{{xx}}}} {{{{{{{{}}}}}}}} | ^^^^^^^^^^ @@ -149,7 +149,7 @@ LL | for i in {{{{xx}}}} {{{{{{{{}}}}}}}} = help: try refactoring your code to minimize nesting error: this block is too nested - --> $DIR/excessive_nesting.rs:160:28 + --> $DIR/excessive_nesting.rs:157:28 | LL | while let Some(i) = {{{{{{Some(1)}}}}}} {{{{{{{}}}}}}} | ^^^^^^^^^^^^^ @@ -157,7 +157,7 @@ LL | while let Some(i) = {{{{{{Some(1)}}}}}} {{{{{{{}}}}}}} = help: try refactoring your code to minimize nesting error: this block is too nested - --> $DIR/excessive_nesting.rs:160:48 + --> $DIR/excessive_nesting.rs:157:48 | LL | while let Some(i) = {{{{{{Some(1)}}}}}} {{{{{{{}}}}}}} | ^^^^^^^^ @@ -165,7 +165,7 @@ LL | while let Some(i) = {{{{{{Some(1)}}}}}} {{{{{{{}}}}}}} = help: try refactoring your code to minimize nesting error: this block is too nested - --> $DIR/excessive_nesting.rs:162:14 + --> $DIR/excessive_nesting.rs:159:14 | LL | while {{{{{{{{true}}}}}}}} {{{{{{{{{}}}}}}}}} | ^^^^^^^^^^^^^^ @@ -173,7 +173,7 @@ LL | while {{{{{{{{true}}}}}}}} {{{{{{{{{}}}}}}}}} = help: try refactoring your code to minimize nesting error: this block is too nested - --> $DIR/excessive_nesting.rs:162:35 + --> $DIR/excessive_nesting.rs:159:35 | LL | while {{{{{{{{true}}}}}}}} {{{{{{{{{}}}}}}}}} | ^^^^^^^^^^^^ @@ -181,7 +181,7 @@ LL | while {{{{{{{{true}}}}}}}} {{{{{{{{{}}}}}}}}} = help: try refactoring your code to minimize nesting error: this block is too nested - --> $DIR/excessive_nesting.rs:164:23 + --> $DIR/excessive_nesting.rs:161:23 | LL | let d = D { d: {{{{{{{{{{{{{{{{{{{{{{{3}}}}}}}}}}}}}}}}}}}}}}} }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -189,7 +189,7 @@ LL | let d = D { d: {{{{{{{{{{{{{{{{{{{{{{{3}}}}}}}}}}}}}}}}}}}}}}} }; = help: try refactoring your code to minimize nesting error: this block is too nested - --> $DIR/excessive_nesting.rs:166:8 + --> $DIR/excessive_nesting.rs:163:8 | LL | {{{{1;}}}}..{{{{{{3}}}}}}; | ^^^^ @@ -197,7 +197,7 @@ LL | {{{{1;}}}}..{{{{{{3}}}}}}; = help: try refactoring your code to minimize nesting error: this block is too nested - --> $DIR/excessive_nesting.rs:166:20 + --> $DIR/excessive_nesting.rs:163:20 | LL | {{{{1;}}}}..{{{{{{3}}}}}}; | ^^^^^^^ @@ -205,7 +205,7 @@ LL | {{{{1;}}}}..{{{{{{3}}}}}}; = help: try refactoring your code to minimize nesting error: this block is too nested - --> $DIR/excessive_nesting.rs:167:8 + --> $DIR/excessive_nesting.rs:164:8 | LL | {{{{1;}}}}..={{{{{{{{{{{{{{{{{{{{{{{{{{6}}}}}}}}}}}}}}}}}}}}}}}}}}; | ^^^^ @@ -213,7 +213,7 @@ LL | {{{{1;}}}}..={{{{{{{{{{{{{{{{{{{{{{{{{{6}}}}}}}}}}}}}}}}}}}}}}}}}}; = help: try refactoring your code to minimize nesting error: this block is too nested - --> $DIR/excessive_nesting.rs:167:21 + --> $DIR/excessive_nesting.rs:164:21 | LL | {{{{1;}}}}..={{{{{{{{{{{{{{{{{{{{{{{{{{6}}}}}}}}}}}}}}}}}}}}}}}}}}; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -221,7 +221,7 @@ LL | {{{{1;}}}}..={{{{{{{{{{{{{{{{{{{{{{{{{{6}}}}}}}}}}}}}}}}}}}}}}}}}}; = help: try refactoring your code to minimize nesting error: this block is too nested - --> $DIR/excessive_nesting.rs:168:10 + --> $DIR/excessive_nesting.rs:165:10 | LL | ..{{{{{{{5}}}}}}}; | ^^^^^^^^^ @@ -229,7 +229,7 @@ LL | ..{{{{{{{5}}}}}}}; = help: try refactoring your code to minimize nesting error: this block is too nested - --> $DIR/excessive_nesting.rs:169:11 + --> $DIR/excessive_nesting.rs:166:11 | LL | ..={{{{{3}}}}}; | ^^^^^ @@ -237,7 +237,7 @@ LL | ..={{{{{3}}}}}; = help: try refactoring your code to minimize nesting error: this block is too nested - --> $DIR/excessive_nesting.rs:170:8 + --> $DIR/excessive_nesting.rs:167:8 | LL | {{{{{1;}}}}}..; | ^^^^^^ @@ -245,7 +245,7 @@ LL | {{{{{1;}}}}}..; = help: try refactoring your code to minimize nesting error: this block is too nested - --> $DIR/excessive_nesting.rs:172:20 + --> $DIR/excessive_nesting.rs:169:20 | LL | loop { break {{{{1}}}} }; | ^^^^^ @@ -253,7 +253,7 @@ LL | loop { break {{{{1}}}} }; = help: try refactoring your code to minimize nesting error: this block is too nested - --> $DIR/excessive_nesting.rs:173:13 + --> $DIR/excessive_nesting.rs:170:13 | LL | loop {{{{{{}}}}}} | ^^^^^^ @@ -261,7 +261,7 @@ LL | loop {{{{{{}}}}}} = help: try refactoring your code to minimize nesting error: this block is too nested - --> $DIR/excessive_nesting.rs:175:14 + --> $DIR/excessive_nesting.rs:172:14 | LL | match {{{{{{true}}}}}} { | ^^^^^^^^^^ @@ -269,7 +269,7 @@ LL | match {{{{{{true}}}}}} { = help: try refactoring your code to minimize nesting error: this block is too nested - --> $DIR/excessive_nesting.rs:176:20 + --> $DIR/excessive_nesting.rs:173:20 | LL | true => {{{{}}}}, | ^^ @@ -277,7 +277,7 @@ LL | true => {{{{}}}}, = help: try refactoring your code to minimize nesting error: this block is too nested - --> $DIR/excessive_nesting.rs:177:21 + --> $DIR/excessive_nesting.rs:174:21 | LL | false => {{{{}}}}, | ^^ @@ -285,7 +285,7 @@ LL | false => {{{{}}}}, = help: try refactoring your code to minimize nesting error: this block is too nested - --> $DIR/excessive_nesting.rs:183:17 + --> $DIR/excessive_nesting.rs:180:17 | LL | / { LL | | println!("warning! :)"); @@ -295,7 +295,7 @@ LL | | } = help: try refactoring your code to minimize nesting error: this block is too nested - --> $DIR/excessive_nesting.rs:192:28 + --> $DIR/excessive_nesting.rs:189:28 | LL | async fn c() -> u32 {{{{{{{0}}}}}}} | ^^^^^^^^^ @@ -303,7 +303,7 @@ LL | async fn c() -> u32 {{{{{{{0}}}}}}} = help: try refactoring your code to minimize nesting error: this block is too nested - --> $DIR/excessive_nesting.rs:198:8 + --> $DIR/excessive_nesting.rs:195:8 | LL | {{{{b().await}}}}; | ^^^^^^^^^^^ diff --git a/tests/ui-toml/excessive_nesting/set/clippy.toml b/tests/ui-toml/excessive_nesting/set/clippy.toml deleted file mode 100644 index 10be2751a86..00000000000 --- a/tests/ui-toml/excessive_nesting/set/clippy.toml +++ /dev/null @@ -1 +0,0 @@ -excessive-nesting-threshold = 3 From 46808be16f38c3c09e9b7af5d08e9b8abb7cab13 Mon Sep 17 00:00:00 2001 From: Alex Macleod Date: Thu, 8 Jun 2023 12:47:15 +0000 Subject: [PATCH 106/310] Direct towards late passes in `cargo dev new_lint` --- clippy_dev/src/main.rs | 4 ++-- clippy_dev/src/new_lint.rs | 12 ++++++++++-- 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/clippy_dev/src/main.rs b/clippy_dev/src/main.rs index c03fbe9d275..97d6a8353a0 100644 --- a/clippy_dev/src/main.rs +++ b/clippy_dev/src/main.rs @@ -35,7 +35,7 @@ fn main() { }, Some(("new_lint", matches)) => { match new_lint::create( - matches.get_one::("pass"), + matches.get_one::("pass").unwrap(), matches.get_one::("name"), matches.get_one::("category").map(String::as_str), matches.get_one::("type").map(String::as_str), @@ -176,7 +176,7 @@ fn get_clap_config() -> ArgMatches { .help("Specify whether the lint runs during the early or late pass") .value_parser(["early", "late"]) .conflicts_with("type") - .required_unless_present("type"), + .default_value("late"), Arg::new("name") .short('n') .long("name") diff --git a/clippy_dev/src/new_lint.rs b/clippy_dev/src/new_lint.rs index 13a27703427..f970a32726b 100644 --- a/clippy_dev/src/new_lint.rs +++ b/clippy_dev/src/new_lint.rs @@ -37,7 +37,7 @@ impl Context for io::Result { /// /// This function errors out if the files couldn't be created or written to. pub fn create( - pass: Option<&String>, + pass: &String, lint_name: Option<&String>, category: Option<&str>, mut ty: Option<&str>, @@ -49,7 +49,7 @@ pub fn create( } let lint = LintData { - pass: pass.map_or("", String::as_str), + pass, name: lint_name.expect("`name` argument is validated by clap"), category: category.expect("`category` argument is validated by clap"), ty, @@ -63,6 +63,14 @@ pub fn create( add_lint(&lint, msrv).context("Unable to add lint to clippy_lints/src/lib.rs")?; } + if pass == "early" { + println!( + "\n\ + NOTE: Use a late pass unless you need something specific from\ + an early pass, as they lack many features and utilities" + ); + } + Ok(()) } From 96697d2ee7dfe1bc67a7c11ae5f90d38548aaf04 Mon Sep 17 00:00:00 2001 From: Alex Macleod Date: Thu, 8 Jun 2023 17:05:08 +0000 Subject: [PATCH 107/310] Fix `useless_vec` suggestion in `for _ in vec![..]` --- clippy_lints/src/lib.rs | 7 +++++- clippy_lints/src/vec.rs | 12 +++++++---- tests/ui/vec.fixed | 37 ++++++++++++++++++++----------- tests/ui/vec.rs | 35 +++++++++++++++++++----------- tests/ui/vec.stderr | 48 +++++++++++++++++++++++------------------ 5 files changed, 88 insertions(+), 51 deletions(-) diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index 2f5932104c1..2dbdee977b0 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -699,7 +699,12 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: }); let too_large_for_stack = conf.too_large_for_stack; store.register_late_pass(move |_| Box::new(escape::BoxedLocal { too_large_for_stack })); - store.register_late_pass(move |_| Box::new(vec::UselessVec { too_large_for_stack })); + store.register_late_pass(move |_| { + Box::new(vec::UselessVec { + too_large_for_stack, + msrv: msrv(), + }) + }); store.register_late_pass(|_| Box::new(panic_unimplemented::PanicUnimplemented)); store.register_late_pass(|_| Box::new(strings::StringLitAsBytes)); store.register_late_pass(|_| Box::new(derive::Derive)); diff --git a/clippy_lints/src/vec.rs b/clippy_lints/src/vec.rs index 467805d90ff..25b6f40762d 100644 --- a/clippy_lints/src/vec.rs +++ b/clippy_lints/src/vec.rs @@ -2,6 +2,7 @@ use std::ops::ControlFlow; use clippy_utils::consts::{constant, Constant}; use clippy_utils::diagnostics::span_lint_and_sugg; +use clippy_utils::msrvs::{self, Msrv}; use clippy_utils::source::snippet_with_applicability; use clippy_utils::ty::is_copy; use clippy_utils::visitors::for_each_local_use_after_expr; @@ -18,9 +19,10 @@ use rustc_span::source_map::Span; use rustc_span::sym; #[expect(clippy::module_name_repetitions)] -#[derive(Copy, Clone)] +#[derive(Clone)] pub struct UselessVec { pub too_large_for_stack: u64, + pub msrv: Msrv, } declare_clippy_lint! { @@ -122,14 +124,16 @@ impl<'tcx> LateLintPass<'tcx> for UselessVec { if_chain! { if let Some(higher::ForLoop { arg, .. }) = higher::ForLoop::hir(expr); if let Some(vec_args) = higher::VecArgs::hir(cx, arg); - if is_copy(cx, vec_type(cx.typeck_results().expr_ty_adjusted(arg))); + if self.msrv.meets(msrvs::ARRAY_INTO_ITERATOR); then { // report the error around the `vec!` not inside `:` let span = arg.span.ctxt().outer_expn_data().call_site; - self.check_vec_macro(cx, &vec_args, Mutability::Not, span, SuggestSlice::Yes); + self.check_vec_macro(cx, &vec_args, Mutability::Not, span, SuggestSlice::No); } } } + + extract_msrv_attr!(LateContext); } #[derive(Copy, Clone)] @@ -142,7 +146,7 @@ enum SuggestSlice { impl UselessVec { fn check_vec_macro<'tcx>( - self, + &mut self, cx: &LateContext<'tcx>, vec_args: &higher::VecArgs<'tcx>, mutability: Mutability, diff --git a/tests/ui/vec.fixed b/tests/ui/vec.fixed index 1bdde69f6f4..55329ee843d 100644 --- a/tests/ui/vec.fixed +++ b/tests/ui/vec.fixed @@ -1,6 +1,6 @@ //@run-rustfix #![warn(clippy::useless_vec)] -#![allow(clippy::nonstandard_macro_braces, clippy::uninlined_format_args)] +#![allow(clippy::nonstandard_macro_braces, clippy::uninlined_format_args, unused)] use std::rc::Rc; @@ -8,9 +8,6 @@ struct StructWithVec { _x: Vec, } -#[derive(Debug)] -struct NonCopy; - fn on_slice(_: &[u8]) {} fn on_mut_slice(_: &mut [u8]) {} @@ -66,14 +63,6 @@ fn main() { on_mut_slice(&mut vec![2; line.length]); on_mut_slice(&mut vec![2; line.length()]); - for a in &[1, 2, 3] { - println!("{:?}", a); - } - - for a in vec![NonCopy, NonCopy] { - println!("{:?}", a); - } - on_vec(&vec![1; 201]); // Ok, size of `vec` higher than `too_large_for_stack` on_mut_vec(&mut vec![1; 201]); // Ok, size of `vec` higher than `too_large_for_stack` @@ -91,7 +80,7 @@ fn main() { let _x: &[i32] = &[1, 2, 3]; - for _ in &[1, 2, 3] {} + for _ in [1, 2, 3] {} // Don't lint let x = vec![1, 2, 3]; @@ -122,3 +111,25 @@ fn main() { // Too large let _x = vec![1; 201]; } + +#[clippy::msrv = "1.53"] +fn above() { + for a in [1, 2, 3] { + let _: usize = a; + } + + for a in [String::new(), String::new()] { + let _: String = a; + } +} + +#[clippy::msrv = "1.52"] +fn below() { + for a in vec![1, 2, 3] { + let _: usize = a; + } + + for a in vec![String::new(), String::new()] { + let _: String = a; + } +} diff --git a/tests/ui/vec.rs b/tests/ui/vec.rs index 89c6a72f339..bab316fa620 100644 --- a/tests/ui/vec.rs +++ b/tests/ui/vec.rs @@ -1,6 +1,6 @@ //@run-rustfix #![warn(clippy::useless_vec)] -#![allow(clippy::nonstandard_macro_braces, clippy::uninlined_format_args)] +#![allow(clippy::nonstandard_macro_braces, clippy::uninlined_format_args, unused)] use std::rc::Rc; @@ -8,9 +8,6 @@ struct StructWithVec { _x: Vec, } -#[derive(Debug)] -struct NonCopy; - fn on_slice(_: &[u8]) {} fn on_mut_slice(_: &mut [u8]) {} @@ -66,14 +63,6 @@ fn main() { on_mut_slice(&mut vec![2; line.length]); on_mut_slice(&mut vec![2; line.length()]); - for a in vec![1, 2, 3] { - println!("{:?}", a); - } - - for a in vec![NonCopy, NonCopy] { - println!("{:?}", a); - } - on_vec(&vec![1; 201]); // Ok, size of `vec` higher than `too_large_for_stack` on_mut_vec(&mut vec![1; 201]); // Ok, size of `vec` higher than `too_large_for_stack` @@ -122,3 +111,25 @@ fn main() { // Too large let _x = vec![1; 201]; } + +#[clippy::msrv = "1.53"] +fn above() { + for a in vec![1, 2, 3] { + let _: usize = a; + } + + for a in vec![String::new(), String::new()] { + let _: String = a; + } +} + +#[clippy::msrv = "1.52"] +fn below() { + for a in vec![1, 2, 3] { + let _: usize = a; + } + + for a in vec![String::new(), String::new()] { + let _: String = a; + } +} diff --git a/tests/ui/vec.stderr b/tests/ui/vec.stderr index f94a82d2171..f3a4bf925dd 100644 --- a/tests/ui/vec.stderr +++ b/tests/ui/vec.stderr @@ -1,5 +1,5 @@ error: useless use of `vec!` - --> $DIR/vec.rs:34:14 + --> $DIR/vec.rs:31:14 | LL | on_slice(&vec![]); | ^^^^^^^ help: you can use a slice directly: `&[]` @@ -7,82 +7,88 @@ LL | on_slice(&vec![]); = note: `-D clippy::useless-vec` implied by `-D warnings` error: useless use of `vec!` - --> $DIR/vec.rs:36:18 + --> $DIR/vec.rs:33:18 | LL | on_mut_slice(&mut vec![]); | ^^^^^^^^^^^ help: you can use a slice directly: `&mut []` error: useless use of `vec!` - --> $DIR/vec.rs:38:14 + --> $DIR/vec.rs:35:14 | LL | on_slice(&vec![1, 2]); | ^^^^^^^^^^^ help: you can use a slice directly: `&[1, 2]` error: useless use of `vec!` - --> $DIR/vec.rs:40:18 + --> $DIR/vec.rs:37:18 | LL | on_mut_slice(&mut vec![1, 2]); | ^^^^^^^^^^^^^^^ help: you can use a slice directly: `&mut [1, 2]` error: useless use of `vec!` - --> $DIR/vec.rs:42:14 + --> $DIR/vec.rs:39:14 | LL | on_slice(&vec![1, 2]); | ^^^^^^^^^^^ help: you can use a slice directly: `&[1, 2]` error: useless use of `vec!` - --> $DIR/vec.rs:44:18 + --> $DIR/vec.rs:41:18 | LL | on_mut_slice(&mut vec![1, 2]); | ^^^^^^^^^^^^^^^ help: you can use a slice directly: `&mut [1, 2]` error: useless use of `vec!` - --> $DIR/vec.rs:46:14 + --> $DIR/vec.rs:43:14 | LL | on_slice(&vec!(1, 2)); | ^^^^^^^^^^^ help: you can use a slice directly: `&[1, 2]` error: useless use of `vec!` - --> $DIR/vec.rs:48:18 + --> $DIR/vec.rs:45:18 | LL | on_mut_slice(&mut vec![1, 2]); | ^^^^^^^^^^^^^^^ help: you can use a slice directly: `&mut [1, 2]` error: useless use of `vec!` - --> $DIR/vec.rs:50:14 + --> $DIR/vec.rs:47:14 | LL | on_slice(&vec![1; 2]); | ^^^^^^^^^^^ help: you can use a slice directly: `&[1; 2]` error: useless use of `vec!` - --> $DIR/vec.rs:52:18 + --> $DIR/vec.rs:49:18 | LL | on_mut_slice(&mut vec![1; 2]); | ^^^^^^^^^^^^^^^ help: you can use a slice directly: `&mut [1; 2]` error: useless use of `vec!` - --> $DIR/vec.rs:69:14 - | -LL | for a in vec![1, 2, 3] { - | ^^^^^^^^^^^^^ help: you can use a slice directly: `&[1, 2, 3]` - -error: useless use of `vec!` - --> $DIR/vec.rs:86:17 + --> $DIR/vec.rs:75:17 | LL | let mut x = vec![1, 2, 3]; | ^^^^^^^^^^^^^ help: you can use an array directly: `[1, 2, 3]` error: useless use of `vec!` - --> $DIR/vec.rs:92:22 + --> $DIR/vec.rs:81:22 | LL | let _x: &[i32] = &vec![1, 2, 3]; | ^^^^^^^^^^^^^^ help: you can use a slice directly: `&[1, 2, 3]` error: useless use of `vec!` - --> $DIR/vec.rs:94:14 + --> $DIR/vec.rs:83:14 | LL | for _ in vec![1, 2, 3] {} - | ^^^^^^^^^^^^^ help: you can use a slice directly: `&[1, 2, 3]` + | ^^^^^^^^^^^^^ help: you can use an array directly: `[1, 2, 3]` -error: aborting due to 14 previous errors +error: useless use of `vec!` + --> $DIR/vec.rs:117:14 + | +LL | for a in vec![1, 2, 3] { + | ^^^^^^^^^^^^^ help: you can use an array directly: `[1, 2, 3]` + +error: useless use of `vec!` + --> $DIR/vec.rs:121:14 + | +LL | for a in vec![String::new(), String::new()] { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: you can use an array directly: `[String::new(), String::new()]` + +error: aborting due to 15 previous errors From 55c9100334ceeccecc75fbdfc5bef321404bc066 Mon Sep 17 00:00:00 2001 From: Renato Lochetti Date: Thu, 8 Jun 2023 19:04:35 +0100 Subject: [PATCH 108/310] Don't ling `as_conversions` in proc macros --- clippy_lints/src/as_conversions.rs | 11 ++++++----- clippy_lints/src/lib.rs | 2 +- tests/ui/as_conversions.rs | 11 ++++++++++- tests/ui/as_conversions.stderr | 6 +++--- 4 files changed, 20 insertions(+), 10 deletions(-) diff --git a/clippy_lints/src/as_conversions.rs b/clippy_lints/src/as_conversions.rs index c7a76e5f907..b9dda49ca41 100644 --- a/clippy_lints/src/as_conversions.rs +++ b/clippy_lints/src/as_conversions.rs @@ -1,6 +1,7 @@ use clippy_utils::diagnostics::span_lint_and_help; -use rustc_ast::ast::{Expr, ExprKind}; -use rustc_lint::{EarlyContext, EarlyLintPass, LintContext}; +use clippy_utils::is_from_proc_macro; +use rustc_hir::{Expr, ExprKind}; +use rustc_lint::{LateContext, LateLintPass, LintContext}; use rustc_middle::lint::in_external_macro; use rustc_session::{declare_lint_pass, declare_tool_lint}; @@ -45,9 +46,9 @@ declare_clippy_lint! { declare_lint_pass!(AsConversions => [AS_CONVERSIONS]); -impl EarlyLintPass for AsConversions { - fn check_expr(&mut self, cx: &EarlyContext<'_>, expr: &Expr) { - if in_external_macro(cx.sess(), expr.span) { +impl<'tcx> LateLintPass<'tcx> for AsConversions { + fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &Expr<'tcx>) { + if in_external_macro(cx.sess(), expr.span) || is_from_proc_macro(cx, expr) { return; } diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index 2f5932104c1..163844f7448 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -839,7 +839,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: store.register_late_pass(move |_| Box::new(large_stack_arrays::LargeStackArrays::new(array_size_threshold))); store.register_late_pass(move |_| Box::new(large_const_arrays::LargeConstArrays::new(array_size_threshold))); store.register_late_pass(|_| Box::new(floating_point_arithmetic::FloatingPointArithmetic)); - store.register_early_pass(|| Box::new(as_conversions::AsConversions)); + store.register_late_pass(|_| Box::new(as_conversions::AsConversions)); store.register_late_pass(|_| Box::new(let_underscore::LetUnderscore)); store.register_early_pass(|| Box::::default()); let max_fn_params_bools = conf.max_fn_params_bools; diff --git a/tests/ui/as_conversions.rs b/tests/ui/as_conversions.rs index 890bf0b0a7e..48ca2f6d143 100644 --- a/tests/ui/as_conversions.rs +++ b/tests/ui/as_conversions.rs @@ -1,10 +1,11 @@ //@aux-build:proc_macros.rs #![warn(clippy::as_conversions)] -#![allow(clippy::borrow_as_ptr)] +#![allow(clippy::borrow_as_ptr, unused)] extern crate proc_macros; use proc_macros::external; +use proc_macros::with_span; fn main() { let i = 0u32 as u64; @@ -13,3 +14,11 @@ fn main() { external!(0u32 as u64); } + +with_span!( + span + + fn coverting() { + let x = 0u32 as u64; + } +); diff --git a/tests/ui/as_conversions.stderr b/tests/ui/as_conversions.stderr index 54037a64997..ca41d1378aa 100644 --- a/tests/ui/as_conversions.stderr +++ b/tests/ui/as_conversions.stderr @@ -1,5 +1,5 @@ error: using a potentially dangerous silent `as` conversion - --> $DIR/as_conversions.rs:10:13 + --> $DIR/as_conversions.rs:11:13 | LL | let i = 0u32 as u64; | ^^^^^^^^^^^ @@ -8,7 +8,7 @@ LL | let i = 0u32 as u64; = note: `-D clippy::as-conversions` implied by `-D warnings` error: using a potentially dangerous silent `as` conversion - --> $DIR/as_conversions.rs:12:13 + --> $DIR/as_conversions.rs:13:13 | LL | let j = &i as *const u64 as *mut u64; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -16,7 +16,7 @@ LL | let j = &i as *const u64 as *mut u64; = help: consider using a safe wrapper for this conversion error: using a potentially dangerous silent `as` conversion - --> $DIR/as_conversions.rs:12:13 + --> $DIR/as_conversions.rs:13:13 | LL | let j = &i as *const u64 as *mut u64; | ^^^^^^^^^^^^^^^^ From 4346c992cb555b79b68265535f5720033f2bdca7 Mon Sep 17 00:00:00 2001 From: Alex Macleod Date: Thu, 8 Jun 2023 18:08:06 +0000 Subject: [PATCH 109/310] Ignore more pointer types in `unnecessary_cast` --- clippy_lints/src/casts/unnecessary_cast.rs | 28 +++++++----- tests/ui/unnecessary_cast.fixed | 13 ++++++ tests/ui/unnecessary_cast.rs | 13 ++++++ tests/ui/unnecessary_cast.stderr | 52 +++++++++++----------- 4 files changed, 69 insertions(+), 37 deletions(-) diff --git a/clippy_lints/src/casts/unnecessary_cast.rs b/clippy_lints/src/casts/unnecessary_cast.rs index 08ed8a63e1a..d3d80ff4100 100644 --- a/clippy_lints/src/casts/unnecessary_cast.rs +++ b/clippy_lints/src/casts/unnecessary_cast.rs @@ -1,7 +1,7 @@ use clippy_utils::diagnostics::span_lint_and_sugg; use clippy_utils::numeric_literal::NumericLiteral; use clippy_utils::source::snippet_opt; -use clippy_utils::{get_parent_expr, is_ty_alias, path_to_local}; +use clippy_utils::{get_parent_expr, is_hir_ty_cfg_dependant, is_ty_alias, path_to_local}; use if_chain::if_chain; use rustc_ast::{LitFloatType, LitIntType, LitKind}; use rustc_errors::Applicability; @@ -27,17 +27,23 @@ pub(super) fn check<'tcx>( // check both mutability and type are the same if cast_from.kind() == cast_to.kind(); if let ExprKind::Cast(_, cast_to_hir) = expr.kind; + // Ignore casts to e.g. type aliases and infer types + // - p as pointer_alias + // - p as _ + if let TyKind::Ptr(to_pointee) = cast_to_hir.kind; then { - if_chain! { - if let TyKind::Path(qpath) = cast_to_hir.kind; - if is_ty_alias(&qpath); - then { - return false; - } - } - - if let TyKind::Infer = cast_to_hir.kind { - return false; + match to_pointee.ty.kind { + // Ignore casts to pointers that are aliases or cfg dependant, e.g. + // - p as *const std::ffi::c_char (alias) + // - p as *const std::os::raw::c_char (cfg dependant) + TyKind::Path(qpath) => { + if is_ty_alias(&qpath) || is_hir_ty_cfg_dependant(cx, to_pointee.ty) { + return false; + } + }, + // Ignore `p as *const _` + TyKind::Infer => return false, + _ => {}, } span_lint_and_sugg( diff --git a/tests/ui/unnecessary_cast.fixed b/tests/ui/unnecessary_cast.fixed index 0fd49e7c815..e74476044d9 100644 --- a/tests/ui/unnecessary_cast.fixed +++ b/tests/ui/unnecessary_cast.fixed @@ -45,6 +45,8 @@ fn main() { [1u8, 2].as_mut_ptr() as PtrConstU8; let _: *const u8 = [1u8, 2].as_ptr() as _; let _: *mut u8 = [1u8, 2].as_mut_ptr() as _; + let _: *const u8 = [1u8, 2].as_ptr() as *const _; + let _: *mut u8 = [1u8, 2].as_mut_ptr() as *mut _; owo::([1u32].as_ptr()); uwu::([1u32].as_ptr()); @@ -71,6 +73,17 @@ fn main() { 1 as I32Alias; &1 as &I32Alias; + let i8_ptr: *const i8 = &1; + let u8_ptr: *const u8 = &1; + + // cfg dependant pointees + i8_ptr as *const std::os::raw::c_char; + u8_ptr as *const std::os::raw::c_char; + + // type aliased pointees + i8_ptr as *const std::ffi::c_char; + u8_ptr as *const std::ffi::c_char; + // issue #9960 macro_rules! bind_var { ($id:ident, $e:expr) => {{ diff --git a/tests/ui/unnecessary_cast.rs b/tests/ui/unnecessary_cast.rs index 27669492329..a577fd79899 100644 --- a/tests/ui/unnecessary_cast.rs +++ b/tests/ui/unnecessary_cast.rs @@ -45,6 +45,8 @@ fn main() { [1u8, 2].as_mut_ptr() as PtrConstU8; let _: *const u8 = [1u8, 2].as_ptr() as _; let _: *mut u8 = [1u8, 2].as_mut_ptr() as _; + let _: *const u8 = [1u8, 2].as_ptr() as *const _; + let _: *mut u8 = [1u8, 2].as_mut_ptr() as *mut _; owo::([1u32].as_ptr()) as *const u32; uwu::([1u32].as_ptr()) as *const u8; @@ -71,6 +73,17 @@ fn main() { 1 as I32Alias; &1 as &I32Alias; + let i8_ptr: *const i8 = &1; + let u8_ptr: *const u8 = &1; + + // cfg dependant pointees + i8_ptr as *const std::os::raw::c_char; + u8_ptr as *const std::os::raw::c_char; + + // type aliased pointees + i8_ptr as *const std::ffi::c_char; + u8_ptr as *const std::ffi::c_char; + // issue #9960 macro_rules! bind_var { ($id:ident, $e:expr) => {{ diff --git a/tests/ui/unnecessary_cast.stderr b/tests/ui/unnecessary_cast.stderr index 0e511fb4c7a..7f748fcf4c2 100644 --- a/tests/ui/unnecessary_cast.stderr +++ b/tests/ui/unnecessary_cast.stderr @@ -73,157 +73,157 @@ LL | [1u8, 2].as_mut_ptr() as *mut u8; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `[1u8, 2].as_mut_ptr()` error: casting raw pointers to the same type and constness is unnecessary (`*const u32` -> `*const u32`) - --> $DIR/unnecessary_cast.rs:49:5 + --> $DIR/unnecessary_cast.rs:51:5 | LL | owo::([1u32].as_ptr()) as *const u32; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `owo::([1u32].as_ptr())` error: casting raw pointers to the same type and constness is unnecessary (`*const u8` -> `*const u8`) - --> $DIR/unnecessary_cast.rs:50:5 + --> $DIR/unnecessary_cast.rs:52:5 | LL | uwu::([1u32].as_ptr()) as *const u8; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `uwu::([1u32].as_ptr())` error: casting raw pointers to the same type and constness is unnecessary (`*const u32` -> `*const u32`) - --> $DIR/unnecessary_cast.rs:52:5 + --> $DIR/unnecessary_cast.rs:54:5 | LL | uwu::([1u32].as_ptr()) as *const u32; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `uwu::([1u32].as_ptr())` error: casting integer literal to `f32` is unnecessary - --> $DIR/unnecessary_cast.rs:93:9 + --> $DIR/unnecessary_cast.rs:106:9 | LL | 100 as f32; | ^^^^^^^^^^ help: try: `100_f32` error: casting integer literal to `f64` is unnecessary - --> $DIR/unnecessary_cast.rs:94:9 + --> $DIR/unnecessary_cast.rs:107:9 | LL | 100 as f64; | ^^^^^^^^^^ help: try: `100_f64` error: casting integer literal to `f64` is unnecessary - --> $DIR/unnecessary_cast.rs:95:9 + --> $DIR/unnecessary_cast.rs:108:9 | LL | 100_i32 as f64; | ^^^^^^^^^^^^^^ help: try: `100_f64` error: casting integer literal to `f32` is unnecessary - --> $DIR/unnecessary_cast.rs:96:17 + --> $DIR/unnecessary_cast.rs:109:17 | LL | let _ = -100 as f32; | ^^^^^^^^^^^ help: try: `-100_f32` error: casting integer literal to `f64` is unnecessary - --> $DIR/unnecessary_cast.rs:97:17 + --> $DIR/unnecessary_cast.rs:110:17 | LL | let _ = -100 as f64; | ^^^^^^^^^^^ help: try: `-100_f64` error: casting integer literal to `f64` is unnecessary - --> $DIR/unnecessary_cast.rs:98:17 + --> $DIR/unnecessary_cast.rs:111:17 | LL | let _ = -100_i32 as f64; | ^^^^^^^^^^^^^^^ help: try: `-100_f64` error: casting float literal to `f32` is unnecessary - --> $DIR/unnecessary_cast.rs:99:9 + --> $DIR/unnecessary_cast.rs:112:9 | LL | 100. as f32; | ^^^^^^^^^^^ help: try: `100_f32` error: casting float literal to `f64` is unnecessary - --> $DIR/unnecessary_cast.rs:100:9 + --> $DIR/unnecessary_cast.rs:113:9 | LL | 100. as f64; | ^^^^^^^^^^^ help: try: `100_f64` error: casting integer literal to `u32` is unnecessary - --> $DIR/unnecessary_cast.rs:112:9 + --> $DIR/unnecessary_cast.rs:125:9 | LL | 1 as u32; | ^^^^^^^^ help: try: `1_u32` error: casting integer literal to `i32` is unnecessary - --> $DIR/unnecessary_cast.rs:113:9 + --> $DIR/unnecessary_cast.rs:126:9 | LL | 0x10 as i32; | ^^^^^^^^^^^ help: try: `0x10_i32` error: casting integer literal to `usize` is unnecessary - --> $DIR/unnecessary_cast.rs:114:9 + --> $DIR/unnecessary_cast.rs:127:9 | LL | 0b10 as usize; | ^^^^^^^^^^^^^ help: try: `0b10_usize` error: casting integer literal to `u16` is unnecessary - --> $DIR/unnecessary_cast.rs:115:9 + --> $DIR/unnecessary_cast.rs:128:9 | LL | 0o73 as u16; | ^^^^^^^^^^^ help: try: `0o73_u16` error: casting integer literal to `u32` is unnecessary - --> $DIR/unnecessary_cast.rs:116:9 + --> $DIR/unnecessary_cast.rs:129:9 | LL | 1_000_000_000 as u32; | ^^^^^^^^^^^^^^^^^^^^ help: try: `1_000_000_000_u32` error: casting float literal to `f64` is unnecessary - --> $DIR/unnecessary_cast.rs:118:9 + --> $DIR/unnecessary_cast.rs:131:9 | LL | 1.0 as f64; | ^^^^^^^^^^ help: try: `1.0_f64` error: casting float literal to `f32` is unnecessary - --> $DIR/unnecessary_cast.rs:119:9 + --> $DIR/unnecessary_cast.rs:132:9 | LL | 0.5 as f32; | ^^^^^^^^^^ help: try: `0.5_f32` error: casting integer literal to `i32` is unnecessary - --> $DIR/unnecessary_cast.rs:123:17 + --> $DIR/unnecessary_cast.rs:136:17 | LL | let _ = -1 as i32; | ^^^^^^^^^ help: try: `-1_i32` error: casting float literal to `f32` is unnecessary - --> $DIR/unnecessary_cast.rs:124:17 + --> $DIR/unnecessary_cast.rs:137:17 | LL | let _ = -1.0 as f32; | ^^^^^^^^^^^ help: try: `-1.0_f32` error: casting to the same type is unnecessary (`i32` -> `i32`) - --> $DIR/unnecessary_cast.rs:130:18 + --> $DIR/unnecessary_cast.rs:143:18 | LL | let _ = &(x as i32); | ^^^^^^^^^^ help: try: `{ x }` error: casting integer literal to `i32` is unnecessary - --> $DIR/unnecessary_cast.rs:136:22 + --> $DIR/unnecessary_cast.rs:149:22 | LL | let _: i32 = -(1) as i32; | ^^^^^^^^^^^ help: try: `-1_i32` error: casting integer literal to `i64` is unnecessary - --> $DIR/unnecessary_cast.rs:138:22 + --> $DIR/unnecessary_cast.rs:151:22 | LL | let _: i64 = -(1) as i64; | ^^^^^^^^^^^ help: try: `-1_i64` error: casting float literal to `f64` is unnecessary - --> $DIR/unnecessary_cast.rs:145:22 + --> $DIR/unnecessary_cast.rs:158:22 | LL | let _: f64 = (-8.0 as f64).exp(); | ^^^^^^^^^^^^^ help: try: `(-8.0_f64)` error: casting float literal to `f64` is unnecessary - --> $DIR/unnecessary_cast.rs:147:23 + --> $DIR/unnecessary_cast.rs:160:23 | LL | let _: f64 = -(8.0 as f64).exp(); // should suggest `-8.0_f64.exp()` here not to change code behavior | ^^^^^^^^^^^^ help: try: `8.0_f64` error: casting to the same type is unnecessary (`f32` -> `f32`) - --> $DIR/unnecessary_cast.rs:155:20 + --> $DIR/unnecessary_cast.rs:168:20 | LL | let _num = foo() as f32; | ^^^^^^^^^^^^ help: try: `foo()` From dd084940de3947b7d095fcbd6d3381f98470c58b Mon Sep 17 00:00:00 2001 From: y21 <30553356+y21@users.noreply.github.com> Date: Fri, 9 Jun 2023 04:13:00 +0200 Subject: [PATCH 110/310] check that the adjusted receiver type matches target --- .../src/methods/unnecessary_to_owned.rs | 5 +++ tests/ui/unnecessary_to_owned.fixed | 33 +++++++++++++++++++ tests/ui/unnecessary_to_owned.rs | 33 +++++++++++++++++++ 3 files changed, 71 insertions(+) diff --git a/clippy_lints/src/methods/unnecessary_to_owned.rs b/clippy_lints/src/methods/unnecessary_to_owned.rs index 309d2157b76..da7196ed0a8 100644 --- a/clippy_lints/src/methods/unnecessary_to_owned.rs +++ b/clippy_lints/src/methods/unnecessary_to_owned.rs @@ -144,6 +144,11 @@ fn check_addr_of_expr( if let Some(deref_trait_id) = cx.tcx.get_diagnostic_item(sym::Deref); if implements_trait(cx, receiver_ty, deref_trait_id, &[]); if cx.get_associated_type(receiver_ty, deref_trait_id, "Target") == Some(target_ty); + // Make sure that it's actually calling the right `.to_string()`, (#10033) + // *or* this is a `Cow::into_owned()` call (which would be the wrong into_owned receiver (str != Cow) + // but that's ok for Cow::into_owned specifically) + if cx.typeck_results().expr_ty_adjusted(receiver).peel_refs() == target_ty + || is_cow_into_owned(cx, method_name, method_def_id); then { if n_receiver_refs > 0 { span_lint_and_sugg( diff --git a/tests/ui/unnecessary_to_owned.fixed b/tests/ui/unnecessary_to_owned.fixed index 08733906b0e..592a53f3a81 100644 --- a/tests/ui/unnecessary_to_owned.fixed +++ b/tests/ui/unnecessary_to_owned.fixed @@ -474,3 +474,36 @@ mod issue_10021 { Ok(()) } } + +mod issue_10033 { + #![allow(dead_code)] + use std::{fmt::Display, ops::Deref}; + + fn _main() { + let f = Foo; + + // Not actually unnecessary - this calls `Foo`'s `Display` impl, not `str`'s (even though `Foo` does + // deref to `str`) + foo(&f.to_string()); + } + + fn foo(s: &str) { + println!("{}", s); + } + + struct Foo; + + impl Deref for Foo { + type Target = str; + + fn deref(&self) -> &Self::Target { + "str" + } + } + + impl Display for Foo { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "Foo") + } + } +} diff --git a/tests/ui/unnecessary_to_owned.rs b/tests/ui/unnecessary_to_owned.rs index e3589ea0d65..f2e48b1c4a6 100644 --- a/tests/ui/unnecessary_to_owned.rs +++ b/tests/ui/unnecessary_to_owned.rs @@ -474,3 +474,36 @@ mod issue_10021 { Ok(()) } } + +mod issue_10033 { + #![allow(dead_code)] + use std::{fmt::Display, ops::Deref}; + + fn _main() { + let f = Foo; + + // Not actually unnecessary - this calls `Foo`'s `Display` impl, not `str`'s (even though `Foo` does + // deref to `str`) + foo(&f.to_string()); + } + + fn foo(s: &str) { + println!("{}", s); + } + + struct Foo; + + impl Deref for Foo { + type Target = str; + + fn deref(&self) -> &Self::Target { + "str" + } + } + + impl Display for Foo { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "Foo") + } + } +} From 85002b09a1858ea8a7e692f969c3c5946febc898 Mon Sep 17 00:00:00 2001 From: y21 <30553356+y21@users.noreply.github.com> Date: Fri, 9 Jun 2023 04:57:07 +0200 Subject: [PATCH 111/310] handle exponent without digits --- clippy_utils/src/numeric_literal.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clippy_utils/src/numeric_literal.rs b/clippy_utils/src/numeric_literal.rs index c225398ad2a..bbe4149fe2a 100644 --- a/clippy_utils/src/numeric_literal.rs +++ b/clippy_utils/src/numeric_literal.rs @@ -161,7 +161,7 @@ impl<'a> NumericLiteral<'a> { } if let Some((separator, exponent)) = self.exponent { - if exponent != "0" { + if !exponent.is_empty() && exponent != "0" { output.push_str(separator); Self::group_digits(&mut output, exponent, group_size, true, false); } From bbb9204008297fc326fcf4dfbc07cee12f173081 Mon Sep 17 00:00:00 2001 From: y21 <30553356+y21@users.noreply.github.com> Date: Fri, 9 Jun 2023 15:49:35 +0200 Subject: [PATCH 112/310] add test --- rustfmt.toml | 1 + tests/ui/crashes/ice-10912.rs | 4 ++++ tests/ui/crashes/ice-10912.stderr | 16 ++++++++++++++++ 3 files changed, 21 insertions(+) create mode 100644 tests/ui/crashes/ice-10912.rs create mode 100644 tests/ui/crashes/ice-10912.stderr diff --git a/rustfmt.toml b/rustfmt.toml index 10d39762043..18b2a33469d 100644 --- a/rustfmt.toml +++ b/rustfmt.toml @@ -5,3 +5,4 @@ wrap_comments = true edition = "2021" error_on_line_overflow = true version = "Two" +ignore = ["tests/ui/crashes/ice-10912.rs"] diff --git a/tests/ui/crashes/ice-10912.rs b/tests/ui/crashes/ice-10912.rs new file mode 100644 index 00000000000..69d7f2f395f --- /dev/null +++ b/tests/ui/crashes/ice-10912.rs @@ -0,0 +1,4 @@ +#![warn(clippy::unreadable_literal)] +fn f2() -> impl Sized { && 3.14159265358979323846E } + +fn main() {} diff --git a/tests/ui/crashes/ice-10912.stderr b/tests/ui/crashes/ice-10912.stderr new file mode 100644 index 00000000000..a74ce731577 --- /dev/null +++ b/tests/ui/crashes/ice-10912.stderr @@ -0,0 +1,16 @@ +error: expected at least one digit in exponent + --> $DIR/ice-10912.rs:2:28 + | +LL | fn f2() -> impl Sized { && 3.14159265358979323846E } + | ^^^^^^^^^^^^^^^^^^^^^^^ + +error: long literal lacking separators + --> $DIR/ice-10912.rs:2:28 + | +LL | fn f2() -> impl Sized { && 3.14159265358979323846E } + | ^^^^^^^^^^^^^^^^^^^^^^^ help: consider: `3.141_592_653_589_793_238_46` + | + = note: `-D clippy::unreadable-literal` implied by `-D warnings` + +error: aborting due to 2 previous errors + From 0c545c7bccdb45055f8874fa2700afb1ecb69f1d Mon Sep 17 00:00:00 2001 From: Centri3 <114838443+Centri3@users.noreply.github.com> Date: Thu, 18 May 2023 22:13:44 -0500 Subject: [PATCH 113/310] also lint single expression blocks Update mixed_read_write_in_expression.rs Update diverging_sub_expression.stderr --- .../src/mixed_read_write_in_expression.rs | 8 +- tests/ui/diverging_sub_expression.rs | 9 ++ tests/ui/diverging_sub_expression.stderr | 84 +++++++++++++++++++ 3 files changed, 100 insertions(+), 1 deletion(-) diff --git a/clippy_lints/src/mixed_read_write_in_expression.rs b/clippy_lints/src/mixed_read_write_in_expression.rs index 942453498cd..caa3463b864 100644 --- a/clippy_lints/src/mixed_read_write_in_expression.rs +++ b/clippy_lints/src/mixed_read_write_in_expression.rs @@ -139,7 +139,13 @@ impl<'a, 'tcx> Visitor<'tcx> for DivergenceVisitor<'a, 'tcx> { match e.kind { // fix #10776 ExprKind::Block(block, ..) => { - if let Some(stmt) = block.stmts.first() && block.stmts.len() == 1 { + if let Some(e) = block.expr { + self.visit_expr(e); + + return; + } + + if let [stmt] = block.stmts && block.stmts.len() == 1 { match stmt.kind { StmtKind::Expr(e) | StmtKind::Semi(e) => self.visit_expr(e), _ => {}, diff --git a/tests/ui/diverging_sub_expression.rs b/tests/ui/diverging_sub_expression.rs index 510eca21f71..3a4d66c5ba5 100644 --- a/tests/ui/diverging_sub_expression.rs +++ b/tests/ui/diverging_sub_expression.rs @@ -40,6 +40,15 @@ fn foobar() { // lint blocks as well 15 => true || { return; }, 16 => false || { return; }, + // ... and when it's a single expression + 17 => true || { return }, + 18 => false || { return }, + // ... but not when there's both an expression and a statement + 19 => true || { _ = 1; return }, + 20 => false || { _ = 1; return }, + // ... or multiple statements + 21 => true || { _ = 1; return; }, + 22 => false || { _ = 1; return; }, _ => true || break, }; } diff --git a/tests/ui/diverging_sub_expression.stderr b/tests/ui/diverging_sub_expression.stderr index e69de29bb2d..e6396de2bb7 100644 --- a/tests/ui/diverging_sub_expression.stderr +++ b/tests/ui/diverging_sub_expression.stderr @@ -0,0 +1,84 @@ +error: sub-expression diverges + --> $DIR/diverging_sub_expression.rs:20:10 + | +LL | b || diverge(); + | ^^^^^^^^^ + | + = note: `-D clippy::diverging-sub-expression` implied by `-D warnings` + +error: sub-expression diverges + --> $DIR/diverging_sub_expression.rs:21:10 + | +LL | b || A.foo(); + | ^^^^^^^ + +error: sub-expression diverges + --> $DIR/diverging_sub_expression.rs:31:26 + | +LL | 6 => true || return, + | ^^^^^^ + +error: sub-expression diverges + --> $DIR/diverging_sub_expression.rs:32:26 + | +LL | 7 => true || continue, + | ^^^^^^^^ + +error: sub-expression diverges + --> $DIR/diverging_sub_expression.rs:35:26 + | +LL | 3 => true || diverge(), + | ^^^^^^^^^ + +error: sub-expression diverges + --> $DIR/diverging_sub_expression.rs:38:30 + | +LL | _ => true || panic!("boo"), + | ^^^^^^^^^^^^^ + | + = note: this error originates in the macro `$crate::panic::panic_2021` which comes from the expansion of the macro `panic` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: sub-expression diverges + --> $DIR/diverging_sub_expression.rs:41:29 + | +LL | 15 => true || { return; }, + | ^^^^^^ + +error: sub-expression diverges + --> $DIR/diverging_sub_expression.rs:42:30 + | +LL | 16 => false || { return; }, + | ^^^^^^ + +error: sub-expression diverges + --> $DIR/diverging_sub_expression.rs:44:29 + | +LL | 17 => true || { return }, + | ^^^^^^ + +error: sub-expression diverges + --> $DIR/diverging_sub_expression.rs:45:30 + | +LL | 18 => false || { return }, + | ^^^^^^ + +error: sub-expression diverges + --> $DIR/diverging_sub_expression.rs:47:36 + | +LL | 19 => true || { _ = 1; return }, + | ^^^^^^ + +error: sub-expression diverges + --> $DIR/diverging_sub_expression.rs:48:37 + | +LL | 20 => false || { _ = 1; return }, + | ^^^^^^ + +error: sub-expression diverges + --> $DIR/diverging_sub_expression.rs:52:26 + | +LL | _ => true || break, + | ^^^^^ + +error: aborting due to 13 previous errors + From c1c134a28828c21230bb54ca4c70d027725aa175 Mon Sep 17 00:00:00 2001 From: Centri3 <114838443+Centri3@users.noreply.github.com> Date: Fri, 9 Jun 2023 11:43:58 -0500 Subject: [PATCH 114/310] ensure there are no stmts for expr check --- clippy_lints/src/mixed_read_write_in_expression.rs | 4 ++-- tests/ui/diverging_sub_expression.stderr | 14 +------------- 2 files changed, 3 insertions(+), 15 deletions(-) diff --git a/clippy_lints/src/mixed_read_write_in_expression.rs b/clippy_lints/src/mixed_read_write_in_expression.rs index caa3463b864..ac94820b40b 100644 --- a/clippy_lints/src/mixed_read_write_in_expression.rs +++ b/clippy_lints/src/mixed_read_write_in_expression.rs @@ -139,13 +139,13 @@ impl<'a, 'tcx> Visitor<'tcx> for DivergenceVisitor<'a, 'tcx> { match e.kind { // fix #10776 ExprKind::Block(block, ..) => { - if let Some(e) = block.expr { + if let Some(e) = block.expr && block.stmts.is_empty() { self.visit_expr(e); return; } - if let [stmt] = block.stmts && block.stmts.len() == 1 { + if let [stmt, rest @ ..] = block.stmts && rest.is_empty() { match stmt.kind { StmtKind::Expr(e) | StmtKind::Semi(e) => self.visit_expr(e), _ => {}, diff --git a/tests/ui/diverging_sub_expression.stderr b/tests/ui/diverging_sub_expression.stderr index e6396de2bb7..f121159ca3e 100644 --- a/tests/ui/diverging_sub_expression.stderr +++ b/tests/ui/diverging_sub_expression.stderr @@ -62,23 +62,11 @@ error: sub-expression diverges LL | 18 => false || { return }, | ^^^^^^ -error: sub-expression diverges - --> $DIR/diverging_sub_expression.rs:47:36 - | -LL | 19 => true || { _ = 1; return }, - | ^^^^^^ - -error: sub-expression diverges - --> $DIR/diverging_sub_expression.rs:48:37 - | -LL | 20 => false || { _ = 1; return }, - | ^^^^^^ - error: sub-expression diverges --> $DIR/diverging_sub_expression.rs:52:26 | LL | _ => true || break, | ^^^^^ -error: aborting due to 13 previous errors +error: aborting due to 11 previous errors From 35aff1ae8608beb9637eed518bc4f2f57186df42 Mon Sep 17 00:00:00 2001 From: Centri3 <114838443+Centri3@users.noreply.github.com> Date: Fri, 9 Jun 2023 15:32:42 -0500 Subject: [PATCH 115/310] refactor --- .../src/mixed_read_write_in_expression.rs | 20 +++++++------------ tests/ui/diverging_sub_expression.rs | 2 ++ tests/ui/diverging_sub_expression.stderr | 2 +- 3 files changed, 10 insertions(+), 14 deletions(-) diff --git a/clippy_lints/src/mixed_read_write_in_expression.rs b/clippy_lints/src/mixed_read_write_in_expression.rs index ac94820b40b..57ec3a1f1e6 100644 --- a/clippy_lints/src/mixed_read_write_in_expression.rs +++ b/clippy_lints/src/mixed_read_write_in_expression.rs @@ -138,19 +138,13 @@ impl<'a, 'tcx> Visitor<'tcx> for DivergenceVisitor<'a, 'tcx> { fn visit_expr(&mut self, e: &'tcx Expr<'_>) { match e.kind { // fix #10776 - ExprKind::Block(block, ..) => { - if let Some(e) = block.expr && block.stmts.is_empty() { - self.visit_expr(e); - - return; - } - - if let [stmt, rest @ ..] = block.stmts && rest.is_empty() { - match stmt.kind { - StmtKind::Expr(e) | StmtKind::Semi(e) => self.visit_expr(e), - _ => {}, - } - } + ExprKind::Block(block, ..) => match (block.stmts, block.expr) { + ([], Some(e)) => self.visit_expr(e), + ([stmt], None) => match stmt.kind { + StmtKind::Expr(e) | StmtKind::Semi(e) => self.visit_expr(e), + _ => {}, + }, + _ => {}, }, ExprKind::Continue(_) | ExprKind::Break(_, _) | ExprKind::Ret(_) => self.report_diverging_sub_expr(e), ExprKind::Call(func, _) => { diff --git a/tests/ui/diverging_sub_expression.rs b/tests/ui/diverging_sub_expression.rs index 3a4d66c5ba5..9b1619baf0e 100644 --- a/tests/ui/diverging_sub_expression.rs +++ b/tests/ui/diverging_sub_expression.rs @@ -49,6 +49,8 @@ fn foobar() { // ... or multiple statements 21 => true || { _ = 1; return; }, 22 => false || { _ = 1; return; }, + 23 => true || { return; true }, + 24 => true || { return; true }, _ => true || break, }; } diff --git a/tests/ui/diverging_sub_expression.stderr b/tests/ui/diverging_sub_expression.stderr index f121159ca3e..243a5cf5369 100644 --- a/tests/ui/diverging_sub_expression.stderr +++ b/tests/ui/diverging_sub_expression.stderr @@ -63,7 +63,7 @@ LL | 18 => false || { return }, | ^^^^^^ error: sub-expression diverges - --> $DIR/diverging_sub_expression.rs:52:26 + --> $DIR/diverging_sub_expression.rs:54:26 | LL | _ => true || break, | ^^^^^ From b7fedb88cffd4156a9a36e22912234fe908ad776 Mon Sep 17 00:00:00 2001 From: Catherine <114838443+Centri3@users.noreply.github.com> Date: Fri, 9 Jun 2023 16:28:01 -0500 Subject: [PATCH 116/310] Update excessive_nesting.rs --- clippy_lints/src/excessive_nesting.rs | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/clippy_lints/src/excessive_nesting.rs b/clippy_lints/src/excessive_nesting.rs index 1c6cd27789d..4c8ea1ed18d 100644 --- a/clippy_lints/src/excessive_nesting.rs +++ b/clippy_lints/src/excessive_nesting.rs @@ -24,8 +24,8 @@ declare_clippy_lint! { /// # clippy.toml /// excessive-nesting-threshold = 3 /// ``` - /// lib.rs: /// ```rust,ignore + /// // lib.rs /// pub mod a { /// pub struct X; /// impl X { @@ -36,9 +36,10 @@ declare_clippy_lint! { /// } /// } /// } + /// ``` /// Use instead: - /// a.rs: /// ```rust,ignore + /// // a.rs /// fn private_run(x: &X) { /// if true { /// // etc... @@ -52,8 +53,8 @@ declare_clippy_lint! { /// } /// } /// ``` - /// lib.rs: /// ```rust,ignore + /// lib// .rs /// pub mod a; /// ``` #[clippy::version = "1.70.0"] From d1957b87c8e6345c1908f19a7be8efc266aa3ad5 Mon Sep 17 00:00:00 2001 From: Catherine <114838443+Centri3@users.noreply.github.com> Date: Fri, 9 Jun 2023 16:29:34 -0500 Subject: [PATCH 117/310] Update excessive_nesting.rs --- clippy_lints/src/excessive_nesting.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clippy_lints/src/excessive_nesting.rs b/clippy_lints/src/excessive_nesting.rs index 4c8ea1ed18d..d04d833e630 100644 --- a/clippy_lints/src/excessive_nesting.rs +++ b/clippy_lints/src/excessive_nesting.rs @@ -54,7 +54,7 @@ declare_clippy_lint! { /// } /// ``` /// ```rust,ignore - /// lib// .rs + /// // lib.rs /// pub mod a; /// ``` #[clippy::version = "1.70.0"] From b6fa4d43d3d800224f724baa322f301bf09a5031 Mon Sep 17 00:00:00 2001 From: Jason Newcomb Date: Sun, 26 Feb 2023 23:16:27 -0500 Subject: [PATCH 118/310] Extend `explicit_iter_loop` to all types --- clippy_lints/src/lib.rs | 2 +- clippy_lints/src/loops/explicit_iter_loop.rs | 200 +++++++++++++++---- clippy_lints/src/loops/mod.rs | 90 +++++---- clippy_utils/src/msrvs.rs | 2 +- clippy_utils/src/ty.rs | 48 +++++ tests/ui/for_loop_fixable.fixed | 91 ++++++++- tests/ui/for_loop_fixable.rs | 85 +++++++- tests/ui/for_loop_fixable.stderr | 28 ++- 8 files changed, 460 insertions(+), 86 deletions(-) diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index 22ff5ef5859..30842cd6510 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -679,7 +679,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: }); store.register_late_pass(|_| Box::::default()); store.register_late_pass(|_| Box::new(unit_types::UnitTypes)); - store.register_late_pass(|_| Box::new(loops::Loops)); + store.register_late_pass(move |_| Box::new(loops::Loops::new(msrv()))); store.register_late_pass(|_| Box::::default()); store.register_late_pass(|_| Box::new(lifetimes::Lifetimes)); store.register_late_pass(|_| Box::new(entry::HashMapPass)); diff --git a/clippy_lints/src/loops/explicit_iter_loop.rs b/clippy_lints/src/loops/explicit_iter_loop.rs index 151c7f1d5d2..ba66af62375 100644 --- a/clippy_lints/src/loops/explicit_iter_loop.rs +++ b/clippy_lints/src/loops/explicit_iter_loop.rs @@ -1,18 +1,37 @@ use super::EXPLICIT_ITER_LOOP; use clippy_utils::diagnostics::span_lint_and_sugg; use clippy_utils::is_trait_method; +use clippy_utils::msrvs::{self, Msrv}; use clippy_utils::source::snippet_with_applicability; -use clippy_utils::ty::is_type_diagnostic_item; +use clippy_utils::ty::{implements_trait_with_env, make_normalized_projection_with_regions, normalize_with_regions, + make_normalized_projection, implements_trait, is_copy}; use rustc_errors::Applicability; use rustc_hir::{Expr, Mutability}; use rustc_lint::LateContext; -use rustc_middle::ty::{self, Ty}; +use rustc_middle::ty::adjustment::{Adjust, Adjustment, AutoBorrow, AutoBorrowMutability}; +use rustc_middle::ty::{self, EarlyBinder, TypeAndMut, Ty}; use rustc_span::sym; -pub(super) fn check(cx: &LateContext<'_>, self_arg: &Expr<'_>, arg: &Expr<'_>, method_name: &str) { - let should_lint = match method_name { - "iter" | "iter_mut" => is_ref_iterable_type(cx, self_arg), - "into_iter" if is_trait_method(cx, arg, sym::IntoIterator) => { +pub(super) fn check(cx: &LateContext<'_>, self_arg: &Expr<'_>, call_expr: &Expr<'_>, method_name: &str, msrv: &Msrv) { + let borrow_kind = match method_name { + "iter" | "iter_mut" => match is_ref_iterable(cx, self_arg, call_expr) { + Some((kind, ty)) => { + if let ty::Array(_, count) = *ty.peel_refs().kind() { + if !ty.is_ref() { + if !msrv.meets(msrvs::ARRAY_INTO_ITERATOR) { + return; + } + } else if count.try_eval_target_usize(cx.tcx, cx.param_env).map_or(true, |x| x > 32) + && !msrv.meets(msrvs::ARRAY_IMPL_ANY_LEN) + { + return + } + } + kind + }, + None => return, + }, + "into_iter" if is_trait_method(cx, call_expr, sym::IntoIterator) => { let receiver_ty = cx.typeck_results().expr_ty(self_arg); let receiver_ty_adjusted = cx.typeck_results().expr_ty_adjusted(self_arg); let ref_receiver_ty = cx.tcx.mk_ref( @@ -22,54 +41,159 @@ pub(super) fn check(cx: &LateContext<'_>, self_arg: &Expr<'_>, arg: &Expr<'_>, m mutbl: Mutability::Not, }, ); - receiver_ty_adjusted == ref_receiver_ty + if receiver_ty_adjusted == ref_receiver_ty { + AdjustKind::None + } else { + return; + } }, - _ => false, + _ => return, }; - if !should_lint { - return; - } - let mut applicability = Applicability::MachineApplicable; let object = snippet_with_applicability(cx, self_arg.span, "_", &mut applicability); - let muta = if method_name == "iter_mut" { "mut " } else { "" }; + let prefix = match borrow_kind { + AdjustKind::None => "", + AdjustKind::Borrow => "&", + AdjustKind::BorrowMut => "&mut ", + AdjustKind::Deref => "*", + AdjustKind::Reborrow => "&*", + AdjustKind::ReborrowMut => "&mut *", + }; span_lint_and_sugg( cx, EXPLICIT_ITER_LOOP, - arg.span, + call_expr.span, "it is more concise to loop over references to containers instead of using explicit \ iteration methods", "to write this more concisely, try", - format!("&{muta}{object}"), + format!("{prefix}{object}"), applicability, ); } -/// Returns `true` if the type of expr is one that provides `IntoIterator` impls -/// for `&T` and `&mut T`, such as `Vec`. -#[rustfmt::skip] -fn is_ref_iterable_type(cx: &LateContext<'_>, e: &Expr<'_>) -> bool { - // no walk_ptrs_ty: calling iter() on a reference can make sense because it - // will allow further borrows afterwards - let ty = cx.typeck_results().expr_ty(e); - is_iterable_array(ty, cx) || - is_type_diagnostic_item(cx, ty, sym::Vec) || - is_type_diagnostic_item(cx, ty, sym::LinkedList) || - is_type_diagnostic_item(cx, ty, sym::HashMap) || - is_type_diagnostic_item(cx, ty, sym::HashSet) || - is_type_diagnostic_item(cx, ty, sym::VecDeque) || - is_type_diagnostic_item(cx, ty, sym::BinaryHeap) || - is_type_diagnostic_item(cx, ty, sym::BTreeMap) || - is_type_diagnostic_item(cx, ty, sym::BTreeSet) +enum AdjustKind { + None, + Borrow, + BorrowMut, + Deref, + Reborrow, + ReborrowMut, } +impl AdjustKind { + fn borrow(mutbl: Mutability) -> Self { + match mutbl { + Mutability::Not => Self::Borrow, + Mutability::Mut => Self::BorrowMut, + } + } -fn is_iterable_array<'tcx>(ty: Ty<'tcx>, cx: &LateContext<'tcx>) -> bool { - // IntoIterator is currently only implemented for array sizes <= 32 in rustc - match ty.kind() { - ty::Array(_, n) => n - .try_eval_target_usize(cx.tcx, cx.param_env) - .map_or(false, |val| (0..=32).contains(&val)), - _ => false, + fn auto_borrow(mutbl: AutoBorrowMutability) -> Self { + match mutbl { + AutoBorrowMutability::Not => Self::Borrow, + AutoBorrowMutability::Mut { .. } => Self::BorrowMut, + } + } + + fn reborrow(mutbl: AutoBorrowMutability) -> Self { + match mutbl { + AutoBorrowMutability::Not => Self::Reborrow, + AutoBorrowMutability::Mut { .. } => Self::ReborrowMut, + } + } +} + +/// Checks if an `iter` or `iter_mut` call returns `IntoIterator::IntoIter`. Returns how the +/// argument needs to be adjusted. +fn is_ref_iterable<'tcx>(cx: &LateContext<'tcx>, self_arg: &Expr<'_>, call_expr: &Expr<'_>) -> Option<(AdjustKind, Ty<'tcx>)> { + let typeck = cx.typeck_results(); + if let Some(trait_id) = cx.tcx.get_diagnostic_item(sym::IntoIterator) + && let Some(fn_id) = typeck.type_dependent_def_id(call_expr.hir_id) + && let sig = cx.tcx.liberate_late_bound_regions(fn_id, cx.tcx.fn_sig(fn_id).skip_binder()) + && let &[req_self_ty, req_res_ty] = &**sig.inputs_and_output + && let param_env = cx.tcx.param_env(fn_id) + && implements_trait_with_env(cx.tcx, param_env, req_self_ty, trait_id, []) + && let Some(into_iter_ty) = + make_normalized_projection_with_regions(cx.tcx, param_env, trait_id, sym!(IntoIter), [req_self_ty]) + && let req_res_ty = normalize_with_regions(cx.tcx, param_env, req_res_ty) + && into_iter_ty == req_res_ty + { + let adjustments = typeck.expr_adjustments(self_arg); + let self_ty = typeck.expr_ty(self_arg); + let self_is_copy = is_copy(cx, self_ty); + + if adjustments.is_empty() && self_is_copy { + return Some((AdjustKind::None, self_ty)); + } + + let res_ty = cx.tcx.erase_regions(EarlyBinder::bind(req_res_ty).subst(cx.tcx, typeck.node_substs(call_expr.hir_id))); + if !adjustments.is_empty() && self_is_copy { + if implements_trait(cx, self_ty, trait_id, &[]) + && let Some(ty) = make_normalized_projection(cx.tcx, cx.param_env, trait_id, sym!(IntoIter), [self_ty]) + && ty == res_ty + { + return Some((AdjustKind::None, self_ty)); + } + } + + let mutbl = if let ty::Ref(_, _, mutbl) = *req_self_ty.kind() { + Some(mutbl) + } else { + None + }; + if let Some(mutbl) = mutbl + && !self_ty.is_ref() + { + let self_ty = cx.tcx.mk_ref(cx.tcx.lifetimes.re_erased, TypeAndMut { + ty: self_ty, + mutbl, + }); + if implements_trait(cx, self_ty, trait_id, &[]) + && let Some(ty) = make_normalized_projection(cx.tcx, cx.param_env, trait_id, sym!(IntoIter), [self_ty]) + && ty == res_ty + { + return Some((AdjustKind::borrow(mutbl), self_ty)); + } + } + + match adjustments { + [] => Some((AdjustKind::None, self_ty)), + &[Adjustment { kind: Adjust::Deref(_), ..}, Adjustment { kind: Adjust::Borrow(AutoBorrow::Ref(_, mutbl)), target }, ..] => { + if target != self_ty + && implements_trait(cx, target, trait_id, &[]) + && let Some(ty) = make_normalized_projection(cx.tcx, cx.param_env, trait_id, sym!(IntoIter), [target]) + && ty == res_ty + { + Some((AdjustKind::reborrow(mutbl), target)) + } else { + None + } + } + &[Adjustment { kind: Adjust::Deref(_), target }, ..] => { + if is_copy(cx, target) + && implements_trait(cx, target, trait_id, &[]) + && let Some(ty) = make_normalized_projection(cx.tcx, cx.param_env, trait_id, sym!(IntoIter), [target]) + && ty == res_ty + { + Some((AdjustKind::Deref, target)) + } else { + None + } + } + &[Adjustment { kind: Adjust::Borrow(AutoBorrow::Ref(_, mutbl)), target }, ..] => { + if self_ty.is_ref() + && implements_trait(cx, target, trait_id, &[]) + && let Some(ty) = make_normalized_projection(cx.tcx, cx.param_env, trait_id, sym!(IntoIter), [target]) + && ty == res_ty + { + Some((AdjustKind::auto_borrow(mutbl), target)) + } else { + None + } + } + _ => None, + } + } else { + None } } diff --git a/clippy_lints/src/loops/mod.rs b/clippy_lints/src/loops/mod.rs index c7c11809752..068166bdeb2 100644 --- a/clippy_lints/src/loops/mod.rs +++ b/clippy_lints/src/loops/mod.rs @@ -20,9 +20,10 @@ mod while_let_loop; mod while_let_on_iterator; use clippy_utils::higher; +use clippy_utils::msrvs::Msrv; use rustc_hir::{Expr, ExprKind, LoopSource, Pat}; use rustc_lint::{LateContext, LateLintPass}; -use rustc_session::{declare_lint_pass, declare_tool_lint}; +use rustc_session::{declare_tool_lint, impl_lint_pass}; use rustc_span::source_map::Span; use utils::{make_iterator_snippet, IncrementVisitor, InitializeVisitor}; @@ -606,7 +607,15 @@ declare_clippy_lint! { "checking for emptiness of a `Vec` in the loop condition and popping an element in the body" } -declare_lint_pass!(Loops => [ +pub struct Loops { + msrv: Msrv, +} +impl Loops { + pub fn new(msrv: Msrv) -> Self { + Self { msrv } + } +} +impl_lint_pass!(Loops => [ MANUAL_MEMCPY, MANUAL_FLATTEN, NEEDLESS_RANGE_LOOP, @@ -645,7 +654,7 @@ impl<'tcx> LateLintPass<'tcx> for Loops { if body.span.from_expansion() { return; } - check_for_loop(cx, pat, arg, body, expr, span); + self.check_for_loop(cx, pat, arg, body, expr, span); if let ExprKind::Block(block, _) = body.kind { never_loop::check(cx, block, loop_id, span, for_loop.as_ref()); } @@ -680,44 +689,47 @@ impl<'tcx> LateLintPass<'tcx> for Loops { } } -fn check_for_loop<'tcx>( - cx: &LateContext<'tcx>, - pat: &'tcx Pat<'_>, - arg: &'tcx Expr<'_>, - body: &'tcx Expr<'_>, - expr: &'tcx Expr<'_>, - span: Span, -) { - let is_manual_memcpy_triggered = manual_memcpy::check(cx, pat, arg, body, expr); - if !is_manual_memcpy_triggered { - needless_range_loop::check(cx, pat, arg, body, expr); - explicit_counter_loop::check(cx, pat, arg, body, expr); +impl Loops { + fn check_for_loop<'tcx>( + &self, + cx: &LateContext<'tcx>, + pat: &'tcx Pat<'_>, + arg: &'tcx Expr<'_>, + body: &'tcx Expr<'_>, + expr: &'tcx Expr<'_>, + span: Span, + ) { + let is_manual_memcpy_triggered = manual_memcpy::check(cx, pat, arg, body, expr); + if !is_manual_memcpy_triggered { + needless_range_loop::check(cx, pat, arg, body, expr); + explicit_counter_loop::check(cx, pat, arg, body, expr); + } + self.check_for_loop_arg(cx, pat, arg); + for_kv_map::check(cx, pat, arg, body); + mut_range_bound::check(cx, arg, body); + single_element_loop::check(cx, pat, arg, body, expr); + same_item_push::check(cx, pat, arg, body, expr); + manual_flatten::check(cx, pat, arg, body, span); + manual_find::check(cx, pat, arg, body, span, expr); } - check_for_loop_arg(cx, pat, arg); - for_kv_map::check(cx, pat, arg, body); - mut_range_bound::check(cx, arg, body); - single_element_loop::check(cx, pat, arg, body, expr); - same_item_push::check(cx, pat, arg, body, expr); - manual_flatten::check(cx, pat, arg, body, span); - manual_find::check(cx, pat, arg, body, span, expr); -} -fn check_for_loop_arg(cx: &LateContext<'_>, _: &Pat<'_>, arg: &Expr<'_>) { - if let ExprKind::MethodCall(method, self_arg, [], _) = arg.kind { - let method_name = method.ident.as_str(); - // check for looping over x.iter() or x.iter_mut(), could use &x or &mut x - match method_name { - "iter" | "iter_mut" => { - explicit_iter_loop::check(cx, self_arg, arg, method_name); - }, - "into_iter" => { - explicit_iter_loop::check(cx, self_arg, arg, method_name); - explicit_into_iter_loop::check(cx, self_arg, arg); - }, - "next" => { - iter_next_loop::check(cx, arg); - }, - _ => {}, + fn check_for_loop_arg(&self, cx: &LateContext<'_>, _: &Pat<'_>, arg: &Expr<'_>) { + if let ExprKind::MethodCall(method, self_arg, [], _) = arg.kind { + let method_name = method.ident.as_str(); + // check for looping over x.iter() or x.iter_mut(), could use &x or &mut x + match method_name { + "iter" | "iter_mut" => { + explicit_iter_loop::check(cx, self_arg, arg, method_name, &self.msrv); + }, + "into_iter" => { + explicit_iter_loop::check(cx, self_arg, arg, method_name, &self.msrv); + explicit_into_iter_loop::check(cx, self_arg, arg); + }, + "next" => { + iter_next_loop::check(cx, arg); + }, + _ => {}, + } } } } diff --git a/clippy_utils/src/msrvs.rs b/clippy_utils/src/msrvs.rs index 6f102308f0b..e1b1a6f7184 100644 --- a/clippy_utils/src/msrvs.rs +++ b/clippy_utils/src/msrvs.rs @@ -28,7 +28,7 @@ msrv_aliases! { 1,52,0 { STR_SPLIT_ONCE, REM_EUCLID_CONST } 1,51,0 { BORROW_AS_PTR, SEEK_FROM_CURRENT, UNSIGNED_ABS } 1,50,0 { BOOL_THEN, CLAMP } - 1,47,0 { TAU, IS_ASCII_DIGIT_CONST } + 1,47,0 { TAU, IS_ASCII_DIGIT_CONST, ARRAY_IMPL_ANY_LEN } 1,46,0 { CONST_IF_MATCH } 1,45,0 { STR_STRIP_PREFIX } 1,43,0 { LOG2_10, LOG10_2 } diff --git a/clippy_utils/src/ty.rs b/clippy_utils/src/ty.rs index 7b4ed77e8ed..78b14dc7abb 100644 --- a/clippy_utils/src/ty.rs +++ b/clippy_utils/src/ty.rs @@ -1180,3 +1180,51 @@ pub fn is_interior_mut_ty<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>) -> bool { _ => false, } } + +pub fn make_normalized_projection_with_regions<'tcx>( + tcx: TyCtxt<'tcx>, + param_env: ParamEnv<'tcx>, + container_id: DefId, + assoc_ty: Symbol, + substs: impl IntoIterator>>, +) -> Option> { + fn helper<'tcx>(tcx: TyCtxt<'tcx>, param_env: ParamEnv<'tcx>, ty: AliasTy<'tcx>) -> Option> { + #[cfg(debug_assertions)] + if let Some((i, subst)) = ty + .substs + .iter() + .enumerate() + .find(|(_, subst)| subst.has_late_bound_regions()) + { + debug_assert!( + false, + "substs contain late-bound region at index `{i}` which can't be normalized.\n\ + use `TyCtxt::erase_late_bound_regions`\n\ + note: subst is `{subst:#?}`", + ); + return None; + } + let cause = rustc_middle::traits::ObligationCause::dummy(); + match tcx + .infer_ctxt() + .build() + .at(&cause, param_env) + .query_normalize(tcx.mk_projection(ty.def_id, ty.substs)) + { + Ok(ty) => Some(ty.value), + Err(e) => { + debug_assert!(false, "failed to normalize type `{ty}`: {e:#?}"); + None + }, + } + } + helper(tcx, param_env, make_projection(tcx, container_id, assoc_ty, substs)?) +} + +pub fn normalize_with_regions<'tcx>(tcx: TyCtxt<'tcx>, param_env: ParamEnv<'tcx>, ty: Ty<'tcx>) -> Ty<'tcx> { + let cause = rustc_middle::traits::ObligationCause::dummy(); + match tcx.infer_ctxt().build().at(&cause, param_env).query_normalize(ty) { + Ok(ty) => ty.value, + Err(_) => ty, + } +} diff --git a/tests/ui/for_loop_fixable.fixed b/tests/ui/for_loop_fixable.fixed index 3e74e2a02d0..99230856446 100644 --- a/tests/ui/for_loop_fixable.fixed +++ b/tests/ui/for_loop_fixable.fixed @@ -1,6 +1,6 @@ //@run-rustfix #![allow(dead_code, unused)] -#![allow(clippy::uninlined_format_args, clippy::useless_vec)] +#![allow(clippy::uninlined_format_args, clippy::useless_vec, clippy::deref_addrof)] use std::collections::*; @@ -52,11 +52,11 @@ fn main() { for _v in &[1, 2, 3] {} - for _v in (&mut [1, 2, 3]).iter() {} // no error + for _v in &*(&mut [1, 2, 3]) {} // no error for _v in &[0; 32] {} - for _v in [0; 33].iter() {} // no error + for _v in &[0; 33] {} // no error let ll: LinkedList<()> = LinkedList::new(); for _v in &ll {} @@ -272,7 +272,7 @@ mod issue_4958 { let rr = &&t; // This case is handled by `explicit_iter_loop`. No idea why. - for _ in &t {} + for _ in t {} for _ in r {} @@ -307,3 +307,86 @@ mod issue_6900 { } } } + +struct IntoIterDiffTy; +impl IntoIterator for &'_ IntoIterDiffTy { + type Item = &'static (); + type IntoIter = core::slice::Iter<'static, ()>; + fn into_iter(self) -> Self::IntoIter { + unimplemented!() + } +} +impl IntoIterDiffTy { + fn iter(&self) -> core::slice::Iter<'static, i32> { + unimplemented!() + } +} + +struct IntoIterDiffSig; +impl IntoIterator for &'_ IntoIterDiffSig { + type Item = &'static (); + type IntoIter = core::slice::Iter<'static, ()>; + fn into_iter(self) -> Self::IntoIter { + unimplemented!() + } +} +impl IntoIterDiffSig { + fn iter(&self, _: u32) -> core::slice::Iter<'static, ()> { + unimplemented!() + } +} + +struct IntoIterDiffLt<'a>(&'a ()); +impl<'a> IntoIterator for &'a IntoIterDiffLt<'_> { + type Item = &'a (); + type IntoIter = core::slice::Iter<'a, ()>; + fn into_iter(self) -> Self::IntoIter { + unimplemented!() + } +} +impl<'a> IntoIterDiffLt<'a> { + fn iter(&self) -> core::slice::Iter<'a, ()> { + unimplemented!() + } +} + +struct CustomType; +impl<'a> IntoIterator for &'a CustomType { + type Item = &'a u32; + type IntoIter = core::slice::Iter<'a, u32>; + fn into_iter(self) -> Self::IntoIter { + unimplemented!() + } +} +impl<'a> IntoIterator for &'a mut CustomType { + type Item = &'a mut u32; + type IntoIter = core::slice::IterMut<'a, u32>; + fn into_iter(self) -> Self::IntoIter { + unimplemented!() + } +} +impl CustomType { + fn iter(&self) -> <&'_ Self as IntoIterator>::IntoIter { + panic!() + } + + fn iter_mut(&mut self) -> core::slice::IterMut<'_, u32> { + panic!() + } +} + +#[warn(clippy::explicit_iter_loop)] +fn _f() { + let x = IntoIterDiffTy; + for _ in x.iter() {} + + let x = IntoIterDiffSig; + for _ in x.iter(0) {} + + let x = IntoIterDiffLt(&()); + for _ in x.iter() {} + + let mut x = CustomType; + for _ in &x {} + for _ in &mut x {} +} diff --git a/tests/ui/for_loop_fixable.rs b/tests/ui/for_loop_fixable.rs index 45c6760f89e..0d7fe3c0314 100644 --- a/tests/ui/for_loop_fixable.rs +++ b/tests/ui/for_loop_fixable.rs @@ -1,6 +1,6 @@ //@run-rustfix #![allow(dead_code, unused)] -#![allow(clippy::uninlined_format_args, clippy::useless_vec)] +#![allow(clippy::uninlined_format_args, clippy::useless_vec, clippy::deref_addrof)] use std::collections::*; @@ -307,3 +307,86 @@ mod issue_6900 { } } } + +struct IntoIterDiffTy; +impl IntoIterator for &'_ IntoIterDiffTy { + type Item = &'static (); + type IntoIter = core::slice::Iter<'static, ()>; + fn into_iter(self) -> Self::IntoIter { + unimplemented!() + } +} +impl IntoIterDiffTy { + fn iter(&self) -> core::slice::Iter<'static, i32> { + unimplemented!() + } +} + +struct IntoIterDiffSig; +impl IntoIterator for &'_ IntoIterDiffSig { + type Item = &'static (); + type IntoIter = core::slice::Iter<'static, ()>; + fn into_iter(self) -> Self::IntoIter { + unimplemented!() + } +} +impl IntoIterDiffSig { + fn iter(&self, _: u32) -> core::slice::Iter<'static, ()> { + unimplemented!() + } +} + +struct IntoIterDiffLt<'a>(&'a ()); +impl<'a> IntoIterator for &'a IntoIterDiffLt<'_> { + type Item = &'a (); + type IntoIter = core::slice::Iter<'a, ()>; + fn into_iter(self) -> Self::IntoIter { + unimplemented!() + } +} +impl<'a> IntoIterDiffLt<'a> { + fn iter(&self) -> core::slice::Iter<'a, ()> { + unimplemented!() + } +} + +struct CustomType; +impl<'a> IntoIterator for &'a CustomType { + type Item = &'a u32; + type IntoIter = core::slice::Iter<'a, u32>; + fn into_iter(self) -> Self::IntoIter { + unimplemented!() + } +} +impl<'a> IntoIterator for &'a mut CustomType { + type Item = &'a mut u32; + type IntoIter = core::slice::IterMut<'a, u32>; + fn into_iter(self) -> Self::IntoIter { + unimplemented!() + } +} +impl CustomType { + fn iter(&self) -> <&'_ Self as IntoIterator>::IntoIter { + panic!() + } + + fn iter_mut(&mut self) -> core::slice::IterMut<'_, u32> { + panic!() + } +} + +#[warn(clippy::explicit_iter_loop)] +fn _f() { + let x = IntoIterDiffTy; + for _ in x.iter() {} + + let x = IntoIterDiffSig; + for _ in x.iter(0) {} + + let x = IntoIterDiffLt(&()); + for _ in x.iter() {} + + let mut x = CustomType; + for _ in x.iter() {} + for _ in x.iter_mut() {} +} diff --git a/tests/ui/for_loop_fixable.stderr b/tests/ui/for_loop_fixable.stderr index ddfe66d675f..4ad23e0b9db 100644 --- a/tests/ui/for_loop_fixable.stderr +++ b/tests/ui/for_loop_fixable.stderr @@ -26,12 +26,24 @@ error: it is more concise to loop over references to containers instead of using LL | for _v in [1, 2, 3].iter() {} | ^^^^^^^^^^^^^^^^ help: to write this more concisely, try: `&[1, 2, 3]` +error: it is more concise to loop over references to containers instead of using explicit iteration methods + --> $DIR/for_loop_fixable.rs:55:15 + | +LL | for _v in (&mut [1, 2, 3]).iter() {} // no error + | ^^^^^^^^^^^^^^^^^^^^^^^ help: to write this more concisely, try: `&*(&mut [1, 2, 3])` + error: it is more concise to loop over references to containers instead of using explicit iteration methods --> $DIR/for_loop_fixable.rs:57:15 | LL | for _v in [0; 32].iter() {} | ^^^^^^^^^^^^^^ help: to write this more concisely, try: `&[0; 32]` +error: it is more concise to loop over references to containers instead of using explicit iteration methods + --> $DIR/for_loop_fixable.rs:59:15 + | +LL | for _v in [0; 33].iter() {} // no error + | ^^^^^^^^^^^^^^ help: to write this more concisely, try: `&[0; 33]` + error: it is more concise to loop over references to containers instead of using explicit iteration methods --> $DIR/for_loop_fixable.rs:62:15 | @@ -84,7 +96,7 @@ error: it is more concise to loop over references to containers instead of using --> $DIR/for_loop_fixable.rs:275:18 | LL | for _ in t.into_iter() {} - | ^^^^^^^^^^^^^ help: to write this more concisely, try: `&t` + | ^^^^^^^^^^^^^ help: to write this more concisely, try: `t` error: it is more concise to loop over containers instead of using explicit iteration methods --> $DIR/for_loop_fixable.rs:277:18 @@ -92,5 +104,17 @@ error: it is more concise to loop over containers instead of using explicit iter LL | for _ in r.into_iter() {} | ^^^^^^^^^^^^^ help: to write this more concisely, try: `r` -error: aborting due to 15 previous errors +error: it is more concise to loop over references to containers instead of using explicit iteration methods + --> $DIR/for_loop_fixable.rs:390:14 + | +LL | for _ in x.iter() {} + | ^^^^^^^^ help: to write this more concisely, try: `&x` + +error: it is more concise to loop over references to containers instead of using explicit iteration methods + --> $DIR/for_loop_fixable.rs:391:14 + | +LL | for _ in x.iter_mut() {} + | ^^^^^^^^^^^^ help: to write this more concisely, try: `&mut x` + +error: aborting due to 19 previous errors From 9d58a426230b5b4200791b9bedee1b14cb971197 Mon Sep 17 00:00:00 2001 From: y21 <30553356+y21@users.noreply.github.com> Date: Sat, 10 Jun 2023 01:38:04 +0200 Subject: [PATCH 119/310] [`map_unwrap_or`]: don't lint when referenced variable is moved --- .../src/methods/option_map_unwrap_or.rs | 105 ++++++++++++------ tests/ui/map_unwrap_or.rs | 29 +++++ 2 files changed, 97 insertions(+), 37 deletions(-) diff --git a/clippy_lints/src/methods/option_map_unwrap_or.rs b/clippy_lints/src/methods/option_map_unwrap_or.rs index 4c6328481e4..e931c6277f4 100644 --- a/clippy_lints/src/methods/option_map_unwrap_or.rs +++ b/clippy_lints/src/methods/option_map_unwrap_or.rs @@ -4,12 +4,17 @@ use clippy_utils::ty::is_copy; use clippy_utils::ty::is_type_diagnostic_item; use rustc_data_structures::fx::FxHashSet; use rustc_errors::Applicability; +use rustc_hir::def::Res; use rustc_hir::intravisit::{walk_path, Visitor}; +use rustc_hir::ExprKind; +use rustc_hir::Node; +use rustc_hir::PatKind; +use rustc_hir::QPath; use rustc_hir::{self, HirId, Path}; use rustc_lint::LateContext; use rustc_middle::hir::nested_filter; use rustc_span::source_map::Span; -use rustc_span::{sym, Symbol}; +use rustc_span::sym; use super::MAP_UNWRAP_OR; @@ -26,8 +31,22 @@ pub(super) fn check<'tcx>( // lint if the caller of `map()` is an `Option` if is_type_diagnostic_item(cx, cx.typeck_results().expr_ty(recv), sym::Option) { if !is_copy(cx, cx.typeck_results().expr_ty(unwrap_arg)) { - // Do not lint if the `map` argument uses identifiers in the `map` - // argument that are also used in the `unwrap_or` argument + // Replacing `.map().unwrap_or()` with `.map_or(, )` can sometimes lead to + // borrowck errors, see #10579 for one such instance. + // In particular, if `a` causes a move and `f` references that moved binding, then we cannot lint: + // ``` + // let x = vec![1, 2]; + // x.get(0..1).map(|s| s.to_vec()).unwrap_or(x); + // ``` + // This compiles, but changing it to `map_or` will produce a compile error: + // ``` + // let x = vec![1, 2]; + // x.get(0..1).map_or(x, |s| s.to_vec()) + // ^ moving `x` here + // ^^^^^^^^^^^ while it is borrowed here (and later used in the closure) + // ``` + // So, we have to check that `a` is not referenced anywhere (even outside of the `.map` closure!) + // before the call to `unwrap_or`. let mut unwrap_visitor = UnwrapVisitor { cx, @@ -35,14 +54,18 @@ pub(super) fn check<'tcx>( }; unwrap_visitor.visit_expr(unwrap_arg); - let mut map_expr_visitor = MapExprVisitor { + let mut reference_visitor = ReferenceVisitor { cx, identifiers: unwrap_visitor.identifiers, - found_identifier: false, + found_reference: false, + unwrap_or_span: unwrap_arg.span, }; - map_expr_visitor.visit_expr(map_arg); - if map_expr_visitor.found_identifier { + let map = cx.tcx.hir(); + let body = map.body(map.body_owned_by(map.enclosing_body_owner(expr.hir_id))); + reference_visitor.visit_body(body); + + if reference_visitor.found_reference { return; } } @@ -91,35 +114,18 @@ pub(super) fn check<'tcx>( struct UnwrapVisitor<'a, 'tcx> { cx: &'a LateContext<'tcx>, - identifiers: FxHashSet, + identifiers: FxHashSet, } impl<'a, 'tcx> Visitor<'tcx> for UnwrapVisitor<'a, 'tcx> { type NestedFilter = nested_filter::All; - fn visit_path(&mut self, path: &Path<'tcx>, _id: HirId) { - self.identifiers.insert(ident(path)); - walk_path(self, path); - } - - fn nested_visit_map(&mut self) -> Self::Map { - self.cx.tcx.hir() - } -} - -struct MapExprVisitor<'a, 'tcx> { - cx: &'a LateContext<'tcx>, - identifiers: FxHashSet, - found_identifier: bool, -} - -impl<'a, 'tcx> Visitor<'tcx> for MapExprVisitor<'a, 'tcx> { - type NestedFilter = nested_filter::All; - - fn visit_path(&mut self, path: &Path<'tcx>, _id: HirId) { - if self.identifiers.contains(&ident(path)) { - self.found_identifier = true; - return; + fn visit_path(&mut self, path: &Path<'tcx>, _: HirId) { + if let Res::Local(local_id) = path.res + && let Some(Node::Pat(pat)) = self.cx.tcx.hir().find(local_id) + && let PatKind::Binding(_, local_id, ..) = pat.kind + { + self.identifiers.insert(local_id); } walk_path(self, path); } @@ -129,10 +135,35 @@ impl<'a, 'tcx> Visitor<'tcx> for MapExprVisitor<'a, 'tcx> { } } -fn ident(path: &Path<'_>) -> Symbol { - path.segments - .last() - .expect("segments should be composed of at least 1 element") - .ident - .name +struct ReferenceVisitor<'a, 'tcx> { + cx: &'a LateContext<'tcx>, + identifiers: FxHashSet, + found_reference: bool, + unwrap_or_span: Span, +} + +impl<'a, 'tcx> Visitor<'tcx> for ReferenceVisitor<'a, 'tcx> { + type NestedFilter = nested_filter::All; + fn visit_expr(&mut self, expr: &'tcx rustc_hir::Expr<'_>) { + // If we haven't found a reference yet, check if this references + // one of the locals that was moved in the `unwrap_or` argument. + // We are only interested in exprs that appear before the `unwrap_or` call. + if !self.found_reference { + if expr.span < self.unwrap_or_span + && let ExprKind::Path(ref path) = expr.kind + && let QPath::Resolved(_, path) = path + && let Res::Local(local_id) = path.res + && let Some(Node::Pat(pat)) = self.cx.tcx.hir().find(local_id) + && let PatKind::Binding(_, local_id, ..) = pat.kind + && self.identifiers.contains(&local_id) + { + self.found_reference = true; + } + rustc_hir::intravisit::walk_expr(self, expr); + } + } + + fn nested_visit_map(&mut self) -> Self::Map { + self.cx.tcx.hir() + } } diff --git a/tests/ui/map_unwrap_or.rs b/tests/ui/map_unwrap_or.rs index cb25d8567aa..0cd49dd7760 100644 --- a/tests/ui/map_unwrap_or.rs +++ b/tests/ui/map_unwrap_or.rs @@ -94,3 +94,32 @@ fn msrv_1_41() { let _ = res.map(|x| x + 1).unwrap_or_else(|_e| 0); } + +mod issue_10579 { + // Different variations of the same issue. + fn v1() { + let x = vec![1, 2, 3, 0]; + let y = x.strip_suffix(&[0]).map(|s| s.to_vec()).unwrap_or(x); + println!("{y:?}"); + } + fn v2() { + let x = vec![1, 2, 3, 0]; + let y = Some(()).map(|_| x.to_vec()).unwrap_or(x); + println!("{y:?}"); + } + fn v3() { + let x = vec![1, 2, 3, 0]; + let xref = &x; + let y = Some(()).map(|_| xref.to_vec()).unwrap_or(x); + println!("{y:?}"); + } + fn v4() { + struct VecInStruct { + v: Vec, + } + let s = VecInStruct { v: vec![1, 2, 3, 0] }; + + let y = Some(()).map(|_| s.v.clone()).unwrap_or(s.v); + println!("{y:?}"); + } +} From 974900b50ed0fa63529032e9d9241b4a3ee5cefd Mon Sep 17 00:00:00 2001 From: Jason Newcomb Date: Mon, 27 Feb 2023 12:47:48 -0500 Subject: [PATCH 120/310] Split `for_loops` tests --- tests/ui/explicit_counter_loop.rs | 48 +++ tests/ui/explicit_counter_loop.stderr | 10 +- tests/ui/explicit_into_iter_loop.fixed | 55 ++++ tests/ui/explicit_into_iter_loop.rs | 55 ++++ tests/ui/explicit_into_iter_loop.stderr | 16 + tests/ui/explicit_iter_loop.fixed | 140 +++++++++ tests/ui/explicit_iter_loop.rs | 140 +++++++++ tests/ui/explicit_iter_loop.stderr | 106 +++++++ tests/ui/for_loop_fixable.fixed | 392 ------------------------ tests/ui/for_loop_fixable.rs | 392 ------------------------ tests/ui/for_loop_fixable.stderr | 120 -------- tests/ui/for_loop_unfixable.rs | 21 -- tests/ui/for_loop_unfixable.stderr | 10 - tests/ui/iter_next_loop.rs | 16 + tests/ui/iter_next_loop.stderr | 9 + tests/ui/needless_collect.fixed | 5 + tests/ui/needless_collect.rs | 5 + tests/ui/needless_range_loop.rs | 58 ++++ 18 files changed, 658 insertions(+), 940 deletions(-) create mode 100644 tests/ui/explicit_into_iter_loop.fixed create mode 100644 tests/ui/explicit_into_iter_loop.rs create mode 100644 tests/ui/explicit_into_iter_loop.stderr create mode 100644 tests/ui/explicit_iter_loop.fixed create mode 100644 tests/ui/explicit_iter_loop.rs create mode 100644 tests/ui/explicit_iter_loop.stderr delete mode 100644 tests/ui/for_loop_fixable.fixed delete mode 100644 tests/ui/for_loop_fixable.rs delete mode 100644 tests/ui/for_loop_fixable.stderr delete mode 100644 tests/ui/for_loop_unfixable.rs delete mode 100644 tests/ui/for_loop_unfixable.stderr create mode 100644 tests/ui/iter_next_loop.rs create mode 100644 tests/ui/iter_next_loop.stderr diff --git a/tests/ui/explicit_counter_loop.rs b/tests/ui/explicit_counter_loop.rs index 08e6de5dc19..e02b8f62b3d 100644 --- a/tests/ui/explicit_counter_loop.rs +++ b/tests/ui/explicit_counter_loop.rs @@ -23,6 +23,54 @@ fn main() { for _v in vec { _index += 1; } + + let vec = [1, 2, 3, 4]; + // Potential false positives + let mut _index = 0; + _index = 1; + for _v in &vec { + _index += 1 + } + + let mut _index = 0; + _index += 1; + for _v in &vec { + _index += 1 + } + + let mut _index = 0; + for _v in &vec { + _index = 1; + _index += 1 + } + + let mut _index = 0; + for _v in &vec { + let mut _index = 0; + _index += 1 + } + + let mut _index = 0; + for _v in &vec { + _index += 1; + _index = 0; + } + + let mut _index = 0; + if true { + _index = 1 + }; + for _v in &vec { + _index += 1 + } + + let mut _index = 1; + if false { + _index = 0 + }; + for _v in &vec { + _index += 1 + } } mod issue_1219 { diff --git a/tests/ui/explicit_counter_loop.stderr b/tests/ui/explicit_counter_loop.stderr index d3f3c626bbd..0677e4d78c8 100644 --- a/tests/ui/explicit_counter_loop.stderr +++ b/tests/ui/explicit_counter_loop.stderr @@ -25,31 +25,31 @@ LL | for _v in vec { | ^^^^^^^^^^^^^ help: consider using: `for (_index, _v) in vec.into_iter().enumerate()` error: the variable `count` is used as a loop counter - --> $DIR/explicit_counter_loop.rs:62:9 + --> $DIR/explicit_counter_loop.rs:110:9 | LL | for ch in text.chars() { | ^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `for (count, ch) in text.chars().enumerate()` error: the variable `count` is used as a loop counter - --> $DIR/explicit_counter_loop.rs:73:9 + --> $DIR/explicit_counter_loop.rs:121:9 | LL | for ch in text.chars() { | ^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `for (count, ch) in text.chars().enumerate()` error: the variable `count` is used as a loop counter - --> $DIR/explicit_counter_loop.rs:131:9 + --> $DIR/explicit_counter_loop.rs:179:9 | LL | for _i in 3..10 { | ^^^^^^^^^^^^^^^ help: consider using: `for (count, _i) in (3..10).enumerate()` error: the variable `idx_usize` is used as a loop counter - --> $DIR/explicit_counter_loop.rs:171:9 + --> $DIR/explicit_counter_loop.rs:219:9 | LL | for _item in slice { | ^^^^^^^^^^^^^^^^^^ help: consider using: `for (idx_usize, _item) in slice.iter().enumerate()` error: the variable `idx_u32` is used as a loop counter - --> $DIR/explicit_counter_loop.rs:183:9 + --> $DIR/explicit_counter_loop.rs:231:9 | LL | for _item in slice { | ^^^^^^^^^^^^^^^^^^ help: consider using: `for (idx_u32, _item) in (0_u32..).zip(slice.iter())` diff --git a/tests/ui/explicit_into_iter_loop.fixed b/tests/ui/explicit_into_iter_loop.fixed new file mode 100644 index 00000000000..bc9ecb1e05a --- /dev/null +++ b/tests/ui/explicit_into_iter_loop.fixed @@ -0,0 +1,55 @@ +//@run-rustfix +#![warn(clippy::explicit_into_iter_loop)] + +fn main() { + // Issue #4958 + fn _takes_iterator(iterator: &T) + where + for<'a> &'a T: IntoIterator, + { + for i in iterator { + println!("{}", i); + } + } + + struct T; + impl IntoIterator for &T { + type Item = (); + type IntoIter = std::vec::IntoIter; + fn into_iter(self) -> Self::IntoIter { + vec![].into_iter() + } + } + + let t = T; + let r = &t; + let rr = &&t; + + // This case is handled by `explicit_iter_loop`. No idea why. + for _ in t.into_iter() {} + + for _ in r {} + + // No suggestion for this. + // We'd have to suggest `for _ in *rr {}` which is less clear. + for _ in rr.into_iter() {} + + // Issue #6900 + struct S; + impl S { + #[allow(clippy::should_implement_trait)] + pub fn into_iter(self) -> I { + unimplemented!() + } + } + + struct I(T); + impl Iterator for I { + type Item = T; + fn next(&mut self) -> Option { + unimplemented!() + } + } + + for _ in S.into_iter::() {} +} diff --git a/tests/ui/explicit_into_iter_loop.rs b/tests/ui/explicit_into_iter_loop.rs new file mode 100644 index 00000000000..9b610fe3d11 --- /dev/null +++ b/tests/ui/explicit_into_iter_loop.rs @@ -0,0 +1,55 @@ +//@run-rustfix +#![warn(clippy::explicit_into_iter_loop)] + +fn main() { + // Issue #4958 + fn _takes_iterator(iterator: &T) + where + for<'a> &'a T: IntoIterator, + { + for i in iterator.into_iter() { + println!("{}", i); + } + } + + struct T; + impl IntoIterator for &T { + type Item = (); + type IntoIter = std::vec::IntoIter; + fn into_iter(self) -> Self::IntoIter { + vec![].into_iter() + } + } + + let t = T; + let r = &t; + let rr = &&t; + + // This case is handled by `explicit_iter_loop`. No idea why. + for _ in t.into_iter() {} + + for _ in r.into_iter() {} + + // No suggestion for this. + // We'd have to suggest `for _ in *rr {}` which is less clear. + for _ in rr.into_iter() {} + + // Issue #6900 + struct S; + impl S { + #[allow(clippy::should_implement_trait)] + pub fn into_iter(self) -> I { + unimplemented!() + } + } + + struct I(T); + impl Iterator for I { + type Item = T; + fn next(&mut self) -> Option { + unimplemented!() + } + } + + for _ in S.into_iter::() {} +} diff --git a/tests/ui/explicit_into_iter_loop.stderr b/tests/ui/explicit_into_iter_loop.stderr new file mode 100644 index 00000000000..1bd2b38a0e7 --- /dev/null +++ b/tests/ui/explicit_into_iter_loop.stderr @@ -0,0 +1,16 @@ +error: it is more concise to loop over containers instead of using explicit iteration methods + --> $DIR/explicit_into_iter_loop.rs:10:18 + | +LL | for i in iterator.into_iter() { + | ^^^^^^^^^^^^^^^^^^^^ help: to write this more concisely, try: `iterator` + | + = note: `-D clippy::explicit-into-iter-loop` implied by `-D warnings` + +error: it is more concise to loop over containers instead of using explicit iteration methods + --> $DIR/explicit_into_iter_loop.rs:31:14 + | +LL | for _ in r.into_iter() {} + | ^^^^^^^^^^^^^ help: to write this more concisely, try: `r` + +error: aborting due to 2 previous errors + diff --git a/tests/ui/explicit_iter_loop.fixed b/tests/ui/explicit_iter_loop.fixed new file mode 100644 index 00000000000..b0de50ed928 --- /dev/null +++ b/tests/ui/explicit_iter_loop.fixed @@ -0,0 +1,140 @@ +//@run-rustfix +#![deny(clippy::explicit_iter_loop)] +#![allow( + clippy::linkedlist, + clippy::similar_names, + clippy::needless_borrow, + clippy::deref_addrof, + dead_code +)] + +use core::slice; +use std::collections::*; + +fn main() { + let mut vec = vec![1, 2, 3, 4]; + + for _ in &vec {} + for _ in &mut vec {} + + for _ in &vec {} // these are fine + for _ in &mut vec {} // these are fine + + for _ in &[1, 2, 3] {} + + for _ in &*(&mut [1, 2, 3]) {} + + for _ in &[0; 32] {} + for _ in &[0; 33] {} + + let ll: LinkedList<()> = LinkedList::new(); + for _ in &ll {} + + let vd: VecDeque<()> = VecDeque::new(); + for _ in &vd {} + + let bh: BinaryHeap<()> = BinaryHeap::new(); + for _ in &bh {} + + let hm: HashMap<(), ()> = HashMap::new(); + for _ in &hm {} + + let bt: BTreeMap<(), ()> = BTreeMap::new(); + for _ in &bt {} + + let hs: HashSet<()> = HashSet::new(); + for _ in &hs {} + + let bs: BTreeSet<()> = BTreeSet::new(); + for _ in &bs {} + + struct NoIntoIter(); + impl NoIntoIter { + fn iter(&self) -> slice::Iter { + unimplemented!() + } + + fn iter_mut(&mut self) -> slice::IterMut { + unimplemented!() + } + } + let mut x = NoIntoIter(); + for _ in x.iter() {} // no error + for _ in x.iter_mut() {} // no error + + struct IntoIterDiffTy; + impl IntoIterator for &'_ IntoIterDiffTy { + type Item = &'static (); + type IntoIter = core::slice::Iter<'static, ()>; + fn into_iter(self) -> Self::IntoIter { + unimplemented!() + } + } + impl IntoIterDiffTy { + fn iter(&self) -> core::slice::Iter<'static, i32> { + unimplemented!() + } + } + let x = IntoIterDiffTy; + for _ in x.iter() {} + + struct IntoIterDiffSig; + impl IntoIterator for &'_ IntoIterDiffSig { + type Item = &'static (); + type IntoIter = core::slice::Iter<'static, ()>; + fn into_iter(self) -> Self::IntoIter { + unimplemented!() + } + } + impl IntoIterDiffSig { + fn iter(&self, _: u32) -> core::slice::Iter<'static, ()> { + unimplemented!() + } + } + let x = IntoIterDiffSig; + for _ in x.iter(0) {} + + struct IntoIterDiffLt<'a>(&'a ()); + impl<'a> IntoIterator for &'a IntoIterDiffLt<'_> { + type Item = &'a (); + type IntoIter = core::slice::Iter<'a, ()>; + fn into_iter(self) -> Self::IntoIter { + unimplemented!() + } + } + impl<'a> IntoIterDiffLt<'a> { + fn iter(&self) -> core::slice::Iter<'a, ()> { + unimplemented!() + } + } + let x = IntoIterDiffLt(&()); + for _ in x.iter() {} + + struct CustomType; + impl<'a> IntoIterator for &'a CustomType { + type Item = &'a u32; + type IntoIter = core::slice::Iter<'a, u32>; + fn into_iter(self) -> Self::IntoIter { + unimplemented!() + } + } + impl<'a> IntoIterator for &'a mut CustomType { + type Item = &'a mut u32; + type IntoIter = core::slice::IterMut<'a, u32>; + fn into_iter(self) -> Self::IntoIter { + unimplemented!() + } + } + impl CustomType { + fn iter(&self) -> <&'_ Self as IntoIterator>::IntoIter { + panic!() + } + + fn iter_mut(&mut self) -> core::slice::IterMut<'_, u32> { + panic!() + } + } + let mut x = CustomType; + for _ in &x {} + for _ in &mut x {} +} diff --git a/tests/ui/explicit_iter_loop.rs b/tests/ui/explicit_iter_loop.rs new file mode 100644 index 00000000000..33d3bada6e2 --- /dev/null +++ b/tests/ui/explicit_iter_loop.rs @@ -0,0 +1,140 @@ +//@run-rustfix +#![deny(clippy::explicit_iter_loop)] +#![allow( + clippy::linkedlist, + clippy::similar_names, + clippy::needless_borrow, + clippy::deref_addrof, + dead_code +)] + +use core::slice; +use std::collections::*; + +fn main() { + let mut vec = vec![1, 2, 3, 4]; + + for _ in vec.iter() {} + for _ in vec.iter_mut() {} + + for _ in &vec {} // these are fine + for _ in &mut vec {} // these are fine + + for _ in [1, 2, 3].iter() {} + + for _ in (&mut [1, 2, 3]).iter() {} + + for _ in [0; 32].iter() {} + for _ in [0; 33].iter() {} + + let ll: LinkedList<()> = LinkedList::new(); + for _ in ll.iter() {} + + let vd: VecDeque<()> = VecDeque::new(); + for _ in vd.iter() {} + + let bh: BinaryHeap<()> = BinaryHeap::new(); + for _ in bh.iter() {} + + let hm: HashMap<(), ()> = HashMap::new(); + for _ in hm.iter() {} + + let bt: BTreeMap<(), ()> = BTreeMap::new(); + for _ in bt.iter() {} + + let hs: HashSet<()> = HashSet::new(); + for _ in hs.iter() {} + + let bs: BTreeSet<()> = BTreeSet::new(); + for _ in bs.iter() {} + + struct NoIntoIter(); + impl NoIntoIter { + fn iter(&self) -> slice::Iter { + unimplemented!() + } + + fn iter_mut(&mut self) -> slice::IterMut { + unimplemented!() + } + } + let mut x = NoIntoIter(); + for _ in x.iter() {} // no error + for _ in x.iter_mut() {} // no error + + struct IntoIterDiffTy; + impl IntoIterator for &'_ IntoIterDiffTy { + type Item = &'static (); + type IntoIter = core::slice::Iter<'static, ()>; + fn into_iter(self) -> Self::IntoIter { + unimplemented!() + } + } + impl IntoIterDiffTy { + fn iter(&self) -> core::slice::Iter<'static, i32> { + unimplemented!() + } + } + let x = IntoIterDiffTy; + for _ in x.iter() {} + + struct IntoIterDiffSig; + impl IntoIterator for &'_ IntoIterDiffSig { + type Item = &'static (); + type IntoIter = core::slice::Iter<'static, ()>; + fn into_iter(self) -> Self::IntoIter { + unimplemented!() + } + } + impl IntoIterDiffSig { + fn iter(&self, _: u32) -> core::slice::Iter<'static, ()> { + unimplemented!() + } + } + let x = IntoIterDiffSig; + for _ in x.iter(0) {} + + struct IntoIterDiffLt<'a>(&'a ()); + impl<'a> IntoIterator for &'a IntoIterDiffLt<'_> { + type Item = &'a (); + type IntoIter = core::slice::Iter<'a, ()>; + fn into_iter(self) -> Self::IntoIter { + unimplemented!() + } + } + impl<'a> IntoIterDiffLt<'a> { + fn iter(&self) -> core::slice::Iter<'a, ()> { + unimplemented!() + } + } + let x = IntoIterDiffLt(&()); + for _ in x.iter() {} + + struct CustomType; + impl<'a> IntoIterator for &'a CustomType { + type Item = &'a u32; + type IntoIter = core::slice::Iter<'a, u32>; + fn into_iter(self) -> Self::IntoIter { + unimplemented!() + } + } + impl<'a> IntoIterator for &'a mut CustomType { + type Item = &'a mut u32; + type IntoIter = core::slice::IterMut<'a, u32>; + fn into_iter(self) -> Self::IntoIter { + unimplemented!() + } + } + impl CustomType { + fn iter(&self) -> <&'_ Self as IntoIterator>::IntoIter { + panic!() + } + + fn iter_mut(&mut self) -> core::slice::IterMut<'_, u32> { + panic!() + } + } + let mut x = CustomType; + for _ in x.iter() {} + for _ in x.iter_mut() {} +} diff --git a/tests/ui/explicit_iter_loop.stderr b/tests/ui/explicit_iter_loop.stderr new file mode 100644 index 00000000000..1508080a243 --- /dev/null +++ b/tests/ui/explicit_iter_loop.stderr @@ -0,0 +1,106 @@ +error: it is more concise to loop over references to containers instead of using explicit iteration methods + --> $DIR/explicit_iter_loop.rs:17:14 + | +LL | for _ in vec.iter() {} + | ^^^^^^^^^^ help: to write this more concisely, try: `&vec` + | +note: the lint level is defined here + --> $DIR/explicit_iter_loop.rs:2:9 + | +LL | #![deny(clippy::explicit_iter_loop)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: it is more concise to loop over references to containers instead of using explicit iteration methods + --> $DIR/explicit_iter_loop.rs:18:14 + | +LL | for _ in vec.iter_mut() {} + | ^^^^^^^^^^^^^^ help: to write this more concisely, try: `&mut vec` + +error: it is more concise to loop over references to containers instead of using explicit iteration methods + --> $DIR/explicit_iter_loop.rs:23:14 + | +LL | for _ in [1, 2, 3].iter() {} + | ^^^^^^^^^^^^^^^^ help: to write this more concisely, try: `&[1, 2, 3]` + +error: it is more concise to loop over references to containers instead of using explicit iteration methods + --> $DIR/explicit_iter_loop.rs:25:14 + | +LL | for _ in (&mut [1, 2, 3]).iter() {} + | ^^^^^^^^^^^^^^^^^^^^^^^ help: to write this more concisely, try: `&*(&mut [1, 2, 3])` + +error: the method `iter` doesn't need a mutable reference + --> $DIR/explicit_iter_loop.rs:25:14 + | +LL | for _ in (&mut [1, 2, 3]).iter() {} + | ^^^^^^^^^^^^^^^^ + | + = note: `-D clippy::unnecessary-mut-passed` implied by `-D warnings` + +error: it is more concise to loop over references to containers instead of using explicit iteration methods + --> $DIR/explicit_iter_loop.rs:27:14 + | +LL | for _ in [0; 32].iter() {} + | ^^^^^^^^^^^^^^ help: to write this more concisely, try: `&[0; 32]` + +error: it is more concise to loop over references to containers instead of using explicit iteration methods + --> $DIR/explicit_iter_loop.rs:28:14 + | +LL | for _ in [0; 33].iter() {} + | ^^^^^^^^^^^^^^ help: to write this more concisely, try: `&[0; 33]` + +error: it is more concise to loop over references to containers instead of using explicit iteration methods + --> $DIR/explicit_iter_loop.rs:31:14 + | +LL | for _ in ll.iter() {} + | ^^^^^^^^^ help: to write this more concisely, try: `&ll` + +error: it is more concise to loop over references to containers instead of using explicit iteration methods + --> $DIR/explicit_iter_loop.rs:34:14 + | +LL | for _ in vd.iter() {} + | ^^^^^^^^^ help: to write this more concisely, try: `&vd` + +error: it is more concise to loop over references to containers instead of using explicit iteration methods + --> $DIR/explicit_iter_loop.rs:37:14 + | +LL | for _ in bh.iter() {} + | ^^^^^^^^^ help: to write this more concisely, try: `&bh` + +error: it is more concise to loop over references to containers instead of using explicit iteration methods + --> $DIR/explicit_iter_loop.rs:40:14 + | +LL | for _ in hm.iter() {} + | ^^^^^^^^^ help: to write this more concisely, try: `&hm` + +error: it is more concise to loop over references to containers instead of using explicit iteration methods + --> $DIR/explicit_iter_loop.rs:43:14 + | +LL | for _ in bt.iter() {} + | ^^^^^^^^^ help: to write this more concisely, try: `&bt` + +error: it is more concise to loop over references to containers instead of using explicit iteration methods + --> $DIR/explicit_iter_loop.rs:46:14 + | +LL | for _ in hs.iter() {} + | ^^^^^^^^^ help: to write this more concisely, try: `&hs` + +error: it is more concise to loop over references to containers instead of using explicit iteration methods + --> $DIR/explicit_iter_loop.rs:49:14 + | +LL | for _ in bs.iter() {} + | ^^^^^^^^^ help: to write this more concisely, try: `&bs` + +error: it is more concise to loop over references to containers instead of using explicit iteration methods + --> $DIR/explicit_iter_loop.rs:138:14 + | +LL | for _ in x.iter() {} + | ^^^^^^^^ help: to write this more concisely, try: `&x` + +error: it is more concise to loop over references to containers instead of using explicit iteration methods + --> $DIR/explicit_iter_loop.rs:139:14 + | +LL | for _ in x.iter_mut() {} + | ^^^^^^^^^^^^ help: to write this more concisely, try: `&mut x` + +error: aborting due to 16 previous errors + diff --git a/tests/ui/for_loop_fixable.fixed b/tests/ui/for_loop_fixable.fixed deleted file mode 100644 index 99230856446..00000000000 --- a/tests/ui/for_loop_fixable.fixed +++ /dev/null @@ -1,392 +0,0 @@ -//@run-rustfix -#![allow(dead_code, unused)] -#![allow(clippy::uninlined_format_args, clippy::useless_vec, clippy::deref_addrof)] - -use std::collections::*; - -#[warn(clippy::all)] -struct Unrelated(Vec); -impl Unrelated { - fn next(&self) -> std::slice::Iter { - self.0.iter() - } - - fn iter(&self) -> std::slice::Iter { - self.0.iter() - } -} - -#[warn( - clippy::needless_range_loop, - clippy::explicit_iter_loop, - clippy::explicit_into_iter_loop, - clippy::iter_next_loop, - clippy::for_kv_map -)] -#[allow( - clippy::linkedlist, - clippy::unnecessary_mut_passed, - clippy::similar_names, - clippy::needless_borrow -)] -#[allow(unused_variables)] -fn main() { - let mut vec = vec![1, 2, 3, 4]; - - // See #601 - for i in 0..10 { - // no error, id_col does not exist outside the loop - let mut id_col = vec![0f64; 10]; - id_col[i] = 1f64; - } - - for _v in &vec {} - - for _v in &mut vec {} - - let out_vec = vec![1, 2, 3]; - for _v in out_vec {} - - for _v in &vec {} // these are fine - for _v in &mut vec {} // these are fine - - for _v in &[1, 2, 3] {} - - for _v in &*(&mut [1, 2, 3]) {} // no error - - for _v in &[0; 32] {} - - for _v in &[0; 33] {} // no error - - let ll: LinkedList<()> = LinkedList::new(); - for _v in &ll {} - - let vd: VecDeque<()> = VecDeque::new(); - for _v in &vd {} - - let bh: BinaryHeap<()> = BinaryHeap::new(); - for _v in &bh {} - - let hm: HashMap<(), ()> = HashMap::new(); - for _v in &hm {} - - let bt: BTreeMap<(), ()> = BTreeMap::new(); - for _v in &bt {} - - let hs: HashSet<()> = HashSet::new(); - for _v in &hs {} - - let bs: BTreeSet<()> = BTreeSet::new(); - for _v in &bs {} - - let u = Unrelated(vec![]); - for _v in u.next() {} // no error - for _v in u.iter() {} // no error - - let mut out = vec![]; - vec.iter().cloned().map(|x| out.push(x)).collect::>(); - let _y = vec.iter().cloned().map(|x| out.push(x)).collect::>(); // this is fine - - // Loop with explicit counter variable - - // Potential false positives - let mut _index = 0; - _index = 1; - for _v in &vec { - _index += 1 - } - - let mut _index = 0; - _index += 1; - for _v in &vec { - _index += 1 - } - - let mut _index = 0; - if true { - _index = 1 - } - for _v in &vec { - _index += 1 - } - - let mut _index = 0; - let mut _index = 1; - for _v in &vec { - _index += 1 - } - - let mut _index = 0; - for _v in &vec { - _index += 1; - _index += 1 - } - - let mut _index = 0; - for _v in &vec { - _index *= 2; - _index += 1 - } - - let mut _index = 0; - for _v in &vec { - _index = 1; - _index += 1 - } - - let mut _index = 0; - - for _v in &vec { - let mut _index = 0; - _index += 1 - } - - let mut _index = 0; - for _v in &vec { - _index += 1; - _index = 0; - } - - let mut _index = 0; - for _v in &vec { - for _x in 0..1 { - _index += 1; - } - _index += 1 - } - - let mut _index = 0; - for x in &vec { - if *x == 1 { - _index += 1 - } - } - - let mut _index = 0; - if true { - _index = 1 - }; - for _v in &vec { - _index += 1 - } - - let mut _index = 1; - if false { - _index = 0 - }; - for _v in &vec { - _index += 1 - } - - let mut index = 0; - { - let mut _x = &mut index; - } - for _v in &vec { - _index += 1 - } - - let mut index = 0; - for _v in &vec { - index += 1 - } - println!("index: {}", index); - - fn f(_: &T, _: &T) -> bool { - unimplemented!() - } - fn g(_: &mut [T], _: usize, _: usize) { - unimplemented!() - } - for i in 1..vec.len() { - if f(&vec[i - 1], &vec[i]) { - g(&mut vec, i - 1, i); - } - } - - for mid in 1..vec.len() { - let (_, _) = vec.split_at(mid); - } -} - -fn partition(v: &mut [T]) -> usize { - let pivot = v.len() - 1; - let mut i = 0; - for j in 0..pivot { - if v[j] <= v[pivot] { - v.swap(i, j); - i += 1; - } - } - v.swap(i, pivot); - i -} - -#[warn(clippy::needless_range_loop)] -pub fn manual_copy_same_destination(dst: &mut [i32], d: usize, s: usize) { - // Same source and destination - don't trigger lint - for i in 0..dst.len() { - dst[d + i] = dst[s + i]; - } -} - -mod issue_2496 { - pub trait Handle { - fn new_for_index(index: usize) -> Self; - fn index(&self) -> usize; - } - - pub fn test() -> H { - for x in 0..5 { - let next_handle = H::new_for_index(x); - println!("{}", next_handle.index()); - } - unimplemented!() - } -} - -// explicit_into_iter_loop bad suggestions -#[warn(clippy::explicit_into_iter_loop, clippy::explicit_iter_loop)] -mod issue_4958 { - fn takes_iterator(iterator: &T) - where - for<'a> &'a T: IntoIterator, - { - for i in iterator { - println!("{}", i); - } - } - - struct T; - impl IntoIterator for &T { - type Item = (); - type IntoIter = std::vec::IntoIter; - fn into_iter(self) -> Self::IntoIter { - vec![].into_iter() - } - } - - fn more_tests() { - let t = T; - let r = &t; - let rr = &&t; - - // This case is handled by `explicit_iter_loop`. No idea why. - for _ in t {} - - for _ in r {} - - // No suggestion for this. - // We'd have to suggest `for _ in *rr {}` which is less clear. - for _ in rr.into_iter() {} - } -} - -// explicit_into_iter_loop -#[warn(clippy::explicit_into_iter_loop)] -mod issue_6900 { - struct S; - impl S { - #[allow(clippy::should_implement_trait)] - pub fn into_iter(self) -> I { - unimplemented!() - } - } - - struct I(T); - impl Iterator for I { - type Item = T; - fn next(&mut self) -> Option { - unimplemented!() - } - } - - fn f() { - for _ in S.into_iter::() { - unimplemented!() - } - } -} - -struct IntoIterDiffTy; -impl IntoIterator for &'_ IntoIterDiffTy { - type Item = &'static (); - type IntoIter = core::slice::Iter<'static, ()>; - fn into_iter(self) -> Self::IntoIter { - unimplemented!() - } -} -impl IntoIterDiffTy { - fn iter(&self) -> core::slice::Iter<'static, i32> { - unimplemented!() - } -} - -struct IntoIterDiffSig; -impl IntoIterator for &'_ IntoIterDiffSig { - type Item = &'static (); - type IntoIter = core::slice::Iter<'static, ()>; - fn into_iter(self) -> Self::IntoIter { - unimplemented!() - } -} -impl IntoIterDiffSig { - fn iter(&self, _: u32) -> core::slice::Iter<'static, ()> { - unimplemented!() - } -} - -struct IntoIterDiffLt<'a>(&'a ()); -impl<'a> IntoIterator for &'a IntoIterDiffLt<'_> { - type Item = &'a (); - type IntoIter = core::slice::Iter<'a, ()>; - fn into_iter(self) -> Self::IntoIter { - unimplemented!() - } -} -impl<'a> IntoIterDiffLt<'a> { - fn iter(&self) -> core::slice::Iter<'a, ()> { - unimplemented!() - } -} - -struct CustomType; -impl<'a> IntoIterator for &'a CustomType { - type Item = &'a u32; - type IntoIter = core::slice::Iter<'a, u32>; - fn into_iter(self) -> Self::IntoIter { - unimplemented!() - } -} -impl<'a> IntoIterator for &'a mut CustomType { - type Item = &'a mut u32; - type IntoIter = core::slice::IterMut<'a, u32>; - fn into_iter(self) -> Self::IntoIter { - unimplemented!() - } -} -impl CustomType { - fn iter(&self) -> <&'_ Self as IntoIterator>::IntoIter { - panic!() - } - - fn iter_mut(&mut self) -> core::slice::IterMut<'_, u32> { - panic!() - } -} - -#[warn(clippy::explicit_iter_loop)] -fn _f() { - let x = IntoIterDiffTy; - for _ in x.iter() {} - - let x = IntoIterDiffSig; - for _ in x.iter(0) {} - - let x = IntoIterDiffLt(&()); - for _ in x.iter() {} - - let mut x = CustomType; - for _ in &x {} - for _ in &mut x {} -} diff --git a/tests/ui/for_loop_fixable.rs b/tests/ui/for_loop_fixable.rs deleted file mode 100644 index 0d7fe3c0314..00000000000 --- a/tests/ui/for_loop_fixable.rs +++ /dev/null @@ -1,392 +0,0 @@ -//@run-rustfix -#![allow(dead_code, unused)] -#![allow(clippy::uninlined_format_args, clippy::useless_vec, clippy::deref_addrof)] - -use std::collections::*; - -#[warn(clippy::all)] -struct Unrelated(Vec); -impl Unrelated { - fn next(&self) -> std::slice::Iter { - self.0.iter() - } - - fn iter(&self) -> std::slice::Iter { - self.0.iter() - } -} - -#[warn( - clippy::needless_range_loop, - clippy::explicit_iter_loop, - clippy::explicit_into_iter_loop, - clippy::iter_next_loop, - clippy::for_kv_map -)] -#[allow( - clippy::linkedlist, - clippy::unnecessary_mut_passed, - clippy::similar_names, - clippy::needless_borrow -)] -#[allow(unused_variables)] -fn main() { - let mut vec = vec![1, 2, 3, 4]; - - // See #601 - for i in 0..10 { - // no error, id_col does not exist outside the loop - let mut id_col = vec![0f64; 10]; - id_col[i] = 1f64; - } - - for _v in vec.iter() {} - - for _v in vec.iter_mut() {} - - let out_vec = vec![1, 2, 3]; - for _v in out_vec.into_iter() {} - - for _v in &vec {} // these are fine - for _v in &mut vec {} // these are fine - - for _v in [1, 2, 3].iter() {} - - for _v in (&mut [1, 2, 3]).iter() {} // no error - - for _v in [0; 32].iter() {} - - for _v in [0; 33].iter() {} // no error - - let ll: LinkedList<()> = LinkedList::new(); - for _v in ll.iter() {} - - let vd: VecDeque<()> = VecDeque::new(); - for _v in vd.iter() {} - - let bh: BinaryHeap<()> = BinaryHeap::new(); - for _v in bh.iter() {} - - let hm: HashMap<(), ()> = HashMap::new(); - for _v in hm.iter() {} - - let bt: BTreeMap<(), ()> = BTreeMap::new(); - for _v in bt.iter() {} - - let hs: HashSet<()> = HashSet::new(); - for _v in hs.iter() {} - - let bs: BTreeSet<()> = BTreeSet::new(); - for _v in bs.iter() {} - - let u = Unrelated(vec![]); - for _v in u.next() {} // no error - for _v in u.iter() {} // no error - - let mut out = vec![]; - vec.iter().cloned().map(|x| out.push(x)).collect::>(); - let _y = vec.iter().cloned().map(|x| out.push(x)).collect::>(); // this is fine - - // Loop with explicit counter variable - - // Potential false positives - let mut _index = 0; - _index = 1; - for _v in &vec { - _index += 1 - } - - let mut _index = 0; - _index += 1; - for _v in &vec { - _index += 1 - } - - let mut _index = 0; - if true { - _index = 1 - } - for _v in &vec { - _index += 1 - } - - let mut _index = 0; - let mut _index = 1; - for _v in &vec { - _index += 1 - } - - let mut _index = 0; - for _v in &vec { - _index += 1; - _index += 1 - } - - let mut _index = 0; - for _v in &vec { - _index *= 2; - _index += 1 - } - - let mut _index = 0; - for _v in &vec { - _index = 1; - _index += 1 - } - - let mut _index = 0; - - for _v in &vec { - let mut _index = 0; - _index += 1 - } - - let mut _index = 0; - for _v in &vec { - _index += 1; - _index = 0; - } - - let mut _index = 0; - for _v in &vec { - for _x in 0..1 { - _index += 1; - } - _index += 1 - } - - let mut _index = 0; - for x in &vec { - if *x == 1 { - _index += 1 - } - } - - let mut _index = 0; - if true { - _index = 1 - }; - for _v in &vec { - _index += 1 - } - - let mut _index = 1; - if false { - _index = 0 - }; - for _v in &vec { - _index += 1 - } - - let mut index = 0; - { - let mut _x = &mut index; - } - for _v in &vec { - _index += 1 - } - - let mut index = 0; - for _v in &vec { - index += 1 - } - println!("index: {}", index); - - fn f(_: &T, _: &T) -> bool { - unimplemented!() - } - fn g(_: &mut [T], _: usize, _: usize) { - unimplemented!() - } - for i in 1..vec.len() { - if f(&vec[i - 1], &vec[i]) { - g(&mut vec, i - 1, i); - } - } - - for mid in 1..vec.len() { - let (_, _) = vec.split_at(mid); - } -} - -fn partition(v: &mut [T]) -> usize { - let pivot = v.len() - 1; - let mut i = 0; - for j in 0..pivot { - if v[j] <= v[pivot] { - v.swap(i, j); - i += 1; - } - } - v.swap(i, pivot); - i -} - -#[warn(clippy::needless_range_loop)] -pub fn manual_copy_same_destination(dst: &mut [i32], d: usize, s: usize) { - // Same source and destination - don't trigger lint - for i in 0..dst.len() { - dst[d + i] = dst[s + i]; - } -} - -mod issue_2496 { - pub trait Handle { - fn new_for_index(index: usize) -> Self; - fn index(&self) -> usize; - } - - pub fn test() -> H { - for x in 0..5 { - let next_handle = H::new_for_index(x); - println!("{}", next_handle.index()); - } - unimplemented!() - } -} - -// explicit_into_iter_loop bad suggestions -#[warn(clippy::explicit_into_iter_loop, clippy::explicit_iter_loop)] -mod issue_4958 { - fn takes_iterator(iterator: &T) - where - for<'a> &'a T: IntoIterator, - { - for i in iterator.into_iter() { - println!("{}", i); - } - } - - struct T; - impl IntoIterator for &T { - type Item = (); - type IntoIter = std::vec::IntoIter; - fn into_iter(self) -> Self::IntoIter { - vec![].into_iter() - } - } - - fn more_tests() { - let t = T; - let r = &t; - let rr = &&t; - - // This case is handled by `explicit_iter_loop`. No idea why. - for _ in t.into_iter() {} - - for _ in r.into_iter() {} - - // No suggestion for this. - // We'd have to suggest `for _ in *rr {}` which is less clear. - for _ in rr.into_iter() {} - } -} - -// explicit_into_iter_loop -#[warn(clippy::explicit_into_iter_loop)] -mod issue_6900 { - struct S; - impl S { - #[allow(clippy::should_implement_trait)] - pub fn into_iter(self) -> I { - unimplemented!() - } - } - - struct I(T); - impl Iterator for I { - type Item = T; - fn next(&mut self) -> Option { - unimplemented!() - } - } - - fn f() { - for _ in S.into_iter::() { - unimplemented!() - } - } -} - -struct IntoIterDiffTy; -impl IntoIterator for &'_ IntoIterDiffTy { - type Item = &'static (); - type IntoIter = core::slice::Iter<'static, ()>; - fn into_iter(self) -> Self::IntoIter { - unimplemented!() - } -} -impl IntoIterDiffTy { - fn iter(&self) -> core::slice::Iter<'static, i32> { - unimplemented!() - } -} - -struct IntoIterDiffSig; -impl IntoIterator for &'_ IntoIterDiffSig { - type Item = &'static (); - type IntoIter = core::slice::Iter<'static, ()>; - fn into_iter(self) -> Self::IntoIter { - unimplemented!() - } -} -impl IntoIterDiffSig { - fn iter(&self, _: u32) -> core::slice::Iter<'static, ()> { - unimplemented!() - } -} - -struct IntoIterDiffLt<'a>(&'a ()); -impl<'a> IntoIterator for &'a IntoIterDiffLt<'_> { - type Item = &'a (); - type IntoIter = core::slice::Iter<'a, ()>; - fn into_iter(self) -> Self::IntoIter { - unimplemented!() - } -} -impl<'a> IntoIterDiffLt<'a> { - fn iter(&self) -> core::slice::Iter<'a, ()> { - unimplemented!() - } -} - -struct CustomType; -impl<'a> IntoIterator for &'a CustomType { - type Item = &'a u32; - type IntoIter = core::slice::Iter<'a, u32>; - fn into_iter(self) -> Self::IntoIter { - unimplemented!() - } -} -impl<'a> IntoIterator for &'a mut CustomType { - type Item = &'a mut u32; - type IntoIter = core::slice::IterMut<'a, u32>; - fn into_iter(self) -> Self::IntoIter { - unimplemented!() - } -} -impl CustomType { - fn iter(&self) -> <&'_ Self as IntoIterator>::IntoIter { - panic!() - } - - fn iter_mut(&mut self) -> core::slice::IterMut<'_, u32> { - panic!() - } -} - -#[warn(clippy::explicit_iter_loop)] -fn _f() { - let x = IntoIterDiffTy; - for _ in x.iter() {} - - let x = IntoIterDiffSig; - for _ in x.iter(0) {} - - let x = IntoIterDiffLt(&()); - for _ in x.iter() {} - - let mut x = CustomType; - for _ in x.iter() {} - for _ in x.iter_mut() {} -} diff --git a/tests/ui/for_loop_fixable.stderr b/tests/ui/for_loop_fixable.stderr deleted file mode 100644 index 4ad23e0b9db..00000000000 --- a/tests/ui/for_loop_fixable.stderr +++ /dev/null @@ -1,120 +0,0 @@ -error: it is more concise to loop over references to containers instead of using explicit iteration methods - --> $DIR/for_loop_fixable.rs:43:15 - | -LL | for _v in vec.iter() {} - | ^^^^^^^^^^ help: to write this more concisely, try: `&vec` - | - = note: `-D clippy::explicit-iter-loop` implied by `-D warnings` - -error: it is more concise to loop over references to containers instead of using explicit iteration methods - --> $DIR/for_loop_fixable.rs:45:15 - | -LL | for _v in vec.iter_mut() {} - | ^^^^^^^^^^^^^^ help: to write this more concisely, try: `&mut vec` - -error: it is more concise to loop over containers instead of using explicit iteration methods - --> $DIR/for_loop_fixable.rs:48:15 - | -LL | for _v in out_vec.into_iter() {} - | ^^^^^^^^^^^^^^^^^^^ help: to write this more concisely, try: `out_vec` - | - = note: `-D clippy::explicit-into-iter-loop` implied by `-D warnings` - -error: it is more concise to loop over references to containers instead of using explicit iteration methods - --> $DIR/for_loop_fixable.rs:53:15 - | -LL | for _v in [1, 2, 3].iter() {} - | ^^^^^^^^^^^^^^^^ help: to write this more concisely, try: `&[1, 2, 3]` - -error: it is more concise to loop over references to containers instead of using explicit iteration methods - --> $DIR/for_loop_fixable.rs:55:15 - | -LL | for _v in (&mut [1, 2, 3]).iter() {} // no error - | ^^^^^^^^^^^^^^^^^^^^^^^ help: to write this more concisely, try: `&*(&mut [1, 2, 3])` - -error: it is more concise to loop over references to containers instead of using explicit iteration methods - --> $DIR/for_loop_fixable.rs:57:15 - | -LL | for _v in [0; 32].iter() {} - | ^^^^^^^^^^^^^^ help: to write this more concisely, try: `&[0; 32]` - -error: it is more concise to loop over references to containers instead of using explicit iteration methods - --> $DIR/for_loop_fixable.rs:59:15 - | -LL | for _v in [0; 33].iter() {} // no error - | ^^^^^^^^^^^^^^ help: to write this more concisely, try: `&[0; 33]` - -error: it is more concise to loop over references to containers instead of using explicit iteration methods - --> $DIR/for_loop_fixable.rs:62:15 - | -LL | for _v in ll.iter() {} - | ^^^^^^^^^ help: to write this more concisely, try: `&ll` - -error: it is more concise to loop over references to containers instead of using explicit iteration methods - --> $DIR/for_loop_fixable.rs:65:15 - | -LL | for _v in vd.iter() {} - | ^^^^^^^^^ help: to write this more concisely, try: `&vd` - -error: it is more concise to loop over references to containers instead of using explicit iteration methods - --> $DIR/for_loop_fixable.rs:68:15 - | -LL | for _v in bh.iter() {} - | ^^^^^^^^^ help: to write this more concisely, try: `&bh` - -error: it is more concise to loop over references to containers instead of using explicit iteration methods - --> $DIR/for_loop_fixable.rs:71:15 - | -LL | for _v in hm.iter() {} - | ^^^^^^^^^ help: to write this more concisely, try: `&hm` - -error: it is more concise to loop over references to containers instead of using explicit iteration methods - --> $DIR/for_loop_fixable.rs:74:15 - | -LL | for _v in bt.iter() {} - | ^^^^^^^^^ help: to write this more concisely, try: `&bt` - -error: it is more concise to loop over references to containers instead of using explicit iteration methods - --> $DIR/for_loop_fixable.rs:77:15 - | -LL | for _v in hs.iter() {} - | ^^^^^^^^^ help: to write this more concisely, try: `&hs` - -error: it is more concise to loop over references to containers instead of using explicit iteration methods - --> $DIR/for_loop_fixable.rs:80:15 - | -LL | for _v in bs.iter() {} - | ^^^^^^^^^ help: to write this more concisely, try: `&bs` - -error: it is more concise to loop over containers instead of using explicit iteration methods - --> $DIR/for_loop_fixable.rs:255:18 - | -LL | for i in iterator.into_iter() { - | ^^^^^^^^^^^^^^^^^^^^ help: to write this more concisely, try: `iterator` - -error: it is more concise to loop over references to containers instead of using explicit iteration methods - --> $DIR/for_loop_fixable.rs:275:18 - | -LL | for _ in t.into_iter() {} - | ^^^^^^^^^^^^^ help: to write this more concisely, try: `t` - -error: it is more concise to loop over containers instead of using explicit iteration methods - --> $DIR/for_loop_fixable.rs:277:18 - | -LL | for _ in r.into_iter() {} - | ^^^^^^^^^^^^^ help: to write this more concisely, try: `r` - -error: it is more concise to loop over references to containers instead of using explicit iteration methods - --> $DIR/for_loop_fixable.rs:390:14 - | -LL | for _ in x.iter() {} - | ^^^^^^^^ help: to write this more concisely, try: `&x` - -error: it is more concise to loop over references to containers instead of using explicit iteration methods - --> $DIR/for_loop_fixable.rs:391:14 - | -LL | for _ in x.iter_mut() {} - | ^^^^^^^^^^^^ help: to write this more concisely, try: `&mut x` - -error: aborting due to 19 previous errors - diff --git a/tests/ui/for_loop_unfixable.rs b/tests/ui/for_loop_unfixable.rs deleted file mode 100644 index 8e3fb99bc7c..00000000000 --- a/tests/ui/for_loop_unfixable.rs +++ /dev/null @@ -1,21 +0,0 @@ -// Tests from for_loop.rs that don't have suggestions - -#[warn( - clippy::needless_range_loop, - clippy::explicit_iter_loop, - clippy::explicit_into_iter_loop, - clippy::iter_next_loop, - clippy::for_kv_map -)] -#[allow( - clippy::linkedlist, - clippy::unnecessary_mut_passed, - clippy::similar_names, - clippy::useless_vec -)] -#[allow(for_loops_over_fallibles)] -fn main() { - let vec = vec![1, 2, 3, 4]; - - for _v in vec.iter().next() {} -} diff --git a/tests/ui/for_loop_unfixable.stderr b/tests/ui/for_loop_unfixable.stderr deleted file mode 100644 index 8b163a142a5..00000000000 --- a/tests/ui/for_loop_unfixable.stderr +++ /dev/null @@ -1,10 +0,0 @@ -error: you are iterating over `Iterator::next()` which is an Option; this will compile but is probably not what you want - --> $DIR/for_loop_unfixable.rs:20:15 - | -LL | for _v in vec.iter().next() {} - | ^^^^^^^^^^^^^^^^^ - | - = note: `-D clippy::iter-next-loop` implied by `-D warnings` - -error: aborting due to previous error - diff --git a/tests/ui/iter_next_loop.rs b/tests/ui/iter_next_loop.rs new file mode 100644 index 00000000000..548b799de44 --- /dev/null +++ b/tests/ui/iter_next_loop.rs @@ -0,0 +1,16 @@ +#![allow(dead_code, unused, for_loops_over_fallibles)] +#![warn(clippy::iter_next_loop)] + +fn main() { + let x = [1, 2, 3, 4]; + for _ in vec.iter().next() {} + + struct Unrelated(&'static [u8]); + impl Unrelated { + fn next(&self) -> std::slice::Iter { + self.0.iter() + } + } + let u = Unrelated(&[0]); + for _v in u.next() {} // no error +} diff --git a/tests/ui/iter_next_loop.stderr b/tests/ui/iter_next_loop.stderr new file mode 100644 index 00000000000..5bba0e635bb --- /dev/null +++ b/tests/ui/iter_next_loop.stderr @@ -0,0 +1,9 @@ +error[E0423]: expected value, found macro `vec` + --> $DIR/iter_next_loop.rs:6:14 + | +LL | for _ in vec.iter().next() {} + | ^^^ not a value + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0423`. diff --git a/tests/ui/needless_collect.fixed b/tests/ui/needless_collect.fixed index b7e80af5015..17a56cdfc2f 100644 --- a/tests/ui/needless_collect.fixed +++ b/tests/ui/needless_collect.fixed @@ -70,6 +70,11 @@ fn main() { bar((0..10).collect::>(), (0..10)); baz((0..10), (), ('a'..='z')) } + + let values = [1, 2, 3, 4]; + let mut out = vec![]; + values.iter().cloned().map(|x| out.push(x)).collect::>(); + let _y = values.iter().cloned().map(|x| out.push(x)).collect::>(); // this is fine } fn foo(_: impl IntoIterator) {} diff --git a/tests/ui/needless_collect.rs b/tests/ui/needless_collect.rs index 680b6fa5b55..8615899e979 100644 --- a/tests/ui/needless_collect.rs +++ b/tests/ui/needless_collect.rs @@ -70,6 +70,11 @@ fn main() { bar((0..10).collect::>(), (0..10).collect::>()); baz((0..10), (), ('a'..='z').collect::>()) } + + let values = [1, 2, 3, 4]; + let mut out = vec![]; + values.iter().cloned().map(|x| out.push(x)).collect::>(); + let _y = values.iter().cloned().map(|x| out.push(x)).collect::>(); // this is fine } fn foo(_: impl IntoIterator) {} diff --git a/tests/ui/needless_range_loop.rs b/tests/ui/needless_range_loop.rs index 329cdc1f06b..1935ccb94bd 100644 --- a/tests/ui/needless_range_loop.rs +++ b/tests/ui/needless_range_loop.rs @@ -82,6 +82,29 @@ fn main() { for i in 0..2 { println!("{}", test[i]); } + + // See #601 + for i in 0..10 { + // no error, id_col does not exist outside the loop + let mut id_col = [0f64; 10]; + id_col[i] = 1f64; + } + + fn f(_: &T, _: &T) -> bool { + unimplemented!() + } + fn g(_: &mut [T], _: usize, _: usize) { + unimplemented!() + } + for i in 1..vec.len() { + if f(&vec[i - 1], &vec[i]) { + g(&mut vec, i - 1, i); + } + } + + for mid in 1..vec.len() { + let (_, _) = vec.split_at(mid); + } } struct Test { @@ -94,3 +117,38 @@ impl std::ops::Index for Test { &self.inner[index] } } + +fn partition(v: &mut [T]) -> usize { + let pivot = v.len() - 1; + let mut i = 0; + for j in 0..pivot { + if v[j] <= v[pivot] { + v.swap(i, j); + i += 1; + } + } + v.swap(i, pivot); + i +} + +pub fn manual_copy_same_destination(dst: &mut [i32], d: usize, s: usize) { + // Same source and destination - don't trigger lint + for i in 0..dst.len() { + dst[d + i] = dst[s + i]; + } +} + +mod issue_2496 { + pub trait Handle { + fn new_for_index(index: usize) -> Self; + fn index(&self) -> usize; + } + + pub fn test() -> H { + for x in 0..5 { + let next_handle = H::new_for_index(x); + println!("{}", next_handle.index()); + } + unimplemented!() + } +} From 482baf2bccaba4a86624fff1483fe2d1d83e53c4 Mon Sep 17 00:00:00 2001 From: Jason Newcomb Date: Mon, 27 Feb 2023 13:28:27 -0500 Subject: [PATCH 121/310] Fix `explicit_into_iter_loop` with mutable references --- .../src/loops/explicit_into_iter_loop.rs | 69 +++++++++++++- clippy_lints/src/loops/explicit_iter_loop.rs | 93 ++++++++++--------- clippy_lints/src/loops/mod.rs | 7 +- tests/ui/explicit_into_iter_loop.fixed | 34 +++++-- tests/ui/explicit_into_iter_loop.rs | 32 +++++-- tests/ui/explicit_into_iter_loop.stderr | 30 +++++- 6 files changed, 188 insertions(+), 77 deletions(-) diff --git a/clippy_lints/src/loops/explicit_into_iter_loop.rs b/clippy_lints/src/loops/explicit_into_iter_loop.rs index 175e2b382e3..bf5e018ce92 100644 --- a/clippy_lints/src/loops/explicit_into_iter_loop.rs +++ b/clippy_lints/src/loops/explicit_into_iter_loop.rs @@ -5,15 +5,76 @@ use clippy_utils::source::snippet_with_applicability; use rustc_errors::Applicability; use rustc_hir::Expr; use rustc_lint::LateContext; +use rustc_middle::ty::adjustment::{Adjust, Adjustment, AutoBorrow, AutoBorrowMutability}; use rustc_span::symbol::sym; +#[derive(Clone, Copy)] +enum AdjustKind { + None, + Borrow, + BorrowMut, + Reborrow, + ReborrowMut, +} +impl AdjustKind { + fn borrow(mutbl: AutoBorrowMutability) -> Self { + match mutbl { + AutoBorrowMutability::Not => Self::Borrow, + AutoBorrowMutability::Mut { .. } => Self::BorrowMut, + } + } + + fn reborrow(mutbl: AutoBorrowMutability) -> Self { + match mutbl { + AutoBorrowMutability::Not => Self::Reborrow, + AutoBorrowMutability::Mut { .. } => Self::ReborrowMut, + } + } + + fn display(self) -> &'static str { + match self { + Self::None => "", + Self::Borrow => "&", + Self::BorrowMut => "&mut ", + Self::Reborrow => "&*", + Self::ReborrowMut => "&mut *", + } + } +} + pub(super) fn check(cx: &LateContext<'_>, self_arg: &Expr<'_>, call_expr: &Expr<'_>) { - let self_ty = cx.typeck_results().expr_ty(self_arg); - let self_ty_adjusted = cx.typeck_results().expr_ty_adjusted(self_arg); - if !(self_ty == self_ty_adjusted && is_trait_method(cx, call_expr, sym::IntoIterator)) { + if !is_trait_method(cx, call_expr, sym::IntoIterator) { return; } + let typeck = cx.typeck_results(); + let self_ty = typeck.expr_ty(self_arg); + let adjust = match typeck.expr_adjustments(self_arg) { + [] => AdjustKind::None, + &[ + Adjustment { + kind: Adjust::Borrow(AutoBorrow::Ref(_, mutbl)), + .. + }, + ] => AdjustKind::borrow(mutbl), + &[ + Adjustment { + kind: Adjust::Deref(_), .. + }, + Adjustment { + kind: Adjust::Borrow(AutoBorrow::Ref(_, mutbl)), + target, + }, + ] => { + if self_ty == target && matches!(mutbl, AutoBorrowMutability::Not) { + AdjustKind::None + } else { + AdjustKind::reborrow(mutbl) + } + }, + _ => return, + }; + let mut applicability = Applicability::MachineApplicable; let object = snippet_with_applicability(cx, self_arg.span, "_", &mut applicability); span_lint_and_sugg( @@ -23,7 +84,7 @@ pub(super) fn check(cx: &LateContext<'_>, self_arg: &Expr<'_>, call_expr: &Expr< "it is more concise to loop over containers instead of using explicit \ iteration methods", "to write this more concisely, try", - object.to_string(), + format!("{}{}", adjust.display(), object.to_string()), applicability, ); } diff --git a/clippy_lints/src/loops/explicit_iter_loop.rs b/clippy_lints/src/loops/explicit_iter_loop.rs index ba66af62375..621f0e0adca 100644 --- a/clippy_lints/src/loops/explicit_iter_loop.rs +++ b/clippy_lints/src/loops/explicit_iter_loop.rs @@ -1,58 +1,39 @@ use super::EXPLICIT_ITER_LOOP; use clippy_utils::diagnostics::span_lint_and_sugg; -use clippy_utils::is_trait_method; use clippy_utils::msrvs::{self, Msrv}; use clippy_utils::source::snippet_with_applicability; -use clippy_utils::ty::{implements_trait_with_env, make_normalized_projection_with_regions, normalize_with_regions, - make_normalized_projection, implements_trait, is_copy}; +use clippy_utils::ty::{ + implements_trait, implements_trait_with_env, is_copy, make_normalized_projection, + make_normalized_projection_with_regions, normalize_with_regions, +}; use rustc_errors::Applicability; use rustc_hir::{Expr, Mutability}; use rustc_lint::LateContext; use rustc_middle::ty::adjustment::{Adjust, Adjustment, AutoBorrow, AutoBorrowMutability}; -use rustc_middle::ty::{self, EarlyBinder, TypeAndMut, Ty}; +use rustc_middle::ty::{self, EarlyBinder, Ty, TypeAndMut}; use rustc_span::sym; -pub(super) fn check(cx: &LateContext<'_>, self_arg: &Expr<'_>, call_expr: &Expr<'_>, method_name: &str, msrv: &Msrv) { - let borrow_kind = match method_name { - "iter" | "iter_mut" => match is_ref_iterable(cx, self_arg, call_expr) { - Some((kind, ty)) => { - if let ty::Array(_, count) = *ty.peel_refs().kind() { - if !ty.is_ref() { - if !msrv.meets(msrvs::ARRAY_INTO_ITERATOR) { - return; - } - } else if count.try_eval_target_usize(cx.tcx, cx.param_env).map_or(true, |x| x > 32) - && !msrv.meets(msrvs::ARRAY_IMPL_ANY_LEN) - { - return - } - } - kind - }, - None => return, - }, - "into_iter" if is_trait_method(cx, call_expr, sym::IntoIterator) => { - let receiver_ty = cx.typeck_results().expr_ty(self_arg); - let receiver_ty_adjusted = cx.typeck_results().expr_ty_adjusted(self_arg); - let ref_receiver_ty = cx.tcx.mk_ref( - cx.tcx.lifetimes.re_erased, - ty::TypeAndMut { - ty: receiver_ty, - mutbl: Mutability::Not, - }, - ); - if receiver_ty_adjusted == ref_receiver_ty { - AdjustKind::None - } else { +pub(super) fn check(cx: &LateContext<'_>, self_arg: &Expr<'_>, call_expr: &Expr<'_>, msrv: &Msrv) { + let Some((adjust, ty)) = is_ref_iterable(cx, self_arg, call_expr) else { + return; + }; + if let ty::Array(_, count) = *ty.peel_refs().kind() { + if !ty.is_ref() { + if !msrv.meets(msrvs::ARRAY_INTO_ITERATOR) { return; } - }, - _ => return, - }; + } else if count + .try_eval_target_usize(cx.tcx, cx.param_env) + .map_or(true, |x| x > 32) + && !msrv.meets(msrvs::ARRAY_IMPL_ANY_LEN) + { + return; + } + } let mut applicability = Applicability::MachineApplicable; let object = snippet_with_applicability(cx, self_arg.span, "_", &mut applicability); - let prefix = match borrow_kind { + let prefix = match adjust { AdjustKind::None => "", AdjustKind::Borrow => "&", AdjustKind::BorrowMut => "&mut ", @@ -105,7 +86,11 @@ impl AdjustKind { /// Checks if an `iter` or `iter_mut` call returns `IntoIterator::IntoIter`. Returns how the /// argument needs to be adjusted. -fn is_ref_iterable<'tcx>(cx: &LateContext<'tcx>, self_arg: &Expr<'_>, call_expr: &Expr<'_>) -> Option<(AdjustKind, Ty<'tcx>)> { +fn is_ref_iterable<'tcx>( + cx: &LateContext<'tcx>, + self_arg: &Expr<'_>, + call_expr: &Expr<'_>, +) -> Option<(AdjustKind, Ty<'tcx>)> { let typeck = cx.typeck_results(); if let Some(trait_id) = cx.tcx.get_diagnostic_item(sym::IntoIterator) && let Some(fn_id) = typeck.type_dependent_def_id(call_expr.hir_id) @@ -158,10 +143,18 @@ fn is_ref_iterable<'tcx>(cx: &LateContext<'tcx>, self_arg: &Expr<'_>, call_expr: match adjustments { [] => Some((AdjustKind::None, self_ty)), - &[Adjustment { kind: Adjust::Deref(_), ..}, Adjustment { kind: Adjust::Borrow(AutoBorrow::Ref(_, mutbl)), target }, ..] => { + &[ + Adjustment { kind: Adjust::Deref(_), ..}, + Adjustment { + kind: Adjust::Borrow(AutoBorrow::Ref(_, mutbl)), + target, + }, + .. + ] => { if target != self_ty && implements_trait(cx, target, trait_id, &[]) - && let Some(ty) = make_normalized_projection(cx.tcx, cx.param_env, trait_id, sym!(IntoIter), [target]) + && let Some(ty) = + make_normalized_projection(cx.tcx, cx.param_env, trait_id, sym!(IntoIter), [target]) && ty == res_ty { Some((AdjustKind::reborrow(mutbl), target)) @@ -172,7 +165,8 @@ fn is_ref_iterable<'tcx>(cx: &LateContext<'tcx>, self_arg: &Expr<'_>, call_expr: &[Adjustment { kind: Adjust::Deref(_), target }, ..] => { if is_copy(cx, target) && implements_trait(cx, target, trait_id, &[]) - && let Some(ty) = make_normalized_projection(cx.tcx, cx.param_env, trait_id, sym!(IntoIter), [target]) + && let Some(ty) = + make_normalized_projection(cx.tcx, cx.param_env, trait_id, sym!(IntoIter), [target]) && ty == res_ty { Some((AdjustKind::Deref, target)) @@ -180,10 +174,17 @@ fn is_ref_iterable<'tcx>(cx: &LateContext<'tcx>, self_arg: &Expr<'_>, call_expr: None } } - &[Adjustment { kind: Adjust::Borrow(AutoBorrow::Ref(_, mutbl)), target }, ..] => { + &[ + Adjustment { + kind: Adjust::Borrow(AutoBorrow::Ref(_, mutbl)), + target, + }, + .. + ] => { if self_ty.is_ref() && implements_trait(cx, target, trait_id, &[]) - && let Some(ty) = make_normalized_projection(cx.tcx, cx.param_env, trait_id, sym!(IntoIter), [target]) + && let Some(ty) = + make_normalized_projection(cx.tcx, cx.param_env, trait_id, sym!(IntoIter), [target]) && ty == res_ty { Some((AdjustKind::auto_borrow(mutbl), target)) diff --git a/clippy_lints/src/loops/mod.rs b/clippy_lints/src/loops/mod.rs index 068166bdeb2..1231fefb180 100644 --- a/clippy_lints/src/loops/mod.rs +++ b/clippy_lints/src/loops/mod.rs @@ -715,14 +715,11 @@ impl Loops { fn check_for_loop_arg(&self, cx: &LateContext<'_>, _: &Pat<'_>, arg: &Expr<'_>) { if let ExprKind::MethodCall(method, self_arg, [], _) = arg.kind { - let method_name = method.ident.as_str(); - // check for looping over x.iter() or x.iter_mut(), could use &x or &mut x - match method_name { + match method.ident.as_str() { "iter" | "iter_mut" => { - explicit_iter_loop::check(cx, self_arg, arg, method_name, &self.msrv); + explicit_iter_loop::check(cx, self_arg, arg, &self.msrv); }, "into_iter" => { - explicit_iter_loop::check(cx, self_arg, arg, method_name, &self.msrv); explicit_into_iter_loop::check(cx, self_arg, arg); }, "next" => { diff --git a/tests/ui/explicit_into_iter_loop.fixed b/tests/ui/explicit_into_iter_loop.fixed index bc9ecb1e05a..dcef6340311 100644 --- a/tests/ui/explicit_into_iter_loop.fixed +++ b/tests/ui/explicit_into_iter_loop.fixed @@ -7,9 +7,7 @@ fn main() { where for<'a> &'a T: IntoIterator, { - for i in iterator { - println!("{}", i); - } + for _ in iterator {} } struct T; @@ -17,23 +15,39 @@ fn main() { type Item = (); type IntoIter = std::vec::IntoIter; fn into_iter(self) -> Self::IntoIter { - vec![].into_iter() + unimplemented!() } } - let t = T; + let mut t = T; + for _ in &t {} + let r = &t; - let rr = &&t; - - // This case is handled by `explicit_iter_loop`. No idea why. - for _ in t.into_iter() {} - for _ in r {} // No suggestion for this. // We'd have to suggest `for _ in *rr {}` which is less clear. + let rr = &&t; for _ in rr.into_iter() {} + let mr = &mut t; + for _ in &*mr {} + + struct U; + impl IntoIterator for &mut U { + type Item = (); + type IntoIter = std::vec::IntoIter; + fn into_iter(self) -> Self::IntoIter { + unimplemented!() + } + } + + let mut u = U; + for _ in &mut u {} + + let mr = &mut u; + for _ in &mut *mr {} + // Issue #6900 struct S; impl S { diff --git a/tests/ui/explicit_into_iter_loop.rs b/tests/ui/explicit_into_iter_loop.rs index 9b610fe3d11..bc048ed302b 100644 --- a/tests/ui/explicit_into_iter_loop.rs +++ b/tests/ui/explicit_into_iter_loop.rs @@ -7,9 +7,7 @@ fn main() { where for<'a> &'a T: IntoIterator, { - for i in iterator.into_iter() { - println!("{}", i); - } + for _ in iterator.into_iter() {} } struct T; @@ -17,23 +15,39 @@ fn main() { type Item = (); type IntoIter = std::vec::IntoIter; fn into_iter(self) -> Self::IntoIter { - vec![].into_iter() + unimplemented!() } } - let t = T; - let r = &t; - let rr = &&t; - - // This case is handled by `explicit_iter_loop`. No idea why. + let mut t = T; for _ in t.into_iter() {} + let r = &t; for _ in r.into_iter() {} // No suggestion for this. // We'd have to suggest `for _ in *rr {}` which is less clear. + let rr = &&t; for _ in rr.into_iter() {} + let mr = &mut t; + for _ in mr.into_iter() {} + + struct U; + impl IntoIterator for &mut U { + type Item = (); + type IntoIter = std::vec::IntoIter; + fn into_iter(self) -> Self::IntoIter { + unimplemented!() + } + } + + let mut u = U; + for _ in u.into_iter() {} + + let mr = &mut u; + for _ in mr.into_iter() {} + // Issue #6900 struct S; impl S { diff --git a/tests/ui/explicit_into_iter_loop.stderr b/tests/ui/explicit_into_iter_loop.stderr index 1bd2b38a0e7..fa89b884fa0 100644 --- a/tests/ui/explicit_into_iter_loop.stderr +++ b/tests/ui/explicit_into_iter_loop.stderr @@ -1,16 +1,40 @@ error: it is more concise to loop over containers instead of using explicit iteration methods --> $DIR/explicit_into_iter_loop.rs:10:18 | -LL | for i in iterator.into_iter() { +LL | for _ in iterator.into_iter() {} | ^^^^^^^^^^^^^^^^^^^^ help: to write this more concisely, try: `iterator` | = note: `-D clippy::explicit-into-iter-loop` implied by `-D warnings` error: it is more concise to loop over containers instead of using explicit iteration methods - --> $DIR/explicit_into_iter_loop.rs:31:14 + --> $DIR/explicit_into_iter_loop.rs:23:14 + | +LL | for _ in t.into_iter() {} + | ^^^^^^^^^^^^^ help: to write this more concisely, try: `&t` + +error: it is more concise to loop over containers instead of using explicit iteration methods + --> $DIR/explicit_into_iter_loop.rs:26:14 | LL | for _ in r.into_iter() {} | ^^^^^^^^^^^^^ help: to write this more concisely, try: `r` -error: aborting due to 2 previous errors +error: it is more concise to loop over containers instead of using explicit iteration methods + --> $DIR/explicit_into_iter_loop.rs:34:14 + | +LL | for _ in mr.into_iter() {} + | ^^^^^^^^^^^^^^ help: to write this more concisely, try: `&*mr` + +error: it is more concise to loop over containers instead of using explicit iteration methods + --> $DIR/explicit_into_iter_loop.rs:46:14 + | +LL | for _ in u.into_iter() {} + | ^^^^^^^^^^^^^ help: to write this more concisely, try: `&mut u` + +error: it is more concise to loop over containers instead of using explicit iteration methods + --> $DIR/explicit_into_iter_loop.rs:49:14 + | +LL | for _ in mr.into_iter() {} + | ^^^^^^^^^^^^^^ help: to write this more concisely, try: `&mut *mr` + +error: aborting due to 6 previous errors From 949712c90ac2af616fc4e72777c78c2948d3146a Mon Sep 17 00:00:00 2001 From: Jason Newcomb Date: Mon, 27 Feb 2023 13:53:53 -0500 Subject: [PATCH 122/310] Reborrow mutable references in `explicit_iter_loop` --- clippy_lints/src/attrs.rs | 4 +- clippy_lints/src/default_numeric_fallback.rs | 2 +- clippy_lints/src/lifetimes.rs | 2 +- .../src/loops/explicit_into_iter_loop.rs | 2 +- clippy_lints/src/loops/explicit_iter_loop.rs | 77 ++++++++++++++----- clippy_lints/src/loops/mod.rs | 2 + clippy_lints/src/loops/same_item_push.rs | 2 +- clippy_lints/src/macro_use.rs | 2 +- .../src/matches/match_wild_err_arm.rs | 2 +- .../matches/significant_drop_in_scrutinee.rs | 2 +- clippy_lints/src/matches/try_err.rs | 2 +- .../src/misc_early/mixed_case_hex_literals.rs | 2 +- .../src/mismatching_type_param_order.rs | 2 +- clippy_lints/src/returns.rs | 2 +- .../src/significant_drop_tightening.rs | 2 +- clippy_lints/src/trait_bounds.rs | 4 +- .../interning_defined_symbol.rs | 2 +- clippy_utils/src/qualify_min_const_fn.rs | 4 +- clippy_utils/src/ty.rs | 2 +- clippy_utils/src/usage.rs | 2 +- lintcheck/src/main.rs | 2 +- tests/ui/explicit_iter_loop.fixed | 14 ++++ tests/ui/explicit_iter_loop.rs | 14 ++++ tests/ui/explicit_iter_loop.stderr | 66 ++++++++++++---- 24 files changed, 159 insertions(+), 58 deletions(-) diff --git a/clippy_lints/src/attrs.rs b/clippy_lints/src/attrs.rs index 89540703bcf..2ba78f99569 100644 --- a/clippy_lints/src/attrs.rs +++ b/clippy_lints/src/attrs.rs @@ -808,7 +808,7 @@ fn check_deprecated_cfg_attr(cx: &EarlyContext<'_>, attr: &Attribute, msrv: &Msr } fn check_nested_cfg(cx: &EarlyContext<'_>, items: &[NestedMetaItem]) { - for item in items.iter() { + for item in items { if let NestedMetaItem::MetaItem(meta) = item { if !meta.has_name(sym::any) && !meta.has_name(sym::all) { continue; @@ -842,7 +842,7 @@ fn check_nested_cfg(cx: &EarlyContext<'_>, items: &[NestedMetaItem]) { } fn check_nested_misused_cfg(cx: &EarlyContext<'_>, items: &[NestedMetaItem]) { - for item in items.iter() { + for item in items { if let NestedMetaItem::MetaItem(meta) = item { if meta.has_name(sym!(features)) && let Some(val) = meta.value_str() { span_lint_and_sugg( diff --git a/clippy_lints/src/default_numeric_fallback.rs b/clippy_lints/src/default_numeric_fallback.rs index 4e1a6cd4d73..e53a9877b20 100644 --- a/clippy_lints/src/default_numeric_fallback.rs +++ b/clippy_lints/src/default_numeric_fallback.rs @@ -161,7 +161,7 @@ impl<'a, 'tcx> Visitor<'tcx> for NumericFallbackVisitor<'a, 'tcx> { let fields_def = &variant.fields; // Push field type then visit each field expr. - for field in fields.iter() { + for field in *fields { let bound = fields_def .iter() diff --git a/clippy_lints/src/lifetimes.rs b/clippy_lints/src/lifetimes.rs index 986ffcad883..7bc901e4e7f 100644 --- a/clippy_lints/src/lifetimes.rs +++ b/clippy_lints/src/lifetimes.rs @@ -562,7 +562,7 @@ fn has_where_lifetimes<'tcx>(cx: &LateContext<'tcx>, generics: &'tcx Generics<'_ // if the bounds define new lifetimes, they are fine to occur let allowed_lts = allowed_lts_from(pred.bound_generic_params); // now walk the bounds - for bound in pred.bounds.iter() { + for bound in pred.bounds { walk_param_bound(&mut visitor, bound); } // and check that all lifetimes are allowed diff --git a/clippy_lints/src/loops/explicit_into_iter_loop.rs b/clippy_lints/src/loops/explicit_into_iter_loop.rs index bf5e018ce92..93d6b808646 100644 --- a/clippy_lints/src/loops/explicit_into_iter_loop.rs +++ b/clippy_lints/src/loops/explicit_into_iter_loop.rs @@ -84,7 +84,7 @@ pub(super) fn check(cx: &LateContext<'_>, self_arg: &Expr<'_>, call_expr: &Expr< "it is more concise to loop over containers instead of using explicit \ iteration methods", "to write this more concisely, try", - format!("{}{}", adjust.display(), object.to_string()), + format!("{}{object}", adjust.display()), applicability, ); } diff --git a/clippy_lints/src/loops/explicit_iter_loop.rs b/clippy_lints/src/loops/explicit_iter_loop.rs index 621f0e0adca..f3347e33077 100644 --- a/clippy_lints/src/loops/explicit_iter_loop.rs +++ b/clippy_lints/src/loops/explicit_iter_loop.rs @@ -33,14 +33,6 @@ pub(super) fn check(cx: &LateContext<'_>, self_arg: &Expr<'_>, call_expr: &Expr< let mut applicability = Applicability::MachineApplicable; let object = snippet_with_applicability(cx, self_arg.span, "_", &mut applicability); - let prefix = match adjust { - AdjustKind::None => "", - AdjustKind::Borrow => "&", - AdjustKind::BorrowMut => "&mut ", - AdjustKind::Deref => "*", - AdjustKind::Reborrow => "&*", - AdjustKind::ReborrowMut => "&mut *", - }; span_lint_and_sugg( cx, EXPLICIT_ITER_LOOP, @@ -48,11 +40,12 @@ pub(super) fn check(cx: &LateContext<'_>, self_arg: &Expr<'_>, call_expr: &Expr< "it is more concise to loop over references to containers instead of using explicit \ iteration methods", "to write this more concisely, try", - format!("{prefix}{object}"), + format!("{}{object}", adjust.display()), applicability, ); } +#[derive(Clone, Copy)] enum AdjustKind { None, Borrow, @@ -76,16 +69,35 @@ impl AdjustKind { } } - fn reborrow(mutbl: AutoBorrowMutability) -> Self { + fn reborrow(mutbl: Mutability) -> Self { + match mutbl { + Mutability::Not => Self::Reborrow, + Mutability::Mut => Self::ReborrowMut, + } + } + + fn auto_reborrow(mutbl: AutoBorrowMutability) -> Self { match mutbl { AutoBorrowMutability::Not => Self::Reborrow, AutoBorrowMutability::Mut { .. } => Self::ReborrowMut, } } + + fn display(self) -> &'static str { + match self { + Self::None => "", + Self::Borrow => "&", + Self::BorrowMut => "&mut ", + Self::Deref => "*", + Self::Reborrow => "&*", + Self::ReborrowMut => "&mut *", + } + } } /// Checks if an `iter` or `iter_mut` call returns `IntoIterator::IntoIter`. Returns how the /// argument needs to be adjusted. +#[expect(clippy::too_many_lines)] fn is_ref_iterable<'tcx>( cx: &LateContext<'tcx>, self_arg: &Expr<'_>, @@ -108,27 +120,50 @@ fn is_ref_iterable<'tcx>( let self_is_copy = is_copy(cx, self_ty); if adjustments.is_empty() && self_is_copy { + // Exact type match, already checked earlier return Some((AdjustKind::None, self_ty)); } - let res_ty = cx.tcx.erase_regions(EarlyBinder::bind(req_res_ty).subst(cx.tcx, typeck.node_substs(call_expr.hir_id))); - if !adjustments.is_empty() && self_is_copy { - if implements_trait(cx, self_ty, trait_id, &[]) - && let Some(ty) = make_normalized_projection(cx.tcx, cx.param_env, trait_id, sym!(IntoIter), [self_ty]) - && ty == res_ty - { - return Some((AdjustKind::None, self_ty)); - } - } - + let res_ty = cx.tcx.erase_regions(EarlyBinder::bind(req_res_ty) + .subst(cx.tcx, typeck.node_substs(call_expr.hir_id))); let mutbl = if let ty::Ref(_, _, mutbl) = *req_self_ty.kind() { Some(mutbl) } else { None }; + + if !adjustments.is_empty() { + if self_is_copy { + // Using by value won't consume anything + if implements_trait(cx, self_ty, trait_id, &[]) + && let Some(ty) = + make_normalized_projection(cx.tcx, cx.param_env, trait_id, sym!(IntoIter), [self_ty]) + && ty == res_ty + { + return Some((AdjustKind::None, self_ty)); + } + } else if let ty::Ref(region, ty, Mutability::Mut) = *self_ty.kind() + && let Some(mutbl) = mutbl + { + // Attempt to reborrow the mutable reference + let self_ty = if mutbl.is_mut() { + self_ty + } else { + cx.tcx.mk_ref(region, TypeAndMut { ty, mutbl }) + }; + if implements_trait(cx, self_ty, trait_id, &[]) + && let Some(ty) = + make_normalized_projection(cx.tcx, cx.param_env, trait_id, sym!(IntoIter), [self_ty]) + && ty == res_ty + { + return Some((AdjustKind::reborrow(mutbl), self_ty)); + } + } + } if let Some(mutbl) = mutbl && !self_ty.is_ref() { + // Attempt to borrow let self_ty = cx.tcx.mk_ref(cx.tcx.lifetimes.re_erased, TypeAndMut { ty: self_ty, mutbl, @@ -157,7 +192,7 @@ fn is_ref_iterable<'tcx>( make_normalized_projection(cx.tcx, cx.param_env, trait_id, sym!(IntoIter), [target]) && ty == res_ty { - Some((AdjustKind::reborrow(mutbl), target)) + Some((AdjustKind::auto_reborrow(mutbl), target)) } else { None } diff --git a/clippy_lints/src/loops/mod.rs b/clippy_lints/src/loops/mod.rs index 1231fefb180..529189b52ac 100644 --- a/clippy_lints/src/loops/mod.rs +++ b/clippy_lints/src/loops/mod.rs @@ -687,6 +687,8 @@ impl<'tcx> LateLintPass<'tcx> for Loops { manual_while_let_some::check(cx, condition, body, span); } } + + extract_msrv_attr!(LateContext); } impl Loops { diff --git a/clippy_lints/src/loops/same_item_push.rs b/clippy_lints/src/loops/same_item_push.rs index 9d9341559ac..f7b3b2358a0 100644 --- a/clippy_lints/src/loops/same_item_push.rs +++ b/clippy_lints/src/loops/same_item_push.rs @@ -148,7 +148,7 @@ impl<'a, 'tcx> Visitor<'tcx> for SameItemPushVisitor<'a, 'tcx> { } fn visit_block(&mut self, b: &'tcx Block<'_>) { - for stmt in b.stmts.iter() { + for stmt in b.stmts { self.visit_stmt(stmt); } } diff --git a/clippy_lints/src/macro_use.rs b/clippy_lints/src/macro_use.rs index 26ae4b409c7..cb3bda96133 100644 --- a/clippy_lints/src/macro_use.rs +++ b/clippy_lints/src/macro_use.rs @@ -101,7 +101,7 @@ impl<'tcx> LateLintPass<'tcx> for MacroUseImports { }); if !id.is_local(); then { - for kid in cx.tcx.module_children(id).iter() { + for kid in cx.tcx.module_children(id) { if let Res::Def(DefKind::Macro(_mac_type), mac_id) = kid.res { let span = mac_attr.span; let def_path = cx.tcx.def_path_str(mac_id); diff --git a/clippy_lints/src/matches/match_wild_err_arm.rs b/clippy_lints/src/matches/match_wild_err_arm.rs index 6424ac31d9f..de911f7a028 100644 --- a/clippy_lints/src/matches/match_wild_err_arm.rs +++ b/clippy_lints/src/matches/match_wild_err_arm.rs @@ -25,7 +25,7 @@ pub(crate) fn check<'tcx>(cx: &LateContext<'tcx>, ex: &Expr<'tcx>, arms: &[Arm<' let mut ident_bind_name = kw::Underscore; if !matching_wild { // Looking for unused bindings (i.e.: `_e`) - for pat in inner.iter() { + for pat in inner { if let PatKind::Binding(_, id, ident, None) = pat.kind { if ident.as_str().starts_with('_') && !is_local_used(cx, arm.body, id) { ident_bind_name = ident.name; diff --git a/clippy_lints/src/matches/significant_drop_in_scrutinee.rs b/clippy_lints/src/matches/significant_drop_in_scrutinee.rs index 7945275393c..da02de3e667 100644 --- a/clippy_lints/src/matches/significant_drop_in_scrutinee.rs +++ b/clippy_lints/src/matches/significant_drop_in_scrutinee.rs @@ -140,7 +140,7 @@ impl<'a, 'tcx> SigDropChecker<'a, 'tcx> { } } - for generic_arg in b.iter() { + for generic_arg in *b { if let GenericArgKind::Type(ty) = generic_arg.unpack() { if self.has_sig_drop_attr(cx, ty) { return true; diff --git a/clippy_lints/src/matches/try_err.rs b/clippy_lints/src/matches/try_err.rs index 704c34c32bf..3a7f1e034f3 100644 --- a/clippy_lints/src/matches/try_err.rs +++ b/clippy_lints/src/matches/try_err.rs @@ -81,7 +81,7 @@ pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>, scrutine /// Finds function return type by examining return expressions in match arms. fn find_return_type<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx ExprKind<'_>) -> Option> { if let ExprKind::Match(_, arms, MatchSource::TryDesugar) = expr { - for arm in arms.iter() { + for arm in *arms { if let ExprKind::Ret(Some(ret)) = arm.body.kind { return Some(cx.typeck_results().expr_ty(ret)); } diff --git a/clippy_lints/src/misc_early/mixed_case_hex_literals.rs b/clippy_lints/src/misc_early/mixed_case_hex_literals.rs index ddb8b9173a5..9151cc63320 100644 --- a/clippy_lints/src/misc_early/mixed_case_hex_literals.rs +++ b/clippy_lints/src/misc_early/mixed_case_hex_literals.rs @@ -13,7 +13,7 @@ pub(super) fn check(cx: &EarlyContext<'_>, lit_span: Span, suffix: &str, lit_sni return; } let mut seen = (false, false); - for ch in lit_snip.as_bytes()[2..=maybe_last_sep_idx].iter() { + for ch in &lit_snip.as_bytes()[2..=maybe_last_sep_idx] { match ch { b'a'..=b'f' => seen.0 = true, b'A'..=b'F' => seen.1 = true, diff --git a/clippy_lints/src/mismatching_type_param_order.rs b/clippy_lints/src/mismatching_type_param_order.rs index 9de4b56b77b..28e041dee0d 100644 --- a/clippy_lints/src/mismatching_type_param_order.rs +++ b/clippy_lints/src/mismatching_type_param_order.rs @@ -59,7 +59,7 @@ impl<'tcx> LateLintPass<'tcx> for TypeParamMismatch { then { // get the name and span of the generic parameters in the Impl let mut impl_params = Vec::new(); - for p in generic_args.args.iter() { + for p in generic_args.args { match p { GenericArg::Type(Ty {kind: TyKind::Path(QPath::Resolved(_, path)), ..}) => impl_params.push((path.segments[0].ident.to_string(), path.span)), diff --git a/clippy_lints/src/returns.rs b/clippy_lints/src/returns.rs index b5686e390ad..958351ad81b 100644 --- a/clippy_lints/src/returns.rs +++ b/clippy_lints/src/returns.rs @@ -292,7 +292,7 @@ fn check_final_expr<'tcx>( // (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() { + for arm in *arms { check_final_expr(cx, arm.body, semi_spans.clone(), RetReplacement::Unit, Some(match_ty)); } }, diff --git a/clippy_lints/src/significant_drop_tightening.rs b/clippy_lints/src/significant_drop_tightening.rs index b930b2c8dd7..f4e56489b09 100644 --- a/clippy_lints/src/significant_drop_tightening.rs +++ b/clippy_lints/src/significant_drop_tightening.rs @@ -333,7 +333,7 @@ impl<'cx, 'sdt, 'tcx> SigDropChecker<'cx, 'sdt, 'tcx> { return true; } } - for generic_arg in b.iter() { + for generic_arg in *b { if let GenericArgKind::Type(ty) = generic_arg.unpack() { if self.has_sig_drop_attr(ty) { return true; diff --git a/clippy_lints/src/trait_bounds.rs b/clippy_lints/src/trait_bounds.rs index 4ccda15068b..0dab0126e6c 100644 --- a/clippy_lints/src/trait_bounds.rs +++ b/clippy_lints/src/trait_bounds.rs @@ -139,7 +139,7 @@ impl<'tcx> LateLintPass<'tcx> for TraitBounds { ) = cx.tcx.hir().get_if_local(*def_id); then { if self_bounds_map.is_empty() { - for bound in self_bounds.iter() { + for bound in *self_bounds { let Some((self_res, self_segments, _)) = get_trait_info_from_bound(bound) else { continue }; self_bounds_map.insert(self_res, self_segments); } @@ -184,7 +184,7 @@ impl<'tcx> LateLintPass<'tcx> for TraitBounds { // Iterate the bounds and add them to our seen hash // If we haven't yet seen it, add it to the fixed traits - for bound in bounds.iter() { + for bound in bounds { let Some(def_id) = bound.trait_ref.trait_def_id() else { continue; }; let new_trait = seen_def_ids.insert(def_id); diff --git a/clippy_lints/src/utils/internal_lints/interning_defined_symbol.rs b/clippy_lints/src/utils/internal_lints/interning_defined_symbol.rs index f8978e30a8e..dced9fcf9ab 100644 --- a/clippy_lints/src/utils/internal_lints/interning_defined_symbol.rs +++ b/clippy_lints/src/utils/internal_lints/interning_defined_symbol.rs @@ -75,7 +75,7 @@ impl<'tcx> LateLintPass<'tcx> for InterningDefinedSymbol { for &module in &[&paths::KW_MODULE, &paths::SYM_MODULE] { for def_id in def_path_def_ids(cx, module) { - for item in cx.tcx.module_children(def_id).iter() { + for item in cx.tcx.module_children(def_id) { if_chain! { if let Res::Def(DefKind::Const, item_def_id) = item.res; let ty = cx.tcx.type_of(item_def_id).subst_identity(); diff --git a/clippy_utils/src/qualify_min_const_fn.rs b/clippy_utils/src/qualify_min_const_fn.rs index c0d2c835d63..67369288b70 100644 --- a/clippy_utils/src/qualify_min_const_fn.rs +++ b/clippy_utils/src/qualify_min_const_fn.rs @@ -61,7 +61,7 @@ pub fn is_min_const_fn<'tcx>(tcx: TyCtxt<'tcx>, body: &Body<'tcx>, msrv: &Msrv) body.local_decls.iter().next().unwrap().source_info.span, )?; - for bb in body.basic_blocks.iter() { + for bb in &*body.basic_blocks { check_terminator(tcx, body, bb.terminator(), msrv)?; for stmt in &bb.statements { check_statement(tcx, body, def_id, stmt)?; @@ -89,7 +89,7 @@ fn check_ty<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>, span: Span) -> McfResult { return Err((span, "function pointers in const fn are unstable".into())); }, ty::Dynamic(preds, _, _) => { - for pred in preds.iter() { + for pred in *preds { match pred.skip_binder() { ty::ExistentialPredicate::AutoTrait(_) | ty::ExistentialPredicate::Projection(_) => { return Err(( diff --git a/clippy_utils/src/ty.rs b/clippy_utils/src/ty.rs index 78b14dc7abb..4132a6c4b18 100644 --- a/clippy_utils/src/ty.rs +++ b/clippy_utils/src/ty.rs @@ -277,7 +277,7 @@ pub fn is_must_use_ty<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>) -> bool { false }, ty::Dynamic(binder, _, _) => { - for predicate in binder.iter() { + for predicate in *binder { if let ty::ExistentialPredicate::Trait(ref trait_ref) = predicate.skip_binder() { if cx.tcx.has_attr(trait_ref.def_id, sym::must_use) { return true; diff --git a/clippy_utils/src/usage.rs b/clippy_utils/src/usage.rs index ab3976a13bd..9855085216f 100644 --- a/clippy_utils/src/usage.rs +++ b/clippy_utils/src/usage.rs @@ -82,7 +82,7 @@ pub struct ParamBindingIdCollector { impl<'tcx> ParamBindingIdCollector { fn collect_binding_hir_ids(body: &'tcx hir::Body<'tcx>) -> Vec { let mut hir_ids: Vec = Vec::new(); - for param in body.params.iter() { + for param in body.params { let mut finder = ParamBindingIdCollector { binding_hir_ids: Vec::new(), }; diff --git a/lintcheck/src/main.rs b/lintcheck/src/main.rs index 03d1877d6c6..de56a6f8275 100644 --- a/lintcheck/src/main.rs +++ b/lintcheck/src/main.rs @@ -474,7 +474,7 @@ fn read_crates(toml_path: &Path) -> (Vec, RecursiveOptions) { }); } else if let Some(ref versions) = tk.versions { // if we have multiple versions, save each one - for ver in versions.iter() { + for ver in versions { crate_sources.push(CrateSource::CratesIo { name: tk.name.clone(), version: ver.to_string(), diff --git a/tests/ui/explicit_iter_loop.fixed b/tests/ui/explicit_iter_loop.fixed index b0de50ed928..746ef813c04 100644 --- a/tests/ui/explicit_iter_loop.fixed +++ b/tests/ui/explicit_iter_loop.fixed @@ -17,6 +17,13 @@ fn main() { for _ in &vec {} for _ in &mut vec {} + let rvec = &vec; + for _ in rvec {} + + let rmvec = &mut vec; + for _ in &*rmvec {} + for _ in &mut *rmvec {} + for _ in &vec {} // these are fine for _ in &mut vec {} // these are fine @@ -29,9 +36,13 @@ fn main() { let ll: LinkedList<()> = LinkedList::new(); for _ in &ll {} + let rll = ≪ + for _ in rll {} let vd: VecDeque<()> = VecDeque::new(); for _ in &vd {} + let rvd = &vd; + for _ in rvd {} let bh: BinaryHeap<()> = BinaryHeap::new(); for _ in &bh {} @@ -137,4 +148,7 @@ fn main() { let mut x = CustomType; for _ in &x {} for _ in &mut x {} + + let r = &x; + for _ in r {} } diff --git a/tests/ui/explicit_iter_loop.rs b/tests/ui/explicit_iter_loop.rs index 33d3bada6e2..fba230ee0ee 100644 --- a/tests/ui/explicit_iter_loop.rs +++ b/tests/ui/explicit_iter_loop.rs @@ -17,6 +17,13 @@ fn main() { for _ in vec.iter() {} for _ in vec.iter_mut() {} + let rvec = &vec; + for _ in rvec.iter() {} + + let rmvec = &mut vec; + for _ in rmvec.iter() {} + for _ in rmvec.iter_mut() {} + for _ in &vec {} // these are fine for _ in &mut vec {} // these are fine @@ -29,9 +36,13 @@ fn main() { let ll: LinkedList<()> = LinkedList::new(); for _ in ll.iter() {} + let rll = ≪ + for _ in rll.iter() {} let vd: VecDeque<()> = VecDeque::new(); for _ in vd.iter() {} + let rvd = &vd; + for _ in rvd.iter() {} let bh: BinaryHeap<()> = BinaryHeap::new(); for _ in bh.iter() {} @@ -137,4 +148,7 @@ fn main() { let mut x = CustomType; for _ in x.iter() {} for _ in x.iter_mut() {} + + let r = &x; + for _ in r.iter() {} } diff --git a/tests/ui/explicit_iter_loop.stderr b/tests/ui/explicit_iter_loop.stderr index 1508080a243..94a264dcea8 100644 --- a/tests/ui/explicit_iter_loop.stderr +++ b/tests/ui/explicit_iter_loop.stderr @@ -17,19 +17,37 @@ LL | for _ in vec.iter_mut() {} | ^^^^^^^^^^^^^^ help: to write this more concisely, try: `&mut vec` error: it is more concise to loop over references to containers instead of using explicit iteration methods - --> $DIR/explicit_iter_loop.rs:23:14 + --> $DIR/explicit_iter_loop.rs:21:14 + | +LL | for _ in rvec.iter() {} + | ^^^^^^^^^^^ help: to write this more concisely, try: `rvec` + +error: it is more concise to loop over references to containers instead of using explicit iteration methods + --> $DIR/explicit_iter_loop.rs:24:14 + | +LL | for _ in rmvec.iter() {} + | ^^^^^^^^^^^^ help: to write this more concisely, try: `&*rmvec` + +error: it is more concise to loop over references to containers instead of using explicit iteration methods + --> $DIR/explicit_iter_loop.rs:25:14 + | +LL | for _ in rmvec.iter_mut() {} + | ^^^^^^^^^^^^^^^^ help: to write this more concisely, try: `&mut *rmvec` + +error: it is more concise to loop over references to containers instead of using explicit iteration methods + --> $DIR/explicit_iter_loop.rs:30:14 | LL | for _ in [1, 2, 3].iter() {} | ^^^^^^^^^^^^^^^^ help: to write this more concisely, try: `&[1, 2, 3]` error: it is more concise to loop over references to containers instead of using explicit iteration methods - --> $DIR/explicit_iter_loop.rs:25:14 + --> $DIR/explicit_iter_loop.rs:32:14 | LL | for _ in (&mut [1, 2, 3]).iter() {} | ^^^^^^^^^^^^^^^^^^^^^^^ help: to write this more concisely, try: `&*(&mut [1, 2, 3])` error: the method `iter` doesn't need a mutable reference - --> $DIR/explicit_iter_loop.rs:25:14 + --> $DIR/explicit_iter_loop.rs:32:14 | LL | for _ in (&mut [1, 2, 3]).iter() {} | ^^^^^^^^^^^^^^^^ @@ -37,70 +55,88 @@ LL | for _ in (&mut [1, 2, 3]).iter() {} = note: `-D clippy::unnecessary-mut-passed` implied by `-D warnings` error: it is more concise to loop over references to containers instead of using explicit iteration methods - --> $DIR/explicit_iter_loop.rs:27:14 + --> $DIR/explicit_iter_loop.rs:34:14 | LL | for _ in [0; 32].iter() {} | ^^^^^^^^^^^^^^ help: to write this more concisely, try: `&[0; 32]` error: it is more concise to loop over references to containers instead of using explicit iteration methods - --> $DIR/explicit_iter_loop.rs:28:14 + --> $DIR/explicit_iter_loop.rs:35:14 | LL | for _ in [0; 33].iter() {} | ^^^^^^^^^^^^^^ help: to write this more concisely, try: `&[0; 33]` error: it is more concise to loop over references to containers instead of using explicit iteration methods - --> $DIR/explicit_iter_loop.rs:31:14 + --> $DIR/explicit_iter_loop.rs:38:14 | LL | for _ in ll.iter() {} | ^^^^^^^^^ help: to write this more concisely, try: `&ll` error: it is more concise to loop over references to containers instead of using explicit iteration methods - --> $DIR/explicit_iter_loop.rs:34:14 + --> $DIR/explicit_iter_loop.rs:40:14 + | +LL | for _ in rll.iter() {} + | ^^^^^^^^^^ help: to write this more concisely, try: `rll` + +error: it is more concise to loop over references to containers instead of using explicit iteration methods + --> $DIR/explicit_iter_loop.rs:43:14 | LL | for _ in vd.iter() {} | ^^^^^^^^^ help: to write this more concisely, try: `&vd` error: it is more concise to loop over references to containers instead of using explicit iteration methods - --> $DIR/explicit_iter_loop.rs:37:14 + --> $DIR/explicit_iter_loop.rs:45:14 + | +LL | for _ in rvd.iter() {} + | ^^^^^^^^^^ help: to write this more concisely, try: `rvd` + +error: it is more concise to loop over references to containers instead of using explicit iteration methods + --> $DIR/explicit_iter_loop.rs:48:14 | LL | for _ in bh.iter() {} | ^^^^^^^^^ help: to write this more concisely, try: `&bh` error: it is more concise to loop over references to containers instead of using explicit iteration methods - --> $DIR/explicit_iter_loop.rs:40:14 + --> $DIR/explicit_iter_loop.rs:51:14 | LL | for _ in hm.iter() {} | ^^^^^^^^^ help: to write this more concisely, try: `&hm` error: it is more concise to loop over references to containers instead of using explicit iteration methods - --> $DIR/explicit_iter_loop.rs:43:14 + --> $DIR/explicit_iter_loop.rs:54:14 | LL | for _ in bt.iter() {} | ^^^^^^^^^ help: to write this more concisely, try: `&bt` error: it is more concise to loop over references to containers instead of using explicit iteration methods - --> $DIR/explicit_iter_loop.rs:46:14 + --> $DIR/explicit_iter_loop.rs:57:14 | LL | for _ in hs.iter() {} | ^^^^^^^^^ help: to write this more concisely, try: `&hs` error: it is more concise to loop over references to containers instead of using explicit iteration methods - --> $DIR/explicit_iter_loop.rs:49:14 + --> $DIR/explicit_iter_loop.rs:60:14 | LL | for _ in bs.iter() {} | ^^^^^^^^^ help: to write this more concisely, try: `&bs` error: it is more concise to loop over references to containers instead of using explicit iteration methods - --> $DIR/explicit_iter_loop.rs:138:14 + --> $DIR/explicit_iter_loop.rs:149:14 | LL | for _ in x.iter() {} | ^^^^^^^^ help: to write this more concisely, try: `&x` error: it is more concise to loop over references to containers instead of using explicit iteration methods - --> $DIR/explicit_iter_loop.rs:139:14 + --> $DIR/explicit_iter_loop.rs:150:14 | LL | for _ in x.iter_mut() {} | ^^^^^^^^^^^^ help: to write this more concisely, try: `&mut x` -error: aborting due to 16 previous errors +error: it is more concise to loop over references to containers instead of using explicit iteration methods + --> $DIR/explicit_iter_loop.rs:153:14 + | +LL | for _ in r.iter() {} + | ^^^^^^^^ help: to write this more concisely, try: `r` + +error: aborting due to 22 previous errors From a495fa06de1e806ae156f618b25139a74815d5a3 Mon Sep 17 00:00:00 2001 From: Centri3 <114838443+Centri3@users.noreply.github.com> Date: Fri, 9 Jun 2023 01:24:41 -0500 Subject: [PATCH 123/310] remove unnecessary checks --- clippy_utils/src/qualify_min_const_fn.rs | 22 +++++++++++++--------- 1 file changed, 13 insertions(+), 9 deletions(-) diff --git a/clippy_utils/src/qualify_min_const_fn.rs b/clippy_utils/src/qualify_min_const_fn.rs index 799b6ffeba6..3dbda478b2f 100644 --- a/clippy_utils/src/qualify_min_const_fn.rs +++ b/clippy_utils/src/qualify_min_const_fn.rs @@ -275,17 +275,21 @@ fn check_operand<'tcx>(tcx: TyCtxt<'tcx>, operand: &Operand<'tcx>, span: Span, b fn check_place<'tcx>(tcx: TyCtxt<'tcx>, place: Place<'tcx>, span: Span, body: &Body<'tcx>, in_move: bool) -> McfResult { let mut cursor = place.projection.as_ref(); + if let [proj_base] = cursor + && let ProjectionElem::Field(_, ty) = proj_base + && !is_ty_const_destruct(tcx, *ty, body) + && in_move + { + return Err(( + span, + "cannot drop locals with a non constant destructor in const fn".into(), + )); + } + while let [ref proj_base @ .., elem] = *cursor { cursor = proj_base; match elem { - ProjectionElem::Field(_, ty) => { - if !is_ty_const_destruct(tcx, ty, body) && in_move { - return Err(( - span, - "cannot drop locals with a non constant destructor in const fn".into(), - )); - } - + ProjectionElem::Field(..) => { let base_ty = Place::ty_from(place.local, proj_base, body, tcx).ty; if let Some(def) = base_ty.ty_adt_def() { // No union field accesses in `const fn` @@ -328,7 +332,7 @@ fn check_terminator<'tcx>( "cannot drop locals with a non constant destructor in const fn".into(), )); } - check_place(tcx, *place, span, body, false) + Ok(()) }, TerminatorKind::SwitchInt { discr, targets: _ } => check_operand(tcx, discr, span, body), TerminatorKind::GeneratorDrop | TerminatorKind::Yield { .. } => { From edb3266b91a38722f65579882238b85da5874c24 Mon Sep 17 00:00:00 2001 From: Urgau Date: Sun, 21 May 2023 12:12:12 +0200 Subject: [PATCH 124/310] Drop uplifted `clippy:cmp_nan` --- clippy_lints/src/declared_lints.rs | 1 - clippy_lints/src/operators/cmp_nan.rs | 30 ------ clippy_lints/src/operators/mod.rs | 28 ----- clippy_lints/src/renamed_lints.rs | 1 + tests/ui/cmp_nan.rs | 34 ------ tests/ui/cmp_nan.stderr | 148 -------------------------- tests/ui/crashes/mut_mut_macro.rs | 5 +- tests/ui/rename.fixed | 2 + tests/ui/rename.rs | 2 + tests/ui/rename.stderr | 110 ++++++++++--------- tests/ui/unknown_clippy_lints.fixed | 2 +- tests/ui/unknown_clippy_lints.rs | 2 +- tests/ui/unknown_clippy_lints.stderr | 6 +- 13 files changed, 70 insertions(+), 301 deletions(-) delete mode 100644 clippy_lints/src/operators/cmp_nan.rs delete mode 100644 tests/ui/cmp_nan.rs delete mode 100644 tests/ui/cmp_nan.stderr diff --git a/clippy_lints/src/declared_lints.rs b/clippy_lints/src/declared_lints.rs index 6270d261313..f1d1355123a 100644 --- a/clippy_lints/src/declared_lints.rs +++ b/clippy_lints/src/declared_lints.rs @@ -476,7 +476,6 @@ pub(crate) static LINTS: &[&crate::LintInfo] = &[ crate::operators::ARITHMETIC_SIDE_EFFECTS_INFO, crate::operators::ASSIGN_OP_PATTERN_INFO, crate::operators::BAD_BIT_MASK_INFO, - crate::operators::CMP_NAN_INFO, crate::operators::CMP_OWNED_INFO, crate::operators::DOUBLE_COMPARISONS_INFO, crate::operators::DURATION_SUBSEC_INFO, diff --git a/clippy_lints/src/operators/cmp_nan.rs b/clippy_lints/src/operators/cmp_nan.rs deleted file mode 100644 index e18064b7061..00000000000 --- a/clippy_lints/src/operators/cmp_nan.rs +++ /dev/null @@ -1,30 +0,0 @@ -use clippy_utils::consts::{constant, Constant}; -use clippy_utils::diagnostics::span_lint; -use clippy_utils::in_constant; -use rustc_hir::{BinOpKind, Expr}; -use rustc_lint::LateContext; - -use super::CMP_NAN; - -pub(super) fn check(cx: &LateContext<'_>, e: &Expr<'_>, op: BinOpKind, lhs: &Expr<'_>, rhs: &Expr<'_>) { - if op.is_comparison() && !in_constant(cx, e.hir_id) && (is_nan(cx, lhs) || is_nan(cx, rhs)) { - span_lint( - cx, - CMP_NAN, - e.span, - "doomed comparison with `NAN`, use `{f32,f64}::is_nan()` instead", - ); - } -} - -fn is_nan(cx: &LateContext<'_>, e: &Expr<'_>) -> bool { - if let Some(value) = constant(cx, cx.typeck_results(), e) { - match value { - Constant::F32(num) => num.is_nan(), - Constant::F64(num) => num.is_nan(), - _ => false, - } - } else { - false - } -} diff --git a/clippy_lints/src/operators/mod.rs b/clippy_lints/src/operators/mod.rs index d63a836e73d..2cf15adda01 100644 --- a/clippy_lints/src/operators/mod.rs +++ b/clippy_lints/src/operators/mod.rs @@ -1,7 +1,6 @@ mod absurd_extreme_comparisons; mod assign_op_pattern; mod bit_mask; -mod cmp_nan; mod cmp_owned; mod double_comparison; mod duration_subsec; @@ -485,31 +484,6 @@ declare_clippy_lint! { "integer division may cause loss of precision" } -declare_clippy_lint! { - /// ### What it does - /// Checks for comparisons to NaN. - /// - /// ### Why is this bad? - /// NaN does not compare meaningfully to anything – not - /// even itself – so those comparisons are simply wrong. - /// - /// ### Example - /// ```rust - /// # let x = 1.0; - /// if x == f32::NAN { } - /// ``` - /// - /// Use instead: - /// ```rust - /// # let x = 1.0f32; - /// if x.is_nan() { } - /// ``` - #[clippy::version = "pre 1.29.0"] - pub CMP_NAN, - correctness, - "comparisons to `NAN`, which will always return false, probably not intended" -} - declare_clippy_lint! { /// ### What it does /// Checks for conversions to owned values just for the sake @@ -775,7 +749,6 @@ impl_lint_pass!(Operators => [ FLOAT_EQUALITY_WITHOUT_ABS, IDENTITY_OP, INTEGER_DIVISION, - CMP_NAN, CMP_OWNED, FLOAT_CMP, FLOAT_CMP_CONST, @@ -816,7 +789,6 @@ impl<'tcx> LateLintPass<'tcx> for Operators { duration_subsec::check(cx, e, op.node, lhs, rhs); float_equality_without_abs::check(cx, e, op.node, lhs, rhs); integer_division::check(cx, e, op.node, lhs, rhs); - cmp_nan::check(cx, e, op.node, lhs, rhs); cmp_owned::check(cx, op.node, lhs, rhs); float_cmp::check(cx, e, op.node, lhs, rhs); modulo_one::check(cx, e, op.node, rhs); diff --git a/clippy_lints/src/renamed_lints.rs b/clippy_lints/src/renamed_lints.rs index f76fa76f076..cbcd11debfd 100644 --- a/clippy_lints/src/renamed_lints.rs +++ b/clippy_lints/src/renamed_lints.rs @@ -33,6 +33,7 @@ pub static RENAMED_LINTS: &[(&str, &str)] = &[ ("clippy::zero_width_space", "clippy::invisible_characters"), ("clippy::cast_ref_to_mut", "cast_ref_to_mut"), ("clippy::clone_double_ref", "suspicious_double_ref_op"), + ("clippy::cmp_nan", "invalid_nan_comparisons"), ("clippy::drop_bounds", "drop_bounds"), ("clippy::drop_copy", "dropping_copy_types"), ("clippy::drop_ref", "dropping_references"), diff --git a/tests/ui/cmp_nan.rs b/tests/ui/cmp_nan.rs deleted file mode 100644 index 64ca52b010a..00000000000 --- a/tests/ui/cmp_nan.rs +++ /dev/null @@ -1,34 +0,0 @@ -const NAN_F32: f32 = f32::NAN; -const NAN_F64: f64 = f64::NAN; - -#[warn(clippy::cmp_nan)] -#[allow(clippy::float_cmp, clippy::no_effect, clippy::unnecessary_operation)] -fn main() { - let x = 5f32; - x == f32::NAN; - x != f32::NAN; - x < f32::NAN; - x > f32::NAN; - x <= f32::NAN; - x >= f32::NAN; - x == NAN_F32; - x != NAN_F32; - x < NAN_F32; - x > NAN_F32; - x <= NAN_F32; - x >= NAN_F32; - - let y = 0f64; - y == f64::NAN; - y != f64::NAN; - y < f64::NAN; - y > f64::NAN; - y <= f64::NAN; - y >= f64::NAN; - y == NAN_F64; - y != NAN_F64; - y < NAN_F64; - y > NAN_F64; - y <= NAN_F64; - y >= NAN_F64; -} diff --git a/tests/ui/cmp_nan.stderr b/tests/ui/cmp_nan.stderr deleted file mode 100644 index 867516661a5..00000000000 --- a/tests/ui/cmp_nan.stderr +++ /dev/null @@ -1,148 +0,0 @@ -error: doomed comparison with `NAN`, use `{f32,f64}::is_nan()` instead - --> $DIR/cmp_nan.rs:8:5 - | -LL | x == f32::NAN; - | ^^^^^^^^^^^^^ - | - = note: `-D clippy::cmp-nan` implied by `-D warnings` - -error: doomed comparison with `NAN`, use `{f32,f64}::is_nan()` instead - --> $DIR/cmp_nan.rs:9:5 - | -LL | x != f32::NAN; - | ^^^^^^^^^^^^^ - -error: doomed comparison with `NAN`, use `{f32,f64}::is_nan()` instead - --> $DIR/cmp_nan.rs:10:5 - | -LL | x < f32::NAN; - | ^^^^^^^^^^^^ - -error: doomed comparison with `NAN`, use `{f32,f64}::is_nan()` instead - --> $DIR/cmp_nan.rs:11:5 - | -LL | x > f32::NAN; - | ^^^^^^^^^^^^ - -error: doomed comparison with `NAN`, use `{f32,f64}::is_nan()` instead - --> $DIR/cmp_nan.rs:12:5 - | -LL | x <= f32::NAN; - | ^^^^^^^^^^^^^ - -error: doomed comparison with `NAN`, use `{f32,f64}::is_nan()` instead - --> $DIR/cmp_nan.rs:13:5 - | -LL | x >= f32::NAN; - | ^^^^^^^^^^^^^ - -error: doomed comparison with `NAN`, use `{f32,f64}::is_nan()` instead - --> $DIR/cmp_nan.rs:14:5 - | -LL | x == NAN_F32; - | ^^^^^^^^^^^^ - -error: doomed comparison with `NAN`, use `{f32,f64}::is_nan()` instead - --> $DIR/cmp_nan.rs:15:5 - | -LL | x != NAN_F32; - | ^^^^^^^^^^^^ - -error: doomed comparison with `NAN`, use `{f32,f64}::is_nan()` instead - --> $DIR/cmp_nan.rs:16:5 - | -LL | x < NAN_F32; - | ^^^^^^^^^^^ - -error: doomed comparison with `NAN`, use `{f32,f64}::is_nan()` instead - --> $DIR/cmp_nan.rs:17:5 - | -LL | x > NAN_F32; - | ^^^^^^^^^^^ - -error: doomed comparison with `NAN`, use `{f32,f64}::is_nan()` instead - --> $DIR/cmp_nan.rs:18:5 - | -LL | x <= NAN_F32; - | ^^^^^^^^^^^^ - -error: doomed comparison with `NAN`, use `{f32,f64}::is_nan()` instead - --> $DIR/cmp_nan.rs:19:5 - | -LL | x >= NAN_F32; - | ^^^^^^^^^^^^ - -error: doomed comparison with `NAN`, use `{f32,f64}::is_nan()` instead - --> $DIR/cmp_nan.rs:22:5 - | -LL | y == f64::NAN; - | ^^^^^^^^^^^^^ - -error: doomed comparison with `NAN`, use `{f32,f64}::is_nan()` instead - --> $DIR/cmp_nan.rs:23:5 - | -LL | y != f64::NAN; - | ^^^^^^^^^^^^^ - -error: doomed comparison with `NAN`, use `{f32,f64}::is_nan()` instead - --> $DIR/cmp_nan.rs:24:5 - | -LL | y < f64::NAN; - | ^^^^^^^^^^^^ - -error: doomed comparison with `NAN`, use `{f32,f64}::is_nan()` instead - --> $DIR/cmp_nan.rs:25:5 - | -LL | y > f64::NAN; - | ^^^^^^^^^^^^ - -error: doomed comparison with `NAN`, use `{f32,f64}::is_nan()` instead - --> $DIR/cmp_nan.rs:26:5 - | -LL | y <= f64::NAN; - | ^^^^^^^^^^^^^ - -error: doomed comparison with `NAN`, use `{f32,f64}::is_nan()` instead - --> $DIR/cmp_nan.rs:27:5 - | -LL | y >= f64::NAN; - | ^^^^^^^^^^^^^ - -error: doomed comparison with `NAN`, use `{f32,f64}::is_nan()` instead - --> $DIR/cmp_nan.rs:28:5 - | -LL | y == NAN_F64; - | ^^^^^^^^^^^^ - -error: doomed comparison with `NAN`, use `{f32,f64}::is_nan()` instead - --> $DIR/cmp_nan.rs:29:5 - | -LL | y != NAN_F64; - | ^^^^^^^^^^^^ - -error: doomed comparison with `NAN`, use `{f32,f64}::is_nan()` instead - --> $DIR/cmp_nan.rs:30:5 - | -LL | y < NAN_F64; - | ^^^^^^^^^^^ - -error: doomed comparison with `NAN`, use `{f32,f64}::is_nan()` instead - --> $DIR/cmp_nan.rs:31:5 - | -LL | y > NAN_F64; - | ^^^^^^^^^^^ - -error: doomed comparison with `NAN`, use `{f32,f64}::is_nan()` instead - --> $DIR/cmp_nan.rs:32:5 - | -LL | y <= NAN_F64; - | ^^^^^^^^^^^^ - -error: doomed comparison with `NAN`, use `{f32,f64}::is_nan()` instead - --> $DIR/cmp_nan.rs:33:5 - | -LL | y >= NAN_F64; - | ^^^^^^^^^^^^ - -error: aborting due to 24 previous errors - diff --git a/tests/ui/crashes/mut_mut_macro.rs b/tests/ui/crashes/mut_mut_macro.rs index a238e7896fc..92821b6ecbb 100644 --- a/tests/ui/crashes/mut_mut_macro.rs +++ b/tests/ui/crashes/mut_mut_macro.rs @@ -1,4 +1,4 @@ -#![deny(clippy::mut_mut, clippy::zero_ptr, clippy::cmp_nan)] +#![deny(clippy::mut_mut, clippy::zero_ptr)] #![allow(dead_code)] // FIXME: compiletest + extern crates doesn't work together. To make this test work, it would need @@ -8,13 +8,12 @@ // extern crate lazy_static; // use std::collections::HashMap; -/// ensure that we don't suggest `is_nan` and `is_null` inside constants +/// ensure that we don't suggest `is_null` inside constants /// FIXME: once const fn is stable, suggest these functions again in constants const BAA: *const i32 = 0 as *const i32; static mut BAR: *const i32 = BAA; static mut FOO: *const i32 = 0 as *const i32; -static mut BUH: bool = 42.0 < f32::NAN; #[allow(unused_variables, unused_mut)] fn main() { diff --git a/tests/ui/rename.fixed b/tests/ui/rename.fixed index 954145fc4e6..f1b25dc094e 100644 --- a/tests/ui/rename.fixed +++ b/tests/ui/rename.fixed @@ -41,6 +41,7 @@ #![allow(invalid_atomic_ordering)] #![allow(invalid_value)] #![allow(invalid_from_utf8_unchecked)] +#![allow(invalid_nan_comparisons)] #![allow(let_underscore_drop)] #![allow(enum_intrinsics_non_enums)] #![allow(non_fmt_panics)] @@ -55,6 +56,7 @@ #![warn(clippy::blocks_in_if_conditions)] #![warn(clippy::blocks_in_if_conditions)] #![warn(clippy::box_collection)] +#![warn(invalid_nan_comparisons)] #![warn(clippy::redundant_static_lifetimes)] #![warn(clippy::cognitive_complexity)] #![warn(clippy::derived_hash_with_manual_eq)] diff --git a/tests/ui/rename.rs b/tests/ui/rename.rs index 067a3109afb..4af511c344c 100644 --- a/tests/ui/rename.rs +++ b/tests/ui/rename.rs @@ -41,6 +41,7 @@ #![allow(invalid_atomic_ordering)] #![allow(invalid_value)] #![allow(invalid_from_utf8_unchecked)] +#![allow(invalid_nan_comparisons)] #![allow(let_underscore_drop)] #![allow(enum_intrinsics_non_enums)] #![allow(non_fmt_panics)] @@ -55,6 +56,7 @@ #![warn(clippy::block_in_if_condition_expr)] #![warn(clippy::block_in_if_condition_stmt)] #![warn(clippy::box_vec)] +#![warn(clippy::cmp_nan)] #![warn(clippy::const_static_lifetime)] #![warn(clippy::cyclomatic_complexity)] #![warn(clippy::derive_hash_xor_eq)] diff --git a/tests/ui/rename.stderr b/tests/ui/rename.stderr index 1819d108c57..156a8f96b50 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:53:9 + --> $DIR/rename.rs:54:9 | LL | #![warn(clippy::almost_complete_letter_range)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::almost_complete_range` @@ -7,304 +7,310 @@ 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:54:9 + --> $DIR/rename.rs:55: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:55:9 + --> $DIR/rename.rs:56: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:56:9 + --> $DIR/rename.rs:57: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:57:9 + --> $DIR/rename.rs:58:9 | LL | #![warn(clippy::box_vec)] | ^^^^^^^^^^^^^^^ help: use the new name: `clippy::box_collection` +error: lint `clippy::cmp_nan` has been renamed to `invalid_nan_comparisons` + --> $DIR/rename.rs:59:9 + | +LL | #![warn(clippy::cmp_nan)] + | ^^^^^^^^^^^^^^^ help: use the new name: `invalid_nan_comparisons` + error: lint `clippy::const_static_lifetime` has been renamed to `clippy::redundant_static_lifetimes` - --> $DIR/rename.rs:58:9 + --> $DIR/rename.rs:60: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:59:9 + --> $DIR/rename.rs:61: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:60:9 + --> $DIR/rename.rs:62: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:61:9 + --> $DIR/rename.rs:63: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:62:9 + --> $DIR/rename.rs:64: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:63:9 + --> $DIR/rename.rs:65: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:64:9 + --> $DIR/rename.rs:66: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:65:9 + --> $DIR/rename.rs:67:9 | LL | #![warn(clippy::if_let_some_result)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::match_result_ok` error: lint `clippy::integer_arithmetic` has been renamed to `clippy::arithmetic_side_effects` - --> $DIR/rename.rs:66:9 + --> $DIR/rename.rs:68:9 | LL | #![warn(clippy::integer_arithmetic)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::arithmetic_side_effects` error: lint `clippy::logic_bug` has been renamed to `clippy::overly_complex_bool_expr` - --> $DIR/rename.rs:67:9 + --> $DIR/rename.rs:69: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:68:9 + --> $DIR/rename.rs:70: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:69:9 + --> $DIR/rename.rs:71: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:70:9 + --> $DIR/rename.rs:72: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:71:9 + --> $DIR/rename.rs:73: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:72:9 + --> $DIR/rename.rs:74: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:73:9 + --> $DIR/rename.rs:75: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:74:9 + --> $DIR/rename.rs:76: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:75:9 + --> $DIR/rename.rs:77: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:76:9 + --> $DIR/rename.rs:78: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:77:9 + --> $DIR/rename.rs:79: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:78:9 + --> $DIR/rename.rs:80: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:79:9 + --> $DIR/rename.rs:81: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:80:9 + --> $DIR/rename.rs:82: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:81:9 + --> $DIR/rename.rs:83:9 | LL | #![warn(clippy::zero_width_space)] | ^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::invisible_characters` error: lint `clippy::cast_ref_to_mut` has been renamed to `cast_ref_to_mut` - --> $DIR/rename.rs:82:9 + --> $DIR/rename.rs:84:9 | LL | #![warn(clippy::cast_ref_to_mut)] | ^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `cast_ref_to_mut` error: lint `clippy::clone_double_ref` has been renamed to `suspicious_double_ref_op` - --> $DIR/rename.rs:83:9 + --> $DIR/rename.rs:85: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:84:9 + --> $DIR/rename.rs:86:9 | LL | #![warn(clippy::drop_bounds)] | ^^^^^^^^^^^^^^^^^^^ help: use the new name: `drop_bounds` error: lint `clippy::drop_copy` has been renamed to `dropping_copy_types` - --> $DIR/rename.rs:85:9 + --> $DIR/rename.rs:87:9 | LL | #![warn(clippy::drop_copy)] | ^^^^^^^^^^^^^^^^^ help: use the new name: `dropping_copy_types` error: lint `clippy::drop_ref` has been renamed to `dropping_references` - --> $DIR/rename.rs:86:9 + --> $DIR/rename.rs:88:9 | LL | #![warn(clippy::drop_ref)] | ^^^^^^^^^^^^^^^^ help: use the new name: `dropping_references` error: lint `clippy::for_loop_over_option` has been renamed to `for_loops_over_fallibles` - --> $DIR/rename.rs:87:9 + --> $DIR/rename.rs:89: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:88:9 + --> $DIR/rename.rs:90: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:89:9 + --> $DIR/rename.rs:91:9 | LL | #![warn(clippy::for_loops_over_fallibles)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `for_loops_over_fallibles` error: lint `clippy::forget_copy` has been renamed to `forgetting_copy_types` - --> $DIR/rename.rs:90:9 + --> $DIR/rename.rs:92:9 | LL | #![warn(clippy::forget_copy)] | ^^^^^^^^^^^^^^^^^^^ help: use the new name: `forgetting_copy_types` error: lint `clippy::forget_ref` has been renamed to `forgetting_references` - --> $DIR/rename.rs:91:9 + --> $DIR/rename.rs:93:9 | LL | #![warn(clippy::forget_ref)] | ^^^^^^^^^^^^^^^^^^ help: use the new name: `forgetting_references` error: lint `clippy::into_iter_on_array` has been renamed to `array_into_iter` - --> $DIR/rename.rs:92:9 + --> $DIR/rename.rs:94: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:93:9 + --> $DIR/rename.rs:95: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:94:9 + --> $DIR/rename.rs:96:9 | LL | #![warn(clippy::invalid_ref)] | ^^^^^^^^^^^^^^^^^^^ help: use the new name: `invalid_value` error: lint `clippy::invalid_utf8_in_unchecked` has been renamed to `invalid_from_utf8_unchecked` - --> $DIR/rename.rs:95:9 + --> $DIR/rename.rs:97:9 | LL | #![warn(clippy::invalid_utf8_in_unchecked)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `invalid_from_utf8_unchecked` error: lint `clippy::let_underscore_drop` has been renamed to `let_underscore_drop` - --> $DIR/rename.rs:96:9 + --> $DIR/rename.rs:98: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:97:9 + --> $DIR/rename.rs:99: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:98:9 + --> $DIR/rename.rs:100: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:99:9 + --> $DIR/rename.rs:101: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:100:9 + --> $DIR/rename.rs:102:9 | LL | #![warn(clippy::temporary_cstring_as_ptr)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `temporary_cstring_as_ptr` error: lint `clippy::undropped_manually_drops` has been renamed to `undropped_manually_drops` - --> $DIR/rename.rs:101:9 + --> $DIR/rename.rs:103:9 | LL | #![warn(clippy::undropped_manually_drops)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `undropped_manually_drops` error: lint `clippy::unknown_clippy_lints` has been renamed to `unknown_lints` - --> $DIR/rename.rs:102:9 + --> $DIR/rename.rs:104: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:103:9 + --> $DIR/rename.rs:105:9 | LL | #![warn(clippy::unused_label)] | ^^^^^^^^^^^^^^^^^^^^ help: use the new name: `unused_labels` -error: aborting due to 51 previous errors +error: aborting due to 52 previous errors diff --git a/tests/ui/unknown_clippy_lints.fixed b/tests/ui/unknown_clippy_lints.fixed index 49c0e4dc7eb..debc7e152e7 100644 --- a/tests/ui/unknown_clippy_lints.fixed +++ b/tests/ui/unknown_clippy_lints.fixed @@ -3,7 +3,7 @@ #![warn(clippy::pedantic)] // Should suggest lowercase #![allow(clippy::all)] -#![warn(clippy::cmp_nan)] +#![warn(clippy::cmp_owned)] // Should suggest similar clippy lint name #[warn(clippy::if_not_else)] diff --git a/tests/ui/unknown_clippy_lints.rs b/tests/ui/unknown_clippy_lints.rs index b60042923ea..16140fd1079 100644 --- a/tests/ui/unknown_clippy_lints.rs +++ b/tests/ui/unknown_clippy_lints.rs @@ -3,7 +3,7 @@ #![warn(clippy::pedantic)] // Should suggest lowercase #![allow(clippy::All)] -#![warn(clippy::CMP_NAN)] +#![warn(clippy::CMP_OWNED)] // Should suggest similar clippy lint name #[warn(clippy::if_not_els)] diff --git a/tests/ui/unknown_clippy_lints.stderr b/tests/ui/unknown_clippy_lints.stderr index 584c428932f..880673eef3e 100644 --- a/tests/ui/unknown_clippy_lints.stderr +++ b/tests/ui/unknown_clippy_lints.stderr @@ -6,11 +6,11 @@ LL | #![allow(clippy::All)] | = note: `-D unknown-lints` implied by `-D warnings` -error: unknown lint: `clippy::CMP_NAN` +error: unknown lint: `clippy::CMP_OWNED` --> $DIR/unknown_clippy_lints.rs:6:9 | -LL | #![warn(clippy::CMP_NAN)] - | ^^^^^^^^^^^^^^^ help: did you mean: `clippy::cmp_nan` +LL | #![warn(clippy::CMP_OWNED)] + | ^^^^^^^^^^^^^^^^^ help: did you mean: `clippy::cmp_owned` error: unknown lint: `clippy::if_not_els` --> $DIR/unknown_clippy_lints.rs:9:8 From 26f50395ba95a4da42b2b1b0d9532a2b9e99cdea Mon Sep 17 00:00:00 2001 From: Centri3 <114838443+Centri3@users.noreply.github.com> Date: Sat, 10 Jun 2023 06:43:30 -0500 Subject: [PATCH 125/310] Add `needless_if` lint --- CHANGELOG.md | 1 + clippy_lints/src/declared_lints.rs | 1 + clippy_lints/src/lib.rs | 2 + clippy_lints/src/needless_if.rs | 66 +++++++++++++++++++ lintcheck/lintcheck_crates.toml | 35 +--------- tests/ui-internal/if_chain_style.rs | 7 +- tests/ui-internal/if_chain_style.stderr | 20 +++--- tests/ui/auxiliary/proc_macros.rs | 2 +- tests/ui/blocks_in_if_conditions.fixed | 2 +- tests/ui/blocks_in_if_conditions.rs | 2 +- tests/ui/blocks_in_if_conditions_closure.rs | 2 +- tests/ui/bool_comparison.fixed | 1 + tests/ui/bool_comparison.rs | 1 + tests/ui/bool_comparison.stderr | 44 ++++++------- .../ui/cmp_owned/asymmetric_partial_eq.fixed | 7 +- tests/ui/cmp_owned/asymmetric_partial_eq.rs | 7 +- .../ui/cmp_owned/asymmetric_partial_eq.stderr | 12 ++-- tests/ui/collapsible_else_if.fixed | 2 +- tests/ui/collapsible_else_if.rs | 2 +- tests/ui/collapsible_if.fixed | 1 + tests/ui/collapsible_if.rs | 1 + tests/ui/collapsible_if.stderr | 18 ++--- tests/ui/crashes/ice-3462.rs | 2 +- tests/ui/crashes/ice-7169.rs | 2 + tests/ui/crashes/ice-7169.stderr | 2 +- tests/ui/disallowed_names.rs | 1 + tests/ui/disallowed_names.stderr | 28 ++++---- tests/ui/double_comparison.fixed | 1 + tests/ui/double_comparison.rs | 1 + tests/ui/double_comparison.stderr | 16 ++--- tests/ui/equatable_if_let.fixed | 7 +- tests/ui/equatable_if_let.rs | 7 +- tests/ui/equatable_if_let.stderr | 28 ++++---- tests/ui/expect_tool_lint_rfc_2383.rs | 1 + tests/ui/expect_tool_lint_rfc_2383.stderr | 12 ++-- tests/ui/filetype_is_file.rs | 1 + tests/ui/filetype_is_file.stderr | 6 +- tests/ui/fn_null_check.rs | 1 + tests/ui/fn_null_check.stderr | 10 +-- tests/ui/if_same_then_else2.rs | 1 + tests/ui/if_same_then_else2.stderr | 24 +++---- tests/ui/ifs_same_cond.rs | 7 +- tests/ui/ifs_same_cond.stderr | 16 ++--- tests/ui/len_zero.fixed | 2 +- tests/ui/len_zero.rs | 2 +- tests/ui/manual_let_else.rs | 3 +- tests/ui/manual_let_else.stderr | 52 +++++++-------- tests/ui/match_overlapping_arm.rs | 2 +- tests/ui/needless_bool/fixable.fixed | 1 + tests/ui/needless_bool/fixable.rs | 1 + tests/ui/needless_bool/fixable.stderr | 42 ++++++------ tests/ui/needless_borrowed_ref.fixed | 3 +- tests/ui/needless_borrowed_ref.rs | 3 +- tests/ui/needless_borrowed_ref.stderr | 34 +++++----- tests/ui/needless_collect.fixed | 2 +- tests/ui/needless_collect.rs | 2 +- tests/ui/needless_collect_indirect.rs | 1 + tests/ui/needless_if.fixed | 37 +++++++++++ tests/ui/needless_if.rs | 37 +++++++++++ tests/ui/needless_if.stderr | 25 +++++++ tests/ui/nonminimal_bool.rs | 2 +- tests/ui/nonminimal_bool_methods.fixed | 2 +- tests/ui/nonminimal_bool_methods.rs | 2 +- tests/ui/overflow_check_conditional.rs | 1 + tests/ui/overflow_check_conditional.stderr | 16 ++--- tests/ui/partialeq_to_none.fixed | 2 +- tests/ui/partialeq_to_none.rs | 2 +- ...edundant_pattern_matching_drop_order.fixed | 7 +- .../redundant_pattern_matching_drop_order.rs | 7 +- ...dundant_pattern_matching_drop_order.stderr | 44 ++++++------- .../redundant_pattern_matching_ipaddr.fixed | 1 + tests/ui/redundant_pattern_matching_ipaddr.rs | 1 + .../redundant_pattern_matching_ipaddr.stderr | 36 +++++----- .../redundant_pattern_matching_option.fixed | 1 + tests/ui/redundant_pattern_matching_option.rs | 1 + .../redundant_pattern_matching_option.stderr | 56 ++++++++-------- .../ui/redundant_pattern_matching_poll.fixed | 1 + tests/ui/redundant_pattern_matching_poll.rs | 1 + .../ui/redundant_pattern_matching_poll.stderr | 36 +++++----- .../redundant_pattern_matching_result.fixed | 1 + tests/ui/redundant_pattern_matching_result.rs | 1 + .../redundant_pattern_matching_result.stderr | 56 ++++++++-------- tests/ui/shadow.rs | 2 +- tests/ui/single_match.fixed | 7 +- tests/ui/single_match.rs | 7 +- tests/ui/single_match.stderr | 36 +++++----- tests/ui/starts_ends_with.fixed | 2 +- tests/ui/starts_ends_with.rs | 2 +- tests/ui/suspicious_else_formatting.rs | 7 +- tests/ui/suspicious_else_formatting.stderr | 18 ++--- tests/ui/suspicious_unary_op_formatting.rs | 1 + .../ui/suspicious_unary_op_formatting.stderr | 8 +-- tests/ui/unit_cmp.rs | 3 +- tests/ui/unit_cmp.stderr | 12 ++-- tests/ui/unnecessary_safety_comment.rs | 2 +- tests/ui/unneeded_wildcard_pattern.fixed | 1 + tests/ui/unneeded_wildcard_pattern.rs | 1 + tests/ui/unneeded_wildcard_pattern.stderr | 28 ++++---- tests/ui/unnested_or_patterns.fixed | 7 +- tests/ui/unnested_or_patterns.rs | 7 +- tests/ui/unnested_or_patterns.stderr | 34 +++++----- tests/ui/unnested_or_patterns2.fixed | 2 +- tests/ui/unnested_or_patterns2.rs | 2 +- tests/ui/useless_conversion.fixed | 2 +- tests/ui/useless_conversion.rs | 2 +- tests/ui/useless_conversion_try.rs | 1 + tests/ui/useless_conversion_try.stderr | 18 ++--- 107 files changed, 692 insertions(+), 456 deletions(-) create mode 100644 clippy_lints/src/needless_if.rs create mode 100644 tests/ui/needless_if.fixed create mode 100644 tests/ui/needless_if.rs create mode 100644 tests/ui/needless_if.stderr diff --git a/CHANGELOG.md b/CHANGELOG.md index 0d00f2c16e7..8a330b35d69 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5008,6 +5008,7 @@ Released 2018-09-13 [`needless_doctest_main`]: https://rust-lang.github.io/rust-clippy/master/index.html#needless_doctest_main [`needless_else`]: https://rust-lang.github.io/rust-clippy/master/index.html#needless_else [`needless_for_each`]: https://rust-lang.github.io/rust-clippy/master/index.html#needless_for_each +[`needless_if`]: https://rust-lang.github.io/rust-clippy/master/index.html#needless_if [`needless_late_init`]: https://rust-lang.github.io/rust-clippy/master/index.html#needless_late_init [`needless_lifetimes`]: https://rust-lang.github.io/rust-clippy/master/index.html#needless_lifetimes [`needless_match`]: https://rust-lang.github.io/rust-clippy/master/index.html#needless_match diff --git a/clippy_lints/src/declared_lints.rs b/clippy_lints/src/declared_lints.rs index b6ceab26006..874c173f709 100644 --- a/clippy_lints/src/declared_lints.rs +++ b/clippy_lints/src/declared_lints.rs @@ -459,6 +459,7 @@ pub(crate) static LINTS: &[&crate::LintInfo] = &[ crate::needless_continue::NEEDLESS_CONTINUE_INFO, crate::needless_else::NEEDLESS_ELSE_INFO, crate::needless_for_each::NEEDLESS_FOR_EACH_INFO, + crate::needless_if::NEEDLESS_IF_INFO, crate::needless_late_init::NEEDLESS_LATE_INIT_INFO, crate::needless_parens_on_range_literals::NEEDLESS_PARENS_ON_RANGE_LITERALS_INFO, crate::needless_pass_by_value::NEEDLESS_PASS_BY_VALUE_INFO, diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index 22ff5ef5859..882c5653c96 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -223,6 +223,7 @@ mod needless_borrowed_ref; mod needless_continue; mod needless_else; mod needless_for_each; +mod needless_if; mod needless_late_init; mod needless_parens_on_range_literals; mod needless_pass_by_value; @@ -1029,6 +1030,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: store.register_late_pass(|_| Box::new(endian_bytes::EndianBytes)); store.register_late_pass(|_| Box::new(redundant_type_annotations::RedundantTypeAnnotations)); store.register_late_pass(|_| Box::new(arc_with_non_send_sync::ArcWithNonSendSync)); + store.register_late_pass(|_| Box::new(needless_if::NeedlessIf)); // add lints here, do not remove this comment, it's used in `new_lint` } diff --git a/clippy_lints/src/needless_if.rs b/clippy_lints/src/needless_if.rs new file mode 100644 index 00000000000..1568c3533a0 --- /dev/null +++ b/clippy_lints/src/needless_if.rs @@ -0,0 +1,66 @@ +use clippy_utils::{diagnostics::span_lint_and_sugg, is_from_proc_macro, source::snippet_with_applicability}; +use rustc_errors::Applicability; +use rustc_hir::{Expr, ExprKind, Node}; +use rustc_lint::{LateContext, LateLintPass, LintContext}; +use rustc_middle::lint::in_external_macro; +use rustc_session::{declare_lint_pass, declare_tool_lint}; + +declare_clippy_lint! { + /// ### What it does + /// + /// ### Why is this bad? + /// + /// ### Example + /// ```rust + /// // example code where clippy issues a warning + /// ``` + /// Use instead: + /// ```rust + /// // example code which does not raise clippy warning + /// ``` + #[clippy::version = "1.72.0"] + pub NEEDLESS_IF, + complexity, + "checks for empty if branches" +} +declare_lint_pass!(NeedlessIf => [NEEDLESS_IF]); + +impl LateLintPass<'_> for NeedlessIf { + fn check_expr<'tcx>(&mut self, cx: &LateContext<'tcx>, expr: &Expr<'tcx>) { + if let ExprKind::If(if_expr, block, else_expr) = &expr.kind + && let ExprKind::Block(block, ..) = block.kind + && block.stmts.is_empty() + && block.expr.is_none() + && else_expr.is_none() + && !in_external_macro(cx.sess(), expr.span) + { + let mut app = Applicability::MachineApplicable; + let snippet = snippet_with_applicability(cx, if_expr.span, "{ ... }", &mut app); + + // Ignore `else if` + if let Some(parent_id) = cx.tcx.hir().opt_parent_id(expr.hir_id) + && let Some(Node::Expr(Expr { + kind: ExprKind::If(_, _, Some(else_expr)), + .. + })) = cx.tcx.hir().find(parent_id) + && else_expr.hir_id == expr.hir_id + { + return; + } + + if is_from_proc_macro(cx, expr) { + return; + } + + span_lint_and_sugg( + cx, + NEEDLESS_IF, + expr.span, + "this if branch is empty", + "you can remove it", + format!("{snippet};"), + Applicability::MachineApplicable, + ); + } + } +} diff --git a/lintcheck/lintcheck_crates.toml b/lintcheck/lintcheck_crates.toml index 52f7fee47b6..066b2657d03 100644 --- a/lintcheck/lintcheck_crates.toml +++ b/lintcheck/lintcheck_crates.toml @@ -1,38 +1,7 @@ [crates] # some of these are from cargotest -cargo = {name = "cargo", versions = ['0.64.0']} -iron = {name = "iron", versions = ['0.6.1']} -ripgrep = {name = "ripgrep", versions = ['12.1.1']} -xsv = {name = "xsv", versions = ['0.13.0']} -# commented out because of 173K clippy::match_same_arms msgs in language_type.rs -#tokei = { name = "tokei", versions = ['12.0.4']} -rayon = {name = "rayon", versions = ['1.5.0']} -serde = {name = "serde", versions = ['1.0.118']} -# top 10 crates.io dls -bitflags = {name = "bitflags", versions = ['1.2.1']} -# crash = {name = "clippy_crash", path = "/tmp/clippy_crash"} -libc = {name = "libc", versions = ['0.2.81']} -log = {name = "log", versions = ['0.4.11']} -proc-macro2 = {name = "proc-macro2", versions = ['1.0.24']} -quote = {name = "quote", versions = ['1.0.7']} -rand = {name = "rand", versions = ['0.7.3']} -rand_core = {name = "rand_core", versions = ['0.6.0']} -regex = {name = "regex", versions = ['1.3.2']} -syn = {name = "syn", versions = ['1.0.54']} -unicode-xid = {name = "unicode-xid", versions = ['0.2.1']} -# some more of dtolnays crates -anyhow = {name = "anyhow", versions = ['1.0.38']} -async-trait = {name = "async-trait", versions = ['0.1.42']} -cxx = {name = "cxx", versions = ['1.0.32']} -ryu = {name = "ryu", versions = ['1.0.5']} -serde_yaml = {name = "serde_yaml", versions = ['0.8.17']} -thiserror = {name = "thiserror", versions = ['1.0.24']} -# some embark crates, there are other interesting crates but -# unfortunately adding them increases lintcheck runtime drastically -cfg-expr = {name = "cfg-expr", versions = ['0.7.1']} -puffin = {name = "puffin", git_url = "https://github.com/EmbarkStudios/puffin", git_hash = "02dd4a3"} -rpmalloc = {name = "rpmalloc", versions = ['0.2.0']} -tame-oidc = {name = "tame-oidc", versions = ['0.1.0']} +bevy = {name = "bevy", versions = ['0.10.1']} +deno = {name = "deno", versions = ['1.34.2']} [recursive] ignore = [ diff --git a/tests/ui-internal/if_chain_style.rs b/tests/ui-internal/if_chain_style.rs index b0d89e038aa..b462b20e04c 100644 --- a/tests/ui-internal/if_chain_style.rs +++ b/tests/ui-internal/if_chain_style.rs @@ -1,5 +1,10 @@ #![warn(clippy::if_chain_style)] -#![allow(clippy::no_effect, clippy::nonminimal_bool, clippy::missing_clippy_version_attribute)] +#![allow( + clippy::needless_if, + clippy::no_effect, + clippy::nonminimal_bool, + clippy::missing_clippy_version_attribute +)] extern crate if_chain; diff --git a/tests/ui-internal/if_chain_style.stderr b/tests/ui-internal/if_chain_style.stderr index d8f1ffb21ba..b12df278652 100644 --- a/tests/ui-internal/if_chain_style.stderr +++ b/tests/ui-internal/if_chain_style.stderr @@ -1,5 +1,5 @@ error: this `if` can be part of the inner `if_chain!` - --> $DIR/if_chain_style.rs:9:5 + --> $DIR/if_chain_style.rs:14:5 | LL | / if true { LL | | let x = ""; @@ -11,14 +11,14 @@ LL | | } | |_____^ | help: this `let` statement can also be in the `if_chain!` - --> $DIR/if_chain_style.rs:10:9 + --> $DIR/if_chain_style.rs:15:9 | LL | let x = ""; | ^^^^^^^^^^^ = note: `-D clippy::if-chain-style` implied by `-D warnings` error: `if a && b;` should be `if a; if b;` - --> $DIR/if_chain_style.rs:19:12 + --> $DIR/if_chain_style.rs:24:12 | LL | if true | ____________^ @@ -27,25 +27,25 @@ LL | | && false; | |____________________^ error: `let` expression should be inside `then { .. }` - --> $DIR/if_chain_style.rs:24:9 + --> $DIR/if_chain_style.rs:29:9 | LL | let x = ""; | ^^^^^^^^^^^ error: this `if` can be part of the outer `if_chain!` - --> $DIR/if_chain_style.rs:35:13 + --> $DIR/if_chain_style.rs:40:13 | LL | if true {} | ^^^^^^^^^^ | help: this `let` statement can also be in the `if_chain!` - --> $DIR/if_chain_style.rs:33:13 + --> $DIR/if_chain_style.rs:38:13 | LL | let x = ""; | ^^^^^^^^^^^ error: `if_chain!` only has one `if` - --> $DIR/if_chain_style.rs:29:5 + --> $DIR/if_chain_style.rs:34:5 | LL | / if_chain! { LL | | // single `if` condition @@ -59,13 +59,13 @@ LL | | } = note: this error originates in the macro `__if_chain` which comes from the expansion of the macro `if_chain` (in Nightly builds, run with -Z macro-backtrace for more info) error: `let` expression should be above the `if_chain!` - --> $DIR/if_chain_style.rs:40:9 + --> $DIR/if_chain_style.rs:45:9 | LL | let x = ""; | ^^^^^^^^^^^ error: this `if_chain!` can be merged with the outer `if_chain!` - --> $DIR/if_chain_style.rs:46:13 + --> $DIR/if_chain_style.rs:51:13 | LL | / if_chain! { LL | | if true; @@ -75,7 +75,7 @@ LL | | } | |_____________^ | help: these `let` statements can also be in the `if_chain!` - --> $DIR/if_chain_style.rs:43:13 + --> $DIR/if_chain_style.rs:48:13 | LL | / let x = ""; LL | | let x = ""; diff --git a/tests/ui/auxiliary/proc_macros.rs b/tests/ui/auxiliary/proc_macros.rs index 94f075ed09c..5d849bfcf81 100644 --- a/tests/ui/auxiliary/proc_macros.rs +++ b/tests/ui/auxiliary/proc_macros.rs @@ -4,7 +4,7 @@ #![crate_type = "proc-macro"] #![feature(let_chains)] #![feature(proc_macro_span)] -#![allow(dead_code)] +#![allow(clippy::needless_if, dead_code)] extern crate proc_macro; diff --git a/tests/ui/blocks_in_if_conditions.fixed b/tests/ui/blocks_in_if_conditions.fixed index a9f18782e58..2a3867ac8fc 100644 --- a/tests/ui/blocks_in_if_conditions.fixed +++ b/tests/ui/blocks_in_if_conditions.fixed @@ -1,6 +1,6 @@ //@run-rustfix #![warn(clippy::blocks_in_if_conditions)] -#![allow(unused, clippy::let_and_return)] +#![allow(unused, clippy::let_and_return, clippy::needless_if)] #![warn(clippy::nonminimal_bool)] macro_rules! blocky { diff --git a/tests/ui/blocks_in_if_conditions.rs b/tests/ui/blocks_in_if_conditions.rs index 0a70317c4d4..704d09fbad3 100644 --- a/tests/ui/blocks_in_if_conditions.rs +++ b/tests/ui/blocks_in_if_conditions.rs @@ -1,6 +1,6 @@ //@run-rustfix #![warn(clippy::blocks_in_if_conditions)] -#![allow(unused, clippy::let_and_return)] +#![allow(unused, clippy::let_and_return, clippy::needless_if)] #![warn(clippy::nonminimal_bool)] macro_rules! blocky { diff --git a/tests/ui/blocks_in_if_conditions_closure.rs b/tests/ui/blocks_in_if_conditions_closure.rs index 169589f6d4e..7da12d89a61 100644 --- a/tests/ui/blocks_in_if_conditions_closure.rs +++ b/tests/ui/blocks_in_if_conditions_closure.rs @@ -1,5 +1,5 @@ #![warn(clippy::blocks_in_if_conditions)] -#![allow(unused, clippy::let_and_return)] +#![allow(unused, clippy::let_and_return, clippy::needless_if)] fn predicate bool, T>(pfn: F, val: T) -> bool { pfn(val) diff --git a/tests/ui/bool_comparison.fixed b/tests/ui/bool_comparison.fixed index 670eef6a21d..d6774c03598 100644 --- a/tests/ui/bool_comparison.fixed +++ b/tests/ui/bool_comparison.fixed @@ -1,5 +1,6 @@ //@run-rustfix +#![allow(clippy::needless_if)] #![warn(clippy::bool_comparison)] fn main() { diff --git a/tests/ui/bool_comparison.rs b/tests/ui/bool_comparison.rs index 72851be635d..c0483fd7374 100644 --- a/tests/ui/bool_comparison.rs +++ b/tests/ui/bool_comparison.rs @@ -1,5 +1,6 @@ //@run-rustfix +#![allow(clippy::needless_if)] #![warn(clippy::bool_comparison)] fn main() { diff --git a/tests/ui/bool_comparison.stderr b/tests/ui/bool_comparison.stderr index 31522d4a525..f4dded365fb 100644 --- a/tests/ui/bool_comparison.stderr +++ b/tests/ui/bool_comparison.stderr @@ -1,5 +1,5 @@ error: equality checks against true are unnecessary - --> $DIR/bool_comparison.rs:7:8 + --> $DIR/bool_comparison.rs:8:8 | LL | if x == true { | ^^^^^^^^^ help: try simplifying it as shown: `x` @@ -7,127 +7,127 @@ LL | if x == true { = note: `-D clippy::bool-comparison` implied by `-D warnings` error: equality checks against false can be replaced by a negation - --> $DIR/bool_comparison.rs:12:8 + --> $DIR/bool_comparison.rs:13:8 | LL | if x == false { | ^^^^^^^^^^ help: try simplifying it as shown: `!x` error: equality checks against true are unnecessary - --> $DIR/bool_comparison.rs:17:8 + --> $DIR/bool_comparison.rs:18:8 | LL | if true == x { | ^^^^^^^^^ help: try simplifying it as shown: `x` error: equality checks against false can be replaced by a negation - --> $DIR/bool_comparison.rs:22:8 + --> $DIR/bool_comparison.rs:23:8 | LL | if false == x { | ^^^^^^^^^^ help: try simplifying it as shown: `!x` error: inequality checks against true can be replaced by a negation - --> $DIR/bool_comparison.rs:27:8 + --> $DIR/bool_comparison.rs:28:8 | LL | if x != true { | ^^^^^^^^^ help: try simplifying it as shown: `!x` error: inequality checks against false are unnecessary - --> $DIR/bool_comparison.rs:32:8 + --> $DIR/bool_comparison.rs:33:8 | LL | if x != false { | ^^^^^^^^^^ help: try simplifying it as shown: `x` error: inequality checks against true can be replaced by a negation - --> $DIR/bool_comparison.rs:37:8 + --> $DIR/bool_comparison.rs:38:8 | LL | if true != x { | ^^^^^^^^^ help: try simplifying it as shown: `!x` error: inequality checks against false are unnecessary - --> $DIR/bool_comparison.rs:42:8 + --> $DIR/bool_comparison.rs:43:8 | LL | if false != x { | ^^^^^^^^^^ help: try simplifying it as shown: `x` error: less than comparison against true can be replaced by a negation - --> $DIR/bool_comparison.rs:47:8 + --> $DIR/bool_comparison.rs:48:8 | LL | if x < true { | ^^^^^^^^ help: try simplifying it as shown: `!x` error: greater than checks against false are unnecessary - --> $DIR/bool_comparison.rs:52:8 + --> $DIR/bool_comparison.rs:53:8 | LL | if false < x { | ^^^^^^^^^ help: try simplifying it as shown: `x` error: greater than checks against false are unnecessary - --> $DIR/bool_comparison.rs:57:8 + --> $DIR/bool_comparison.rs:58:8 | LL | if x > false { | ^^^^^^^^^ help: try simplifying it as shown: `x` error: less than comparison against true can be replaced by a negation - --> $DIR/bool_comparison.rs:62:8 + --> $DIR/bool_comparison.rs:63:8 | LL | if true > x { | ^^^^^^^^ help: try simplifying it as shown: `!x` error: order comparisons between booleans can be simplified - --> $DIR/bool_comparison.rs:68:8 + --> $DIR/bool_comparison.rs:69:8 | LL | if x < y { | ^^^^^ help: try simplifying it as shown: `!x & y` error: order comparisons between booleans can be simplified - --> $DIR/bool_comparison.rs:73:8 + --> $DIR/bool_comparison.rs:74:8 | LL | if x > y { | ^^^^^ help: try simplifying it as shown: `x & !y` error: this comparison might be written more concisely - --> $DIR/bool_comparison.rs:121:8 + --> $DIR/bool_comparison.rs:122:8 | LL | if a == !b {}; | ^^^^^^^ help: try simplifying it as shown: `a != b` error: this comparison might be written more concisely - --> $DIR/bool_comparison.rs:122:8 + --> $DIR/bool_comparison.rs:123:8 | LL | if !a == b {}; | ^^^^^^^ help: try simplifying it as shown: `a != b` error: this comparison might be written more concisely - --> $DIR/bool_comparison.rs:126:8 + --> $DIR/bool_comparison.rs:127:8 | LL | if b == !a {}; | ^^^^^^^ help: try simplifying it as shown: `b != a` error: this comparison might be written more concisely - --> $DIR/bool_comparison.rs:127:8 + --> $DIR/bool_comparison.rs:128:8 | LL | if !b == a {}; | ^^^^^^^ help: try simplifying it as shown: `b != a` error: equality checks against false can be replaced by a negation - --> $DIR/bool_comparison.rs:151:8 + --> $DIR/bool_comparison.rs:152:8 | LL | if false == m!(func) {} | ^^^^^^^^^^^^^^^^^ help: try simplifying it as shown: `!m!(func)` error: equality checks against false can be replaced by a negation - --> $DIR/bool_comparison.rs:152:8 + --> $DIR/bool_comparison.rs:153:8 | LL | if m!(func) == false {} | ^^^^^^^^^^^^^^^^^ help: try simplifying it as shown: `!m!(func)` error: equality checks against true are unnecessary - --> $DIR/bool_comparison.rs:153:8 + --> $DIR/bool_comparison.rs:154:8 | LL | if true == m!(func) {} | ^^^^^^^^^^^^^^^^ help: try simplifying it as shown: `m!(func)` error: equality checks against true are unnecessary - --> $DIR/bool_comparison.rs:154:8 + --> $DIR/bool_comparison.rs:155:8 | LL | if m!(func) == true {} | ^^^^^^^^^^^^^^^^ help: try simplifying it as shown: `m!(func)` diff --git a/tests/ui/cmp_owned/asymmetric_partial_eq.fixed b/tests/ui/cmp_owned/asymmetric_partial_eq.fixed index 3bf3deb9b91..11834634856 100644 --- a/tests/ui/cmp_owned/asymmetric_partial_eq.fixed +++ b/tests/ui/cmp_owned/asymmetric_partial_eq.fixed @@ -1,5 +1,10 @@ //@run-rustfix -#![allow(unused, clippy::redundant_clone, clippy::derive_partial_eq_without_eq)] // See #5700 +#![allow( + unused, + clippy::needless_if, + clippy::redundant_clone, + clippy::derive_partial_eq_without_eq +)] // See #5700 // Define the types in each module to avoid trait impls leaking between modules. macro_rules! impl_types { diff --git a/tests/ui/cmp_owned/asymmetric_partial_eq.rs b/tests/ui/cmp_owned/asymmetric_partial_eq.rs index 10107dc8f86..3a25d53a5d0 100644 --- a/tests/ui/cmp_owned/asymmetric_partial_eq.rs +++ b/tests/ui/cmp_owned/asymmetric_partial_eq.rs @@ -1,5 +1,10 @@ //@run-rustfix -#![allow(unused, clippy::redundant_clone, clippy::derive_partial_eq_without_eq)] // See #5700 +#![allow( + unused, + clippy::needless_if, + clippy::redundant_clone, + clippy::derive_partial_eq_without_eq +)] // See #5700 // Define the types in each module to avoid trait impls leaking between modules. macro_rules! impl_types { diff --git a/tests/ui/cmp_owned/asymmetric_partial_eq.stderr b/tests/ui/cmp_owned/asymmetric_partial_eq.stderr index 43bf8851fc6..4714a0daaa6 100644 --- a/tests/ui/cmp_owned/asymmetric_partial_eq.stderr +++ b/tests/ui/cmp_owned/asymmetric_partial_eq.stderr @@ -1,5 +1,5 @@ error: this creates an owned instance just for comparison - --> $DIR/asymmetric_partial_eq.rs:42:12 + --> $DIR/asymmetric_partial_eq.rs:47:12 | LL | if borrowed.to_owned() == owned {} | ^^^^^^^^^^^^^^^^^^^ help: try: `borrowed` @@ -7,7 +7,7 @@ LL | if borrowed.to_owned() == owned {} = note: `-D clippy::cmp-owned` implied by `-D warnings` error: this creates an owned instance just for comparison - --> $DIR/asymmetric_partial_eq.rs:43:21 + --> $DIR/asymmetric_partial_eq.rs:48:21 | LL | if owned == borrowed.to_owned() {} | ---------^^^^^^^^^^^^^^^^^^^ @@ -15,13 +15,13 @@ LL | if owned == borrowed.to_owned() {} | help: try: `borrowed == owned` error: this creates an owned instance just for comparison - --> $DIR/asymmetric_partial_eq.rs:61:21 + --> $DIR/asymmetric_partial_eq.rs:66:21 | LL | if owned == borrowed.to_owned() {} | ^^^^^^^^^^^^^^^^^^^ help: try: `borrowed` error: this creates an owned instance just for comparison - --> $DIR/asymmetric_partial_eq.rs:62:12 + --> $DIR/asymmetric_partial_eq.rs:67:12 | LL | if borrowed.to_owned() == owned {} | ^^^^^^^^^^^^^^^^^^^--------- @@ -29,7 +29,7 @@ LL | if borrowed.to_owned() == owned {} | help: try: `owned == borrowed` error: this creates an owned instance just for comparison - --> $DIR/asymmetric_partial_eq.rs:88:20 + --> $DIR/asymmetric_partial_eq.rs:93:20 | LL | if "Hi" == borrowed.to_string() {} | --------^^^^^^^^^^^^^^^^^^^^ @@ -37,7 +37,7 @@ LL | if "Hi" == borrowed.to_string() {} | help: try: `borrowed == "Hi"` error: this creates an owned instance just for comparison - --> $DIR/asymmetric_partial_eq.rs:89:12 + --> $DIR/asymmetric_partial_eq.rs:94:12 | LL | if borrowed.to_string() == "Hi" {} | ^^^^^^^^^^^^^^^^^^^^ help: try: `borrowed` diff --git a/tests/ui/collapsible_else_if.fixed b/tests/ui/collapsible_else_if.fixed index 8302cec45e7..c4116cd8520 100644 --- a/tests/ui/collapsible_else_if.fixed +++ b/tests/ui/collapsible_else_if.fixed @@ -1,5 +1,5 @@ //@run-rustfix -#![allow(clippy::assertions_on_constants, clippy::equatable_if_let)] +#![allow(clippy::assertions_on_constants, clippy::equatable_if_let, clippy::needless_if)] #[rustfmt::skip] #[warn(clippy::collapsible_if)] diff --git a/tests/ui/collapsible_else_if.rs b/tests/ui/collapsible_else_if.rs index 5913dcf41ca..8f51d0ee508 100644 --- a/tests/ui/collapsible_else_if.rs +++ b/tests/ui/collapsible_else_if.rs @@ -1,5 +1,5 @@ //@run-rustfix -#![allow(clippy::assertions_on_constants, clippy::equatable_if_let)] +#![allow(clippy::assertions_on_constants, clippy::equatable_if_let, clippy::needless_if)] #[rustfmt::skip] #[warn(clippy::collapsible_if)] diff --git a/tests/ui/collapsible_if.fixed b/tests/ui/collapsible_if.fixed index c6514a55934..e305e1d7a87 100644 --- a/tests/ui/collapsible_if.fixed +++ b/tests/ui/collapsible_if.fixed @@ -2,6 +2,7 @@ #![allow( clippy::assertions_on_constants, clippy::equatable_if_let, + clippy::needless_if, clippy::nonminimal_bool, clippy::eq_op )] diff --git a/tests/ui/collapsible_if.rs b/tests/ui/collapsible_if.rs index 2c85b68df63..7c52959d3b5 100644 --- a/tests/ui/collapsible_if.rs +++ b/tests/ui/collapsible_if.rs @@ -2,6 +2,7 @@ #![allow( clippy::assertions_on_constants, clippy::equatable_if_let, + clippy::needless_if, clippy::nonminimal_bool, clippy::eq_op )] diff --git a/tests/ui/collapsible_if.stderr b/tests/ui/collapsible_if.stderr index c687bae1acc..4a1a9e8a60a 100644 --- a/tests/ui/collapsible_if.stderr +++ b/tests/ui/collapsible_if.stderr @@ -1,5 +1,5 @@ error: this `if` statement can be collapsed - --> $DIR/collapsible_if.rs:14:5 + --> $DIR/collapsible_if.rs:15:5 | LL | / if x == "hello" { LL | | if y == "world" { @@ -17,7 +17,7 @@ LL + } | error: this `if` statement can be collapsed - --> $DIR/collapsible_if.rs:20:5 + --> $DIR/collapsible_if.rs:21:5 | LL | / if x == "hello" || x == "world" { LL | | if y == "world" || y == "hello" { @@ -34,7 +34,7 @@ LL + } | error: this `if` statement can be collapsed - --> $DIR/collapsible_if.rs:26:5 + --> $DIR/collapsible_if.rs:27:5 | LL | / if x == "hello" && x == "world" { LL | | if y == "world" || y == "hello" { @@ -51,7 +51,7 @@ LL + } | error: this `if` statement can be collapsed - --> $DIR/collapsible_if.rs:32:5 + --> $DIR/collapsible_if.rs:33:5 | LL | / if x == "hello" || x == "world" { LL | | if y == "world" && y == "hello" { @@ -68,7 +68,7 @@ LL + } | error: this `if` statement can be collapsed - --> $DIR/collapsible_if.rs:38:5 + --> $DIR/collapsible_if.rs:39:5 | LL | / if x == "hello" && x == "world" { LL | | if y == "world" && y == "hello" { @@ -85,7 +85,7 @@ LL + } | error: this `if` statement can be collapsed - --> $DIR/collapsible_if.rs:44:5 + --> $DIR/collapsible_if.rs:45:5 | LL | / if 42 == 1337 { LL | | if 'a' != 'A' { @@ -102,7 +102,7 @@ LL + } | error: this `if` statement can be collapsed - --> $DIR/collapsible_if.rs:100:5 + --> $DIR/collapsible_if.rs:101:5 | LL | / if x == "hello" { LL | | if y == "world" { // Collapsible @@ -119,7 +119,7 @@ LL + } | error: this `if` statement can be collapsed - --> $DIR/collapsible_if.rs:159:5 + --> $DIR/collapsible_if.rs:160:5 | LL | / if matches!(true, true) { LL | | if matches!(true, true) {} @@ -127,7 +127,7 @@ LL | | } | |_____^ help: collapse nested if block: `if matches!(true, true) && matches!(true, true) {}` error: this `if` statement can be collapsed - --> $DIR/collapsible_if.rs:164:5 + --> $DIR/collapsible_if.rs:165:5 | LL | / if matches!(true, true) && truth() { LL | | if matches!(true, true) {} diff --git a/tests/ui/crashes/ice-3462.rs b/tests/ui/crashes/ice-3462.rs index b402052882a..21cd9d337cd 100644 --- a/tests/ui/crashes/ice-3462.rs +++ b/tests/ui/crashes/ice-3462.rs @@ -1,5 +1,5 @@ #![warn(clippy::all)] -#![allow(clippy::disallowed_names, clippy::equatable_if_let)] +#![allow(clippy::disallowed_names, clippy::equatable_if_let, clippy::needless_if)] #![allow(unused)] /// Test for https://github.com/rust-lang/rust-clippy/issues/3462 diff --git a/tests/ui/crashes/ice-7169.rs b/tests/ui/crashes/ice-7169.rs index 82095febc19..b203252f0a1 100644 --- a/tests/ui/crashes/ice-7169.rs +++ b/tests/ui/crashes/ice-7169.rs @@ -1,3 +1,5 @@ +#![allow(clippy::needless_if)] + #[derive(Default)] struct A { a: Vec>, diff --git a/tests/ui/crashes/ice-7169.stderr b/tests/ui/crashes/ice-7169.stderr index 5a9cd32380a..84e0af3f0d0 100644 --- a/tests/ui/crashes/ice-7169.stderr +++ b/tests/ui/crashes/ice-7169.stderr @@ -1,5 +1,5 @@ error: redundant pattern matching, consider using `is_ok()` - --> $DIR/ice-7169.rs:8:12 + --> $DIR/ice-7169.rs:10:12 | LL | if let Ok(_) = Ok::<_, ()>(A::::default()) {} | -------^^^^^-------------------------------------- help: try this: `if Ok::<_, ()>(A::::default()).is_ok()` diff --git a/tests/ui/disallowed_names.rs b/tests/ui/disallowed_names.rs index e937c49f389..5889f04439f 100644 --- a/tests/ui/disallowed_names.rs +++ b/tests/ui/disallowed_names.rs @@ -1,5 +1,6 @@ #![allow( dead_code, + clippy::needless_if, clippy::similar_names, clippy::single_match, clippy::toplevel_ref_arg, diff --git a/tests/ui/disallowed_names.stderr b/tests/ui/disallowed_names.stderr index 78cb55096ff..9ab68b641f1 100644 --- a/tests/ui/disallowed_names.stderr +++ b/tests/ui/disallowed_names.stderr @@ -1,5 +1,5 @@ error: use of a disallowed/placeholder name `foo` - --> $DIR/disallowed_names.rs:11:9 + --> $DIR/disallowed_names.rs:12:9 | LL | fn test(foo: ()) {} | ^^^ @@ -7,79 +7,79 @@ LL | fn test(foo: ()) {} = note: `-D clippy::disallowed-names` implied by `-D warnings` error: use of a disallowed/placeholder name `foo` - --> $DIR/disallowed_names.rs:14:9 + --> $DIR/disallowed_names.rs:15:9 | LL | let foo = 42; | ^^^ error: use of a disallowed/placeholder name `baz` - --> $DIR/disallowed_names.rs:15:9 + --> $DIR/disallowed_names.rs:16:9 | LL | let baz = 42; | ^^^ error: use of a disallowed/placeholder name `quux` - --> $DIR/disallowed_names.rs:16:9 + --> $DIR/disallowed_names.rs:17:9 | LL | let quux = 42; | ^^^^ error: use of a disallowed/placeholder name `foo` - --> $DIR/disallowed_names.rs:27:10 + --> $DIR/disallowed_names.rs:28:10 | LL | (foo, Some(baz), quux @ Some(_)) => (), | ^^^ error: use of a disallowed/placeholder name `baz` - --> $DIR/disallowed_names.rs:27:20 + --> $DIR/disallowed_names.rs:28:20 | LL | (foo, Some(baz), quux @ Some(_)) => (), | ^^^ error: use of a disallowed/placeholder name `quux` - --> $DIR/disallowed_names.rs:27:26 + --> $DIR/disallowed_names.rs:28:26 | LL | (foo, Some(baz), quux @ Some(_)) => (), | ^^^^ error: use of a disallowed/placeholder name `foo` - --> $DIR/disallowed_names.rs:32:19 + --> $DIR/disallowed_names.rs:33:19 | LL | fn issue_1647(mut foo: u8) { | ^^^ error: use of a disallowed/placeholder name `baz` - --> $DIR/disallowed_names.rs:33:13 + --> $DIR/disallowed_names.rs:34:13 | LL | let mut baz = 0; | ^^^ error: use of a disallowed/placeholder name `quux` - --> $DIR/disallowed_names.rs:34:21 + --> $DIR/disallowed_names.rs:35:21 | LL | if let Some(mut quux) = Some(42) {} | ^^^^ error: use of a disallowed/placeholder name `baz` - --> $DIR/disallowed_names.rs:38:13 + --> $DIR/disallowed_names.rs:39:13 | LL | let ref baz = 0; | ^^^ error: use of a disallowed/placeholder name `quux` - --> $DIR/disallowed_names.rs:39:21 + --> $DIR/disallowed_names.rs:40:21 | LL | if let Some(ref quux) = Some(42) {} | ^^^^ error: use of a disallowed/placeholder name `baz` - --> $DIR/disallowed_names.rs:43:17 + --> $DIR/disallowed_names.rs:44:17 | LL | let ref mut baz = 0; | ^^^ error: use of a disallowed/placeholder name `quux` - --> $DIR/disallowed_names.rs:44:25 + --> $DIR/disallowed_names.rs:45:25 | LL | if let Some(ref mut quux) = Some(42) {} | ^^^^ diff --git a/tests/ui/double_comparison.fixed b/tests/ui/double_comparison.fixed index c80ff671a5d..f8ca92ef0b3 100644 --- a/tests/ui/double_comparison.fixed +++ b/tests/ui/double_comparison.fixed @@ -1,4 +1,5 @@ //@run-rustfix +#![allow(clippy::needless_if)] fn main() { let x = 1; diff --git a/tests/ui/double_comparison.rs b/tests/ui/double_comparison.rs index bc78694aa68..47ff87bea0a 100644 --- a/tests/ui/double_comparison.rs +++ b/tests/ui/double_comparison.rs @@ -1,4 +1,5 @@ //@run-rustfix +#![allow(clippy::needless_if)] fn main() { let x = 1; diff --git a/tests/ui/double_comparison.stderr b/tests/ui/double_comparison.stderr index 05ef4e25f7f..4df1c28ac48 100644 --- a/tests/ui/double_comparison.stderr +++ b/tests/ui/double_comparison.stderr @@ -1,5 +1,5 @@ error: this binary expression can be simplified - --> $DIR/double_comparison.rs:6:8 + --> $DIR/double_comparison.rs:7:8 | LL | if x == y || x < y { | ^^^^^^^^^^^^^^^ help: try: `x <= y` @@ -7,43 +7,43 @@ LL | if x == y || x < y { = note: `-D clippy::double-comparisons` implied by `-D warnings` error: this binary expression can be simplified - --> $DIR/double_comparison.rs:9:8 + --> $DIR/double_comparison.rs:10:8 | LL | if x < y || x == y { | ^^^^^^^^^^^^^^^ help: try: `x <= y` error: this binary expression can be simplified - --> $DIR/double_comparison.rs:12:8 + --> $DIR/double_comparison.rs:13:8 | LL | if x == y || x > y { | ^^^^^^^^^^^^^^^ help: try: `x >= y` error: this binary expression can be simplified - --> $DIR/double_comparison.rs:15:8 + --> $DIR/double_comparison.rs:16:8 | LL | if x > y || x == y { | ^^^^^^^^^^^^^^^ help: try: `x >= y` error: this binary expression can be simplified - --> $DIR/double_comparison.rs:18:8 + --> $DIR/double_comparison.rs:19:8 | LL | if x < y || x > y { | ^^^^^^^^^^^^^^ help: try: `x != y` error: this binary expression can be simplified - --> $DIR/double_comparison.rs:21:8 + --> $DIR/double_comparison.rs:22:8 | LL | if x > y || x < y { | ^^^^^^^^^^^^^^ help: try: `x != y` error: this binary expression can be simplified - --> $DIR/double_comparison.rs:24:8 + --> $DIR/double_comparison.rs:25:8 | LL | if x <= y && x >= y { | ^^^^^^^^^^^^^^^^ help: try: `x == y` error: this binary expression can be simplified - --> $DIR/double_comparison.rs:27:8 + --> $DIR/double_comparison.rs:28:8 | LL | if x >= y && x <= y { | ^^^^^^^^^^^^^^^^ help: try: `x == y` diff --git a/tests/ui/equatable_if_let.fixed b/tests/ui/equatable_if_let.fixed index 53e62760bef..1869301d224 100644 --- a/tests/ui/equatable_if_let.fixed +++ b/tests/ui/equatable_if_let.fixed @@ -1,7 +1,12 @@ //@run-rustfix //@aux-build:proc_macros.rs -#![allow(unused_variables, dead_code, clippy::derive_partial_eq_without_eq)] +#![allow( + unused_variables, + dead_code, + clippy::derive_partial_eq_without_eq, + clippy::needless_if +)] #![warn(clippy::equatable_if_let)] extern crate proc_macros; diff --git a/tests/ui/equatable_if_let.rs b/tests/ui/equatable_if_let.rs index 55918a5bb11..a78aec74a7b 100644 --- a/tests/ui/equatable_if_let.rs +++ b/tests/ui/equatable_if_let.rs @@ -1,7 +1,12 @@ //@run-rustfix //@aux-build:proc_macros.rs -#![allow(unused_variables, dead_code, clippy::derive_partial_eq_without_eq)] +#![allow( + unused_variables, + dead_code, + clippy::derive_partial_eq_without_eq, + clippy::needless_if +)] #![warn(clippy::equatable_if_let)] extern crate proc_macros; diff --git a/tests/ui/equatable_if_let.stderr b/tests/ui/equatable_if_let.stderr index a72d87bb7ba..649495dded7 100644 --- a/tests/ui/equatable_if_let.stderr +++ b/tests/ui/equatable_if_let.stderr @@ -1,5 +1,5 @@ error: this pattern matching can be expressed using equality - --> $DIR/equatable_if_let.rs:60:8 + --> $DIR/equatable_if_let.rs:65:8 | LL | if let 2 = a {} | ^^^^^^^^^ help: try: `a == 2` @@ -7,79 +7,79 @@ LL | if let 2 = a {} = note: `-D clippy::equatable-if-let` implied by `-D warnings` error: this pattern matching can be expressed using equality - --> $DIR/equatable_if_let.rs:61:8 + --> $DIR/equatable_if_let.rs:66:8 | LL | if let Ordering::Greater = a.cmp(&b) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `a.cmp(&b) == Ordering::Greater` error: this pattern matching can be expressed using equality - --> $DIR/equatable_if_let.rs:62:8 + --> $DIR/equatable_if_let.rs:67:8 | LL | if let Some(2) = c {} | ^^^^^^^^^^^^^^^ help: try: `c == Some(2)` error: this pattern matching can be expressed using equality - --> $DIR/equatable_if_let.rs:63:8 + --> $DIR/equatable_if_let.rs:68:8 | LL | if let Struct { a: 2, b: false } = d {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `d == (Struct { a: 2, b: false })` error: this pattern matching can be expressed using equality - --> $DIR/equatable_if_let.rs:64:8 + --> $DIR/equatable_if_let.rs:69:8 | LL | if let Enum::TupleVariant(32, 64) = e {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `e == Enum::TupleVariant(32, 64)` error: this pattern matching can be expressed using equality - --> $DIR/equatable_if_let.rs:65:8 + --> $DIR/equatable_if_let.rs:70:8 | LL | if let Enum::RecordVariant { a: 64, b: 32 } = e {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `e == (Enum::RecordVariant { a: 64, b: 32 })` error: this pattern matching can be expressed using equality - --> $DIR/equatable_if_let.rs:66:8 + --> $DIR/equatable_if_let.rs:71:8 | LL | if let Enum::UnitVariant = e {} | ^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `e == Enum::UnitVariant` error: this pattern matching can be expressed using equality - --> $DIR/equatable_if_let.rs:67:8 + --> $DIR/equatable_if_let.rs:72:8 | LL | if let (Enum::UnitVariant, &Struct { a: 2, b: false }) = (e, &d) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `(e, &d) == (Enum::UnitVariant, &Struct { a: 2, b: false })` error: this pattern matching can be expressed using `matches!` - --> $DIR/equatable_if_let.rs:76:8 + --> $DIR/equatable_if_let.rs:81:8 | LL | if let NotPartialEq::A = f {} | ^^^^^^^^^^^^^^^^^^^^^^^ help: try: `matches!(f, NotPartialEq::A)` error: this pattern matching can be expressed using equality - --> $DIR/equatable_if_let.rs:77:8 + --> $DIR/equatable_if_let.rs:82:8 | LL | if let NotStructuralEq::A = g {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `g == NotStructuralEq::A` error: this pattern matching can be expressed using `matches!` - --> $DIR/equatable_if_let.rs:78:8 + --> $DIR/equatable_if_let.rs:83:8 | LL | if let Some(NotPartialEq::A) = Some(f) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `matches!(Some(f), Some(NotPartialEq::A))` error: this pattern matching can be expressed using equality - --> $DIR/equatable_if_let.rs:79:8 + --> $DIR/equatable_if_let.rs:84:8 | LL | if let Some(NotStructuralEq::A) = Some(g) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `Some(g) == Some(NotStructuralEq::A)` error: this pattern matching can be expressed using `matches!` - --> $DIR/equatable_if_let.rs:80:8 + --> $DIR/equatable_if_let.rs:85:8 | LL | if let NoPartialEqStruct { a: 2, b: false } = h {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `matches!(h, NoPartialEqStruct { a: 2, b: false })` error: this pattern matching can be expressed using equality - --> $DIR/equatable_if_let.rs:82:8 + --> $DIR/equatable_if_let.rs:87:8 | LL | if let inline!("abc") = "abc" { | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `"abc" == inline!("abc")` diff --git a/tests/ui/expect_tool_lint_rfc_2383.rs b/tests/ui/expect_tool_lint_rfc_2383.rs index ca81808a863..7963bf0f3a6 100644 --- a/tests/ui/expect_tool_lint_rfc_2383.rs +++ b/tests/ui/expect_tool_lint_rfc_2383.rs @@ -11,6 +11,7 @@ //! This test can't cover every lint from Clippy, rustdoc and potentially other //! tools that will be developed. This therefore only tests a small subset of lints #![expect(rustdoc::missing_crate_level_docs)] +#![allow(clippy::needless_if)] mod rustc_ok { //! See diff --git a/tests/ui/expect_tool_lint_rfc_2383.stderr b/tests/ui/expect_tool_lint_rfc_2383.stderr index 77210ca7a9d..7ce9e855b5e 100644 --- a/tests/ui/expect_tool_lint_rfc_2383.stderr +++ b/tests/ui/expect_tool_lint_rfc_2383.stderr @@ -1,5 +1,5 @@ error: this lint expectation is unfulfilled - --> $DIR/expect_tool_lint_rfc_2383.rs:34:14 + --> $DIR/expect_tool_lint_rfc_2383.rs:35:14 | LL | #[expect(dead_code)] | ^^^^^^^^^ @@ -7,31 +7,31 @@ LL | #[expect(dead_code)] = note: `-D unfulfilled-lint-expectations` implied by `-D warnings` error: this lint expectation is unfulfilled - --> $DIR/expect_tool_lint_rfc_2383.rs:38:18 + --> $DIR/expect_tool_lint_rfc_2383.rs:39:18 | LL | #[expect(illegal_floating_point_literal_pattern)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: this lint expectation is unfulfilled - --> $DIR/expect_tool_lint_rfc_2383.rs:112:14 + --> $DIR/expect_tool_lint_rfc_2383.rs:113:14 | LL | #[expect(clippy::almost_swapped)] | ^^^^^^^^^^^^^^^^^^^^^^ error: this lint expectation is unfulfilled - --> $DIR/expect_tool_lint_rfc_2383.rs:119:14 + --> $DIR/expect_tool_lint_rfc_2383.rs:120:14 | LL | #[expect(clippy::bytes_nth)] | ^^^^^^^^^^^^^^^^^ error: this lint expectation is unfulfilled - --> $DIR/expect_tool_lint_rfc_2383.rs:124:14 + --> $DIR/expect_tool_lint_rfc_2383.rs:125:14 | LL | #[expect(clippy::if_same_then_else)] | ^^^^^^^^^^^^^^^^^^^^^^^^^ error: this lint expectation is unfulfilled - --> $DIR/expect_tool_lint_rfc_2383.rs:129:14 + --> $DIR/expect_tool_lint_rfc_2383.rs:130:14 | LL | #[expect(clippy::overly_complex_bool_expr)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/filetype_is_file.rs b/tests/ui/filetype_is_file.rs index 5de8fe8cdd7..d3ad36e40b5 100644 --- a/tests/ui/filetype_is_file.rs +++ b/tests/ui/filetype_is_file.rs @@ -1,3 +1,4 @@ +#![allow(clippy::needless_if)] #![warn(clippy::filetype_is_file)] fn main() -> std::io::Result<()> { diff --git a/tests/ui/filetype_is_file.stderr b/tests/ui/filetype_is_file.stderr index e51a90d6cfd..36142deb309 100644 --- a/tests/ui/filetype_is_file.stderr +++ b/tests/ui/filetype_is_file.stderr @@ -1,5 +1,5 @@ error: `FileType::is_file()` only covers regular files - --> $DIR/filetype_is_file.rs:8:8 + --> $DIR/filetype_is_file.rs:9:8 | LL | if fs::metadata("foo.txt")?.file_type().is_file() { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -8,7 +8,7 @@ LL | if fs::metadata("foo.txt")?.file_type().is_file() { = note: `-D clippy::filetype-is-file` implied by `-D warnings` error: `!FileType::is_file()` only denies regular files - --> $DIR/filetype_is_file.rs:13:8 + --> $DIR/filetype_is_file.rs:14:8 | LL | if !fs::metadata("foo.txt")?.file_type().is_file() { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -16,7 +16,7 @@ LL | if !fs::metadata("foo.txt")?.file_type().is_file() { = help: use `FileType::is_dir()` instead error: `FileType::is_file()` only covers regular files - --> $DIR/filetype_is_file.rs:18:9 + --> $DIR/filetype_is_file.rs:19:9 | LL | if !fs::metadata("foo.txt")?.file_type().is_file().bitor(true) { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/fn_null_check.rs b/tests/ui/fn_null_check.rs index df5bc8420d5..dfdea100c8f 100644 --- a/tests/ui/fn_null_check.rs +++ b/tests/ui/fn_null_check.rs @@ -1,6 +1,7 @@ #![allow(unused)] #![warn(clippy::fn_null_check)] #![allow(clippy::cmp_null)] +#![allow(clippy::needless_if)] #![allow(clippy::ptr_eq)] #![allow(clippy::zero_ptr)] diff --git a/tests/ui/fn_null_check.stderr b/tests/ui/fn_null_check.stderr index 660dd323979..5b9f48a961c 100644 --- a/tests/ui/fn_null_check.stderr +++ b/tests/ui/fn_null_check.stderr @@ -1,5 +1,5 @@ error: function pointer assumed to be nullable, even though it isn't - --> $DIR/fn_null_check.rs:13:8 + --> $DIR/fn_null_check.rs:14:8 | LL | if (fn_ptr as *mut ()).is_null() {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -8,7 +8,7 @@ LL | if (fn_ptr as *mut ()).is_null() {} = note: `-D clippy::fn-null-check` implied by `-D warnings` error: function pointer assumed to be nullable, even though it isn't - --> $DIR/fn_null_check.rs:14:8 + --> $DIR/fn_null_check.rs:15:8 | LL | if (fn_ptr as *const u8).is_null() {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -16,7 +16,7 @@ LL | if (fn_ptr as *const u8).is_null() {} = help: try wrapping your function pointer type in `Option` instead, and using `is_none` to check for null pointer value error: function pointer assumed to be nullable, even though it isn't - --> $DIR/fn_null_check.rs:15:8 + --> $DIR/fn_null_check.rs:16:8 | LL | if (fn_ptr as *const ()) == std::ptr::null() {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -24,7 +24,7 @@ LL | if (fn_ptr as *const ()) == std::ptr::null() {} = help: try wrapping your function pointer type in `Option` instead, and using `is_none` to check for null pointer value error: function pointer assumed to be nullable, even though it isn't - --> $DIR/fn_null_check.rs:16:8 + --> $DIR/fn_null_check.rs:17:8 | LL | if (fn_ptr as *const ()) == (0 as *const ()) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -32,7 +32,7 @@ LL | if (fn_ptr as *const ()) == (0 as *const ()) {} = help: try wrapping your function pointer type in `Option` instead, and using `is_none` to check for null pointer value error: function pointer assumed to be nullable, even though it isn't - --> $DIR/fn_null_check.rs:17:8 + --> $DIR/fn_null_check.rs:18:8 | LL | if (fn_ptr as *const ()) == ZPTR {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/if_same_then_else2.rs b/tests/ui/if_same_then_else2.rs index 58167f4446d..3b9b029d354 100644 --- a/tests/ui/if_same_then_else2.rs +++ b/tests/ui/if_same_then_else2.rs @@ -5,6 +5,7 @@ clippy::equatable_if_let, clippy::collapsible_if, clippy::ifs_same_cond, + clippy::needless_if, clippy::needless_return, clippy::single_element_loop, clippy::branches_sharing_code diff --git a/tests/ui/if_same_then_else2.stderr b/tests/ui/if_same_then_else2.stderr index 704cfd9669a..a4d8a74167e 100644 --- a/tests/ui/if_same_then_else2.stderr +++ b/tests/ui/if_same_then_else2.stderr @@ -1,5 +1,5 @@ error: this `if` has identical blocks - --> $DIR/if_same_then_else2.rs:14:13 + --> $DIR/if_same_then_else2.rs:15:13 | LL | if true { | _____________^ @@ -12,7 +12,7 @@ LL | | } else { | |_____^ | note: same as this - --> $DIR/if_same_then_else2.rs:23:12 + --> $DIR/if_same_then_else2.rs:24:12 | LL | } else { | ____________^ @@ -26,7 +26,7 @@ LL | | } = note: `-D clippy::if-same-then-else` implied by `-D warnings` error: this `if` has identical blocks - --> $DIR/if_same_then_else2.rs:35:13 + --> $DIR/if_same_then_else2.rs:36:13 | LL | if true { | _____________^ @@ -35,7 +35,7 @@ LL | | } else { | |_____^ | note: same as this - --> $DIR/if_same_then_else2.rs:37:12 + --> $DIR/if_same_then_else2.rs:38:12 | LL | } else { | ____________^ @@ -45,7 +45,7 @@ LL | | } | |_____^ error: this `if` has identical blocks - --> $DIR/if_same_then_else2.rs:42:13 + --> $DIR/if_same_then_else2.rs:43:13 | LL | if true { | _____________^ @@ -54,7 +54,7 @@ LL | | } else { | |_____^ | note: same as this - --> $DIR/if_same_then_else2.rs:44:12 + --> $DIR/if_same_then_else2.rs:45:12 | LL | } else { | ____________^ @@ -64,7 +64,7 @@ LL | | } | |_____^ error: this `if` has identical blocks - --> $DIR/if_same_then_else2.rs:92:21 + --> $DIR/if_same_then_else2.rs:93:21 | LL | let _ = if true { | _____________________^ @@ -73,7 +73,7 @@ LL | | } else { | |_____^ | note: same as this - --> $DIR/if_same_then_else2.rs:94:12 + --> $DIR/if_same_then_else2.rs:95:12 | LL | } else { | ____________^ @@ -83,7 +83,7 @@ LL | | }; | |_____^ error: this `if` has identical blocks - --> $DIR/if_same_then_else2.rs:99:13 + --> $DIR/if_same_then_else2.rs:100:13 | LL | if true { | _____________^ @@ -92,7 +92,7 @@ LL | | } else { | |_____^ | note: same as this - --> $DIR/if_same_then_else2.rs:101:12 + --> $DIR/if_same_then_else2.rs:102:12 | LL | } else { | ____________^ @@ -102,7 +102,7 @@ LL | | } | |_____^ error: this `if` has identical blocks - --> $DIR/if_same_then_else2.rs:123:20 + --> $DIR/if_same_then_else2.rs:124:20 | LL | } else if true { | ____________________^ @@ -112,7 +112,7 @@ LL | | } else { | |_____^ | note: same as this - --> $DIR/if_same_then_else2.rs:126:12 + --> $DIR/if_same_then_else2.rs:127:12 | LL | } else { | ____________^ diff --git a/tests/ui/ifs_same_cond.rs b/tests/ui/ifs_same_cond.rs index f62da157d1b..c321b08909f 100644 --- a/tests/ui/ifs_same_cond.rs +++ b/tests/ui/ifs_same_cond.rs @@ -1,5 +1,10 @@ #![warn(clippy::ifs_same_cond)] -#![allow(clippy::if_same_then_else, clippy::comparison_chain, clippy::needless_else)] // all empty blocks +#![allow( + clippy::if_same_then_else, + clippy::comparison_chain, + clippy::needless_if, + clippy::needless_else +)] // all empty blocks fn ifs_same_cond() { let a = 0; diff --git a/tests/ui/ifs_same_cond.stderr b/tests/ui/ifs_same_cond.stderr index 9519f6904cb..8d70934476c 100644 --- a/tests/ui/ifs_same_cond.stderr +++ b/tests/ui/ifs_same_cond.stderr @@ -1,48 +1,48 @@ error: this `if` has the same condition as a previous `if` - --> $DIR/ifs_same_cond.rs:9:15 + --> $DIR/ifs_same_cond.rs:14:15 | LL | } else if b { | ^ | note: same as this - --> $DIR/ifs_same_cond.rs:8:8 + --> $DIR/ifs_same_cond.rs:13:8 | LL | if b { | ^ = note: `-D clippy::ifs-same-cond` implied by `-D warnings` error: this `if` has the same condition as a previous `if` - --> $DIR/ifs_same_cond.rs:14:15 + --> $DIR/ifs_same_cond.rs:19:15 | LL | } else if a == 1 { | ^^^^^^ | note: same as this - --> $DIR/ifs_same_cond.rs:13:8 + --> $DIR/ifs_same_cond.rs:18:8 | LL | if a == 1 { | ^^^^^^ error: this `if` has the same condition as a previous `if` - --> $DIR/ifs_same_cond.rs:20:15 + --> $DIR/ifs_same_cond.rs:25:15 | LL | } else if 2 * a == 1 { | ^^^^^^^^^^ | note: same as this - --> $DIR/ifs_same_cond.rs:18:8 + --> $DIR/ifs_same_cond.rs:23:8 | LL | if 2 * a == 1 { | ^^^^^^^^^^ error: this `if` has the same condition as a previous `if` - --> $DIR/ifs_same_cond.rs:49:15 + --> $DIR/ifs_same_cond.rs:54:15 | LL | } else if a.contains("ah") { | ^^^^^^^^^^^^^^^^ | note: same as this - --> $DIR/ifs_same_cond.rs:48:8 + --> $DIR/ifs_same_cond.rs:53:8 | LL | if a.contains("ah") { | ^^^^^^^^^^^^^^^^ diff --git a/tests/ui/len_zero.fixed b/tests/ui/len_zero.fixed index 2c22abd7e4b..fafee6a0d41 100644 --- a/tests/ui/len_zero.fixed +++ b/tests/ui/len_zero.fixed @@ -1,7 +1,7 @@ //@run-rustfix #![warn(clippy::len_zero)] -#![allow(dead_code, unused, clippy::len_without_is_empty)] +#![allow(dead_code, unused, clippy::needless_if, clippy::len_without_is_empty)] extern crate core; use core::ops::Deref; diff --git a/tests/ui/len_zero.rs b/tests/ui/len_zero.rs index a011ff97644..6a9006c4779 100644 --- a/tests/ui/len_zero.rs +++ b/tests/ui/len_zero.rs @@ -1,7 +1,7 @@ //@run-rustfix #![warn(clippy::len_zero)] -#![allow(dead_code, unused, clippy::len_without_is_empty)] +#![allow(dead_code, unused, clippy::needless_if, clippy::len_without_is_empty)] extern crate core; use core::ops::Deref; diff --git a/tests/ui/manual_let_else.rs b/tests/ui/manual_let_else.rs index b5c2a5dba34..46241afec94 100644 --- a/tests/ui/manual_let_else.rs +++ b/tests/ui/manual_let_else.rs @@ -4,7 +4,8 @@ clippy::unused_unit, clippy::let_unit_value, clippy::match_single_binding, - clippy::never_loop + clippy::never_loop, + clippy::needless_if )] #![warn(clippy::manual_let_else)] diff --git a/tests/ui/manual_let_else.stderr b/tests/ui/manual_let_else.stderr index 9d4aef4cad6..1eada4f992e 100644 --- a/tests/ui/manual_let_else.stderr +++ b/tests/ui/manual_let_else.stderr @@ -1,5 +1,5 @@ error: this could be rewritten as `let...else` - --> $DIR/manual_let_else.rs:24:5 + --> $DIR/manual_let_else.rs:25:5 | LL | let v = if let Some(v_some) = g() { v_some } else { return }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider writing: `let Some(v) = g() else { return };` @@ -7,7 +7,7 @@ LL | let v = if let Some(v_some) = g() { v_some } else { return }; = note: `-D clippy::manual-let-else` implied by `-D warnings` error: this could be rewritten as `let...else` - --> $DIR/manual_let_else.rs:25:5 + --> $DIR/manual_let_else.rs:26:5 | LL | / let v = if let Some(v_some) = g() { LL | | v_some @@ -24,7 +24,7 @@ LL + }; | error: this could be rewritten as `let...else` - --> $DIR/manual_let_else.rs:31:5 + --> $DIR/manual_let_else.rs:32:5 | LL | / let v = if let Some(v) = g() { LL | | // Blocks around the identity should have no impact @@ -45,25 +45,25 @@ LL + }; | error: this could be rewritten as `let...else` - --> $DIR/manual_let_else.rs:44:9 + --> $DIR/manual_let_else.rs:45:9 | LL | let v = if let Some(v_some) = g() { v_some } else { continue }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider writing: `let Some(v) = g() else { continue };` error: this could be rewritten as `let...else` - --> $DIR/manual_let_else.rs:45:9 + --> $DIR/manual_let_else.rs:46:9 | LL | let v = if let Some(v_some) = g() { v_some } else { break }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider writing: `let Some(v) = g() else { break };` error: this could be rewritten as `let...else` - --> $DIR/manual_let_else.rs:49:5 + --> $DIR/manual_let_else.rs:50:5 | LL | let v = if let Some(v_some) = g() { v_some } else { panic!() }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider writing: `let Some(v) = g() else { panic!() };` error: this could be rewritten as `let...else` - --> $DIR/manual_let_else.rs:52:5 + --> $DIR/manual_let_else.rs:53:5 | LL | / let v = if let Some(v_some) = g() { LL | | v_some @@ -80,7 +80,7 @@ LL + }; | error: this could be rewritten as `let...else` - --> $DIR/manual_let_else.rs:59:5 + --> $DIR/manual_let_else.rs:60:5 | LL | / let v = if let Some(v_some) = g() { LL | | v_some @@ -97,7 +97,7 @@ LL + }; | error: this could be rewritten as `let...else` - --> $DIR/manual_let_else.rs:66:5 + --> $DIR/manual_let_else.rs:67:5 | LL | / let v = if let Some(v_some) = g() { LL | | v_some @@ -116,7 +116,7 @@ LL + }; | error: this could be rewritten as `let...else` - --> $DIR/manual_let_else.rs:76:5 + --> $DIR/manual_let_else.rs:77:5 | LL | / let v = if let Some(v_some) = g() { LL | | v_some @@ -138,13 +138,13 @@ LL + }; | error: this could be rewritten as `let...else` - --> $DIR/manual_let_else.rs:86:5 + --> $DIR/manual_let_else.rs:87:5 | LL | let v = if let Some(v_some) = g() { v_some } else { if panic!() {} }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider writing: `let Some(v) = g() else { if panic!() {} };` error: this could be rewritten as `let...else` - --> $DIR/manual_let_else.rs:89:5 + --> $DIR/manual_let_else.rs:90:5 | LL | / let v = if let Some(v_some) = g() { LL | | v_some @@ -165,7 +165,7 @@ LL + }; | error: this could be rewritten as `let...else` - --> $DIR/manual_let_else.rs:98:5 + --> $DIR/manual_let_else.rs:99:5 | LL | / let v = if let Some(v_some) = g() { LL | | v_some @@ -186,7 +186,7 @@ LL + } }; | error: this could be rewritten as `let...else` - --> $DIR/manual_let_else.rs:107:5 + --> $DIR/manual_let_else.rs:108:5 | LL | / let v = if let Some(v_some) = g() { LL | | v_some @@ -215,7 +215,7 @@ LL + }; | error: this could be rewritten as `let...else` - --> $DIR/manual_let_else.rs:124:5 + --> $DIR/manual_let_else.rs:125:5 | LL | / let (v, w) = if let Some(v_some) = g().map(|v| (v, 42)) { LL | | v_some @@ -232,7 +232,7 @@ LL + }; | error: this could be rewritten as `let...else` - --> $DIR/manual_let_else.rs:131:5 + --> $DIR/manual_let_else.rs:132:5 | LL | / let (w, S { v }) = if let (Some(v_some), w_some) = (g().map(|_| S { v: 0 }), 0) { LL | | (w_some, v_some) @@ -249,7 +249,7 @@ LL + }; | error: this could be rewritten as `let...else` - --> $DIR/manual_let_else.rs:140:13 + --> $DIR/manual_let_else.rs:141:13 | LL | let $n = if let Some(v) = $e { v } else { return }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider writing: `let Some($n) = g() else { return };` @@ -260,19 +260,19 @@ LL | create_binding_if_some!(w, g()); = note: this error originates in the macro `create_binding_if_some` (in Nightly builds, run with -Z macro-backtrace for more info) error: this could be rewritten as `let...else` - --> $DIR/manual_let_else.rs:149:5 + --> $DIR/manual_let_else.rs:150:5 | LL | let v = if let Variant::A(a, 0) = e() { a } else { return }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider writing: `let Variant::A(v, 0) = e() else { return };` error: this could be rewritten as `let...else` - --> $DIR/manual_let_else.rs:152:5 + --> $DIR/manual_let_else.rs:153:5 | LL | let mut v = if let Variant::B(b) = e() { b } else { return }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider writing: `let Variant::B(mut v) = e() else { return };` error: this could be rewritten as `let...else` - --> $DIR/manual_let_else.rs:156:5 + --> $DIR/manual_let_else.rs:157:5 | LL | / let v = if let Ok(Some(Variant::B(b))) | Err(Some(Variant::A(b, _))) = nested { LL | | b @@ -289,19 +289,19 @@ LL + }; | error: this could be rewritten as `let...else` - --> $DIR/manual_let_else.rs:162:5 + --> $DIR/manual_let_else.rs:163:5 | LL | let v = if let Variant::A(.., a) = e() { a } else { return }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider writing: `let Variant::A(.., v) = e() else { return };` error: this could be rewritten as `let...else` - --> $DIR/manual_let_else.rs:165:5 + --> $DIR/manual_let_else.rs:166:5 | LL | let w = if let (Some(v), ()) = (g(), ()) { v } else { return }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider writing: `let (Some(w), ()) = (g(), ()) else { return };` error: this could be rewritten as `let...else` - --> $DIR/manual_let_else.rs:168:5 + --> $DIR/manual_let_else.rs:169:5 | LL | / let w = if let Some(S { v: x }) = Some(S { v: 0 }) { LL | | x @@ -318,7 +318,7 @@ LL + }; | error: this could be rewritten as `let...else` - --> $DIR/manual_let_else.rs:175:5 + --> $DIR/manual_let_else.rs:176:5 | LL | / let v = if let Some(S { v: x }) = Some(S { v: 0 }) { LL | | x @@ -335,7 +335,7 @@ LL + }; | error: this could be rewritten as `let...else` - --> $DIR/manual_let_else.rs:182:5 + --> $DIR/manual_let_else.rs:183:5 | LL | / let (x, S { v }, w) = if let Some(U { v, w, x }) = None::>> { LL | | (x, v, w) @@ -352,7 +352,7 @@ LL + }; | error: this could be rewritten as `let...else` - --> $DIR/manual_let_else.rs:296:5 + --> $DIR/manual_let_else.rs:297:5 | LL | / let _ = match ff { LL | | Some(value) => value, diff --git a/tests/ui/match_overlapping_arm.rs b/tests/ui/match_overlapping_arm.rs index b4097fa9604..b78c1fd06d4 100644 --- a/tests/ui/match_overlapping_arm.rs +++ b/tests/ui/match_overlapping_arm.rs @@ -1,7 +1,7 @@ #![feature(exclusive_range_pattern)] #![warn(clippy::match_overlapping_arm)] #![allow(clippy::redundant_pattern_matching)] -#![allow(clippy::if_same_then_else, clippy::equatable_if_let)] +#![allow(clippy::if_same_then_else, clippy::equatable_if_let, clippy::needless_if)] /// Tests for match_overlapping_arm diff --git a/tests/ui/needless_bool/fixable.fixed b/tests/ui/needless_bool/fixable.fixed index bf1911881c8..7d0e556528f 100644 --- a/tests/ui/needless_bool/fixable.fixed +++ b/tests/ui/needless_bool/fixable.fixed @@ -7,6 +7,7 @@ clippy::no_effect, clippy::if_same_then_else, clippy::equatable_if_let, + clippy::needless_if, clippy::needless_return, clippy::self_named_constructors )] diff --git a/tests/ui/needless_bool/fixable.rs b/tests/ui/needless_bool/fixable.rs index a6c465d4fbd..88bfe8af733 100644 --- a/tests/ui/needless_bool/fixable.rs +++ b/tests/ui/needless_bool/fixable.rs @@ -7,6 +7,7 @@ clippy::no_effect, clippy::if_same_then_else, clippy::equatable_if_let, + clippy::needless_if, clippy::needless_return, clippy::self_named_constructors )] diff --git a/tests/ui/needless_bool/fixable.stderr b/tests/ui/needless_bool/fixable.stderr index fa906374fb3..1476aea439f 100644 --- a/tests/ui/needless_bool/fixable.stderr +++ b/tests/ui/needless_bool/fixable.stderr @@ -1,5 +1,5 @@ error: this if-then-else expression returns a bool literal - --> $DIR/fixable.rs:41:5 + --> $DIR/fixable.rs:42:5 | LL | / if x { LL | | true @@ -11,7 +11,7 @@ LL | | }; = note: `-D clippy::needless-bool` implied by `-D warnings` error: this if-then-else expression returns a bool literal - --> $DIR/fixable.rs:46:5 + --> $DIR/fixable.rs:47:5 | LL | / if x { LL | | false @@ -21,7 +21,7 @@ LL | | }; | |_____^ help: you can reduce it to: `!x` error: this if-then-else expression returns a bool literal - --> $DIR/fixable.rs:51:5 + --> $DIR/fixable.rs:52:5 | LL | / if x && y { LL | | false @@ -31,7 +31,7 @@ LL | | }; | |_____^ help: you can reduce it to: `!(x && y)` error: this if-then-else expression returns a bool literal - --> $DIR/fixable.rs:59:5 + --> $DIR/fixable.rs:60:5 | LL | / if a == b { LL | | false @@ -41,7 +41,7 @@ LL | | }; | |_____^ help: you can reduce it to: `a != b` error: this if-then-else expression returns a bool literal - --> $DIR/fixable.rs:64:5 + --> $DIR/fixable.rs:65:5 | LL | / if a != b { LL | | false @@ -51,7 +51,7 @@ LL | | }; | |_____^ help: you can reduce it to: `a == b` error: this if-then-else expression returns a bool literal - --> $DIR/fixable.rs:69:5 + --> $DIR/fixable.rs:70:5 | LL | / if a < b { LL | | false @@ -61,7 +61,7 @@ LL | | }; | |_____^ help: you can reduce it to: `a >= b` error: this if-then-else expression returns a bool literal - --> $DIR/fixable.rs:74:5 + --> $DIR/fixable.rs:75:5 | LL | / if a <= b { LL | | false @@ -71,7 +71,7 @@ LL | | }; | |_____^ help: you can reduce it to: `a > b` error: this if-then-else expression returns a bool literal - --> $DIR/fixable.rs:79:5 + --> $DIR/fixable.rs:80:5 | LL | / if a > b { LL | | false @@ -81,7 +81,7 @@ LL | | }; | |_____^ help: you can reduce it to: `a <= b` error: this if-then-else expression returns a bool literal - --> $DIR/fixable.rs:84:5 + --> $DIR/fixable.rs:85:5 | LL | / if a >= b { LL | | false @@ -91,7 +91,7 @@ LL | | }; | |_____^ help: you can reduce it to: `a < b` error: this if-then-else expression returns a bool literal - --> $DIR/fixable.rs:112:5 + --> $DIR/fixable.rs:113:5 | LL | / if x { LL | | return true; @@ -101,7 +101,7 @@ LL | | }; | |_____^ help: you can reduce it to: `return x` error: this if-then-else expression returns a bool literal - --> $DIR/fixable.rs:120:5 + --> $DIR/fixable.rs:121:5 | LL | / if x { LL | | return false; @@ -111,7 +111,7 @@ LL | | }; | |_____^ help: you can reduce it to: `return !x` error: this if-then-else expression returns a bool literal - --> $DIR/fixable.rs:128:5 + --> $DIR/fixable.rs:129:5 | LL | / if x && y { LL | | return true; @@ -121,7 +121,7 @@ LL | | }; | |_____^ help: you can reduce it to: `return x && y` error: this if-then-else expression returns a bool literal - --> $DIR/fixable.rs:136:5 + --> $DIR/fixable.rs:137:5 | LL | / if x && y { LL | | return false; @@ -131,7 +131,7 @@ LL | | }; | |_____^ help: you can reduce it to: `return !(x && y)` error: equality checks against true are unnecessary - --> $DIR/fixable.rs:144:8 + --> $DIR/fixable.rs:145:8 | LL | if x == true {}; | ^^^^^^^^^ help: try simplifying it as shown: `x` @@ -139,25 +139,25 @@ LL | if x == true {}; = note: `-D clippy::bool-comparison` implied by `-D warnings` error: equality checks against false can be replaced by a negation - --> $DIR/fixable.rs:148:8 + --> $DIR/fixable.rs:149:8 | LL | if x == false {}; | ^^^^^^^^^^ help: try simplifying it as shown: `!x` error: equality checks against true are unnecessary - --> $DIR/fixable.rs:158:8 + --> $DIR/fixable.rs:159:8 | LL | if x == true {}; | ^^^^^^^^^ help: try simplifying it as shown: `x` error: equality checks against false can be replaced by a negation - --> $DIR/fixable.rs:159:8 + --> $DIR/fixable.rs:160:8 | LL | if x == false {}; | ^^^^^^^^^^ help: try simplifying it as shown: `!x` error: this if-then-else expression returns a bool literal - --> $DIR/fixable.rs:168:12 + --> $DIR/fixable.rs:169:12 | LL | } else if returns_bool() { | ____________^ @@ -168,7 +168,7 @@ LL | | }; | |_____^ help: you can reduce it to: `{ !returns_bool() }` error: this if-then-else expression returns a bool literal - --> $DIR/fixable.rs:181:5 + --> $DIR/fixable.rs:182:5 | LL | / if unsafe { no(4) } & 1 != 0 { LL | | true @@ -178,13 +178,13 @@ LL | | }; | |_____^ help: you can reduce it to: `(unsafe { no(4) } & 1 != 0)` error: this if-then-else expression returns a bool literal - --> $DIR/fixable.rs:186:30 + --> $DIR/fixable.rs:187:30 | LL | let _brackets_unneeded = if unsafe { no(4) } & 1 != 0 { true } else { false }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: you can reduce it to: `unsafe { no(4) } & 1 != 0` error: this if-then-else expression returns a bool literal - --> $DIR/fixable.rs:189:9 + --> $DIR/fixable.rs:190:9 | LL | if unsafe { no(4) } & 1 != 0 { true } else { false } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: you can reduce it to: `(unsafe { no(4) } & 1 != 0)` diff --git a/tests/ui/needless_borrowed_ref.fixed b/tests/ui/needless_borrowed_ref.fixed index 6663520da8a..59a38425b06 100644 --- a/tests/ui/needless_borrowed_ref.fixed +++ b/tests/ui/needless_borrowed_ref.fixed @@ -5,7 +5,8 @@ unused, irrefutable_let_patterns, non_shorthand_field_patterns, - clippy::needless_borrow + clippy::needless_borrow, + clippy::needless_if )] fn main() {} diff --git a/tests/ui/needless_borrowed_ref.rs b/tests/ui/needless_borrowed_ref.rs index 6c8efd2ce18..e48b19cb19d 100644 --- a/tests/ui/needless_borrowed_ref.rs +++ b/tests/ui/needless_borrowed_ref.rs @@ -5,7 +5,8 @@ unused, irrefutable_let_patterns, non_shorthand_field_patterns, - clippy::needless_borrow + clippy::needless_borrow, + clippy::needless_if )] fn main() {} diff --git a/tests/ui/needless_borrowed_ref.stderr b/tests/ui/needless_borrowed_ref.stderr index 8d0f0c258dd..35497a01ec2 100644 --- a/tests/ui/needless_borrowed_ref.stderr +++ b/tests/ui/needless_borrowed_ref.stderr @@ -1,5 +1,5 @@ error: this pattern takes a reference on something that is being dereferenced - --> $DIR/needless_borrowed_ref.rs:31:34 + --> $DIR/needless_borrowed_ref.rs:32:34 | LL | let _ = v.iter_mut().filter(|&ref a| a.is_empty()); | ^^^^^^ @@ -12,7 +12,7 @@ LL + let _ = v.iter_mut().filter(|a| a.is_empty()); | error: this pattern takes a reference on something that is being dereferenced - --> $DIR/needless_borrowed_ref.rs:35:17 + --> $DIR/needless_borrowed_ref.rs:36:17 | LL | if let Some(&ref v) = thingy {} | ^^^^^^ @@ -24,7 +24,7 @@ LL + if let Some(v) = thingy {} | error: this pattern takes a reference on something that is being dereferenced - --> $DIR/needless_borrowed_ref.rs:37:14 + --> $DIR/needless_borrowed_ref.rs:38:14 | LL | if let &[&ref a, ref b] = slice_of_refs {} | ^^^^^^ @@ -36,7 +36,7 @@ LL + if let &[a, ref b] = slice_of_refs {} | error: dereferencing a slice pattern where every element takes a reference - --> $DIR/needless_borrowed_ref.rs:39:9 + --> $DIR/needless_borrowed_ref.rs:40:9 | LL | let &[ref a, ..] = &array; | ^^^^^^^^^^^^ @@ -48,7 +48,7 @@ LL + let [a, ..] = &array; | error: dereferencing a slice pattern where every element takes a reference - --> $DIR/needless_borrowed_ref.rs:40:9 + --> $DIR/needless_borrowed_ref.rs:41:9 | LL | let &[ref a, ref b, ..] = &array; | ^^^^^^^^^^^^^^^^^^^ @@ -60,7 +60,7 @@ LL + let [a, b, ..] = &array; | error: dereferencing a slice pattern where every element takes a reference - --> $DIR/needless_borrowed_ref.rs:42:12 + --> $DIR/needless_borrowed_ref.rs:43:12 | LL | if let &[ref a, ref b] = slice {} | ^^^^^^^^^^^^^^^ @@ -72,7 +72,7 @@ LL + if let [a, b] = slice {} | error: dereferencing a slice pattern where every element takes a reference - --> $DIR/needless_borrowed_ref.rs:43:12 + --> $DIR/needless_borrowed_ref.rs:44:12 | LL | if let &[ref a, ref b] = &vec[..] {} | ^^^^^^^^^^^^^^^ @@ -84,7 +84,7 @@ LL + if let [a, b] = &vec[..] {} | error: dereferencing a slice pattern where every element takes a reference - --> $DIR/needless_borrowed_ref.rs:45:12 + --> $DIR/needless_borrowed_ref.rs:46:12 | LL | if let &[ref a, ref b, ..] = slice {} | ^^^^^^^^^^^^^^^^^^^ @@ -96,7 +96,7 @@ LL + if let [a, b, ..] = slice {} | error: dereferencing a slice pattern where every element takes a reference - --> $DIR/needless_borrowed_ref.rs:46:12 + --> $DIR/needless_borrowed_ref.rs:47:12 | LL | if let &[ref a, .., ref b] = slice {} | ^^^^^^^^^^^^^^^^^^^ @@ -108,7 +108,7 @@ LL + if let [a, .., b] = slice {} | error: dereferencing a slice pattern where every element takes a reference - --> $DIR/needless_borrowed_ref.rs:47:12 + --> $DIR/needless_borrowed_ref.rs:48:12 | LL | if let &[.., ref a, ref b] = slice {} | ^^^^^^^^^^^^^^^^^^^ @@ -120,7 +120,7 @@ LL + if let [.., a, b] = slice {} | error: dereferencing a slice pattern where every element takes a reference - --> $DIR/needless_borrowed_ref.rs:49:12 + --> $DIR/needless_borrowed_ref.rs:50:12 | LL | if let &[ref a, _] = slice {} | ^^^^^^^^^^^ @@ -132,7 +132,7 @@ LL + if let [a, _] = slice {} | error: dereferencing a tuple pattern where every element takes a reference - --> $DIR/needless_borrowed_ref.rs:51:12 + --> $DIR/needless_borrowed_ref.rs:52:12 | LL | if let &(ref a, ref b, ref c) = &tuple {} | ^^^^^^^^^^^^^^^^^^^^^^ @@ -144,7 +144,7 @@ LL + if let (a, b, c) = &tuple {} | error: dereferencing a tuple pattern where every element takes a reference - --> $DIR/needless_borrowed_ref.rs:52:12 + --> $DIR/needless_borrowed_ref.rs:53:12 | LL | if let &(ref a, _, ref c) = &tuple {} | ^^^^^^^^^^^^^^^^^^ @@ -156,7 +156,7 @@ LL + if let (a, _, c) = &tuple {} | error: dereferencing a tuple pattern where every element takes a reference - --> $DIR/needless_borrowed_ref.rs:53:12 + --> $DIR/needless_borrowed_ref.rs:54:12 | LL | if let &(ref a, ..) = &tuple {} | ^^^^^^^^^^^^ @@ -168,7 +168,7 @@ LL + if let (a, ..) = &tuple {} | error: dereferencing a tuple pattern where every element takes a reference - --> $DIR/needless_borrowed_ref.rs:55:12 + --> $DIR/needless_borrowed_ref.rs:56:12 | LL | if let &TupleStruct(ref a, ..) = &tuple_struct {} | ^^^^^^^^^^^^^^^^^^^^^^^ @@ -180,7 +180,7 @@ LL + if let TupleStruct(a, ..) = &tuple_struct {} | error: dereferencing a struct pattern where every field's pattern takes a reference - --> $DIR/needless_borrowed_ref.rs:57:12 + --> $DIR/needless_borrowed_ref.rs:58:12 | LL | if let &Struct { | ____________^ @@ -199,7 +199,7 @@ LL ~ c: renamed, | error: dereferencing a struct pattern where every field's pattern takes a reference - --> $DIR/needless_borrowed_ref.rs:64:12 + --> $DIR/needless_borrowed_ref.rs:65:12 | LL | if let &Struct { ref a, b: _, .. } = &s {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/needless_collect.fixed b/tests/ui/needless_collect.fixed index b7e80af5015..a1a27ca5051 100644 --- a/tests/ui/needless_collect.fixed +++ b/tests/ui/needless_collect.fixed @@ -1,6 +1,6 @@ //@run-rustfix -#![allow(unused, clippy::suspicious_map, clippy::iter_count)] +#![allow(unused, clippy::needless_if, clippy::suspicious_map, clippy::iter_count)] use std::collections::{BTreeMap, BTreeSet, BinaryHeap, HashMap, HashSet, LinkedList}; diff --git a/tests/ui/needless_collect.rs b/tests/ui/needless_collect.rs index 680b6fa5b55..237fd9540d6 100644 --- a/tests/ui/needless_collect.rs +++ b/tests/ui/needless_collect.rs @@ -1,6 +1,6 @@ //@run-rustfix -#![allow(unused, clippy::suspicious_map, clippy::iter_count)] +#![allow(unused, clippy::needless_if, clippy::suspicious_map, clippy::iter_count)] use std::collections::{BTreeMap, BTreeSet, BinaryHeap, HashMap, HashSet, LinkedList}; diff --git a/tests/ui/needless_collect_indirect.rs b/tests/ui/needless_collect_indirect.rs index 55a7c2c21d9..d3d856c2c65 100644 --- a/tests/ui/needless_collect_indirect.rs +++ b/tests/ui/needless_collect_indirect.rs @@ -1,4 +1,5 @@ #![allow(clippy::uninlined_format_args, clippy::useless_vec)] +#![allow(clippy::needless_if, clippy::uninlined_format_args)] #![warn(clippy::needless_collect)] use std::collections::{BinaryHeap, HashMap, HashSet, LinkedList, VecDeque}; diff --git a/tests/ui/needless_if.fixed b/tests/ui/needless_if.fixed new file mode 100644 index 00000000000..7587a397dc9 --- /dev/null +++ b/tests/ui/needless_if.fixed @@ -0,0 +1,37 @@ +//@run-rustfix +//@aux-build:proc_macros.rs +#![allow( + clippy::blocks_in_if_conditions, + clippy::if_same_then_else, + clippy::ifs_same_cond, + clippy::needless_else, + clippy::no_effect, + unused +)] +#![warn(clippy::needless_if)] + +extern crate proc_macros; +use proc_macros::external; +use proc_macros::with_span; + +fn main() { + // Lint + (true); + // Do not lint + if (true) { + } else { + } + // Do not lint if `else if` is present + if (true) { + } else if (true) { + } + // Ensure clippy does not bork this up, other cases should be added + { + return; + }; + external! { if (true) {} } + with_span! { + span + if (true) {} + } +} diff --git a/tests/ui/needless_if.rs b/tests/ui/needless_if.rs new file mode 100644 index 00000000000..3006995e09d --- /dev/null +++ b/tests/ui/needless_if.rs @@ -0,0 +1,37 @@ +//@run-rustfix +//@aux-build:proc_macros.rs +#![allow( + clippy::blocks_in_if_conditions, + clippy::if_same_then_else, + clippy::ifs_same_cond, + clippy::needless_else, + clippy::no_effect, + unused +)] +#![warn(clippy::needless_if)] + +extern crate proc_macros; +use proc_macros::external; +use proc_macros::with_span; + +fn main() { + // Lint + if (true) {} + // Do not lint + if (true) { + } else { + } + // Do not lint if `else if` is present + if (true) { + } else if (true) { + } + // Ensure clippy does not bork this up, other cases should be added + if { + return; + } {} + external! { if (true) {} } + with_span! { + span + if (true) {} + } +} diff --git a/tests/ui/needless_if.stderr b/tests/ui/needless_if.stderr new file mode 100644 index 00000000000..bbb2a035668 --- /dev/null +++ b/tests/ui/needless_if.stderr @@ -0,0 +1,25 @@ +error: this if branch is empty + --> $DIR/needless_if.rs:19:5 + | +LL | if (true) {} + | ^^^^^^^^^^^^ help: you can remove it: `(true);` + | + = note: `-D clippy::needless-if` implied by `-D warnings` + +error: this if branch is empty + --> $DIR/needless_if.rs:29:5 + | +LL | / if { +LL | | return; +LL | | } {} + | |________^ + | +help: you can remove it + | +LL ~ { +LL + return; +LL + }; + | + +error: aborting due to 2 previous errors + diff --git a/tests/ui/nonminimal_bool.rs b/tests/ui/nonminimal_bool.rs index 73e056c722e..e4aa0937b97 100644 --- a/tests/ui/nonminimal_bool.rs +++ b/tests/ui/nonminimal_bool.rs @@ -1,5 +1,5 @@ #![feature(lint_reasons)] -#![allow(unused, clippy::diverging_sub_expression)] +#![allow(unused, clippy::diverging_sub_expression, clippy::needless_if)] #![warn(clippy::nonminimal_bool)] #![allow(clippy::useless_vec)] diff --git a/tests/ui/nonminimal_bool_methods.fixed b/tests/ui/nonminimal_bool_methods.fixed index 05802a2c865..294f2aa48f1 100644 --- a/tests/ui/nonminimal_bool_methods.fixed +++ b/tests/ui/nonminimal_bool_methods.fixed @@ -1,5 +1,5 @@ //@run-rustfix -#![allow(unused, clippy::diverging_sub_expression)] +#![allow(unused, clippy::diverging_sub_expression, clippy::needless_if)] #![warn(clippy::nonminimal_bool)] fn methods_with_negation() { diff --git a/tests/ui/nonminimal_bool_methods.rs b/tests/ui/nonminimal_bool_methods.rs index cd5b576fa07..a165368ab17 100644 --- a/tests/ui/nonminimal_bool_methods.rs +++ b/tests/ui/nonminimal_bool_methods.rs @@ -1,5 +1,5 @@ //@run-rustfix -#![allow(unused, clippy::diverging_sub_expression)] +#![allow(unused, clippy::diverging_sub_expression, clippy::needless_if)] #![warn(clippy::nonminimal_bool)] fn methods_with_negation() { diff --git a/tests/ui/overflow_check_conditional.rs b/tests/ui/overflow_check_conditional.rs index e1e30114081..14a6b98d07d 100644 --- a/tests/ui/overflow_check_conditional.rs +++ b/tests/ui/overflow_check_conditional.rs @@ -1,4 +1,5 @@ #![warn(clippy::overflow_check_conditional)] +#![allow(clippy::needless_if)] fn test(a: u32, b: u32, c: u32) { if a + b < a {} diff --git a/tests/ui/overflow_check_conditional.stderr b/tests/ui/overflow_check_conditional.stderr index 92d1d8ef911..3ec2298f828 100644 --- a/tests/ui/overflow_check_conditional.stderr +++ b/tests/ui/overflow_check_conditional.stderr @@ -1,5 +1,5 @@ error: you are trying to use classic C overflow conditions that will fail in Rust - --> $DIR/overflow_check_conditional.rs:4:8 + --> $DIR/overflow_check_conditional.rs:5:8 | LL | if a + b < a {} | ^^^^^^^^^ @@ -7,43 +7,43 @@ LL | if a + b < a {} = note: `-D clippy::overflow-check-conditional` implied by `-D warnings` error: you are trying to use classic C overflow conditions that will fail in Rust - --> $DIR/overflow_check_conditional.rs:5:8 + --> $DIR/overflow_check_conditional.rs:6:8 | LL | if a > a + b {} | ^^^^^^^^^ error: you are trying to use classic C overflow conditions that will fail in Rust - --> $DIR/overflow_check_conditional.rs:6:8 + --> $DIR/overflow_check_conditional.rs:7:8 | LL | if a + b < b {} | ^^^^^^^^^ error: you are trying to use classic C overflow conditions that will fail in Rust - --> $DIR/overflow_check_conditional.rs:7:8 + --> $DIR/overflow_check_conditional.rs:8:8 | LL | if b > a + b {} | ^^^^^^^^^ error: you are trying to use classic C underflow conditions that will fail in Rust - --> $DIR/overflow_check_conditional.rs:8:8 + --> $DIR/overflow_check_conditional.rs:9:8 | LL | if a - b > b {} | ^^^^^^^^^ error: you are trying to use classic C underflow conditions that will fail in Rust - --> $DIR/overflow_check_conditional.rs:9:8 + --> $DIR/overflow_check_conditional.rs:10:8 | LL | if b < a - b {} | ^^^^^^^^^ error: you are trying to use classic C underflow conditions that will fail in Rust - --> $DIR/overflow_check_conditional.rs:10:8 + --> $DIR/overflow_check_conditional.rs:11:8 | LL | if a - b > a {} | ^^^^^^^^^ error: you are trying to use classic C underflow conditions that will fail in Rust - --> $DIR/overflow_check_conditional.rs:11:8 + --> $DIR/overflow_check_conditional.rs:12:8 | LL | if a < a - b {} | ^^^^^^^^^ diff --git a/tests/ui/partialeq_to_none.fixed b/tests/ui/partialeq_to_none.fixed index 2df87a26d6d..95e184b1de6 100644 --- a/tests/ui/partialeq_to_none.fixed +++ b/tests/ui/partialeq_to_none.fixed @@ -1,6 +1,6 @@ //@run-rustfix #![warn(clippy::partialeq_to_none)] -#![allow(clippy::eq_op)] +#![allow(clippy::eq_op, clippy::needless_if)] struct Foobar; diff --git a/tests/ui/partialeq_to_none.rs b/tests/ui/partialeq_to_none.rs index df6233b9afd..4fa50dcc11b 100644 --- a/tests/ui/partialeq_to_none.rs +++ b/tests/ui/partialeq_to_none.rs @@ -1,6 +1,6 @@ //@run-rustfix #![warn(clippy::partialeq_to_none)] -#![allow(clippy::eq_op)] +#![allow(clippy::eq_op, clippy::needless_if)] struct Foobar; diff --git a/tests/ui/redundant_pattern_matching_drop_order.fixed b/tests/ui/redundant_pattern_matching_drop_order.fixed index 481c9b263fb..d1134de5ab4 100644 --- a/tests/ui/redundant_pattern_matching_drop_order.fixed +++ b/tests/ui/redundant_pattern_matching_drop_order.fixed @@ -2,7 +2,12 @@ // Issue #5746 #![warn(clippy::redundant_pattern_matching)] -#![allow(clippy::if_same_then_else, clippy::equatable_if_let, clippy::needless_else)] +#![allow( + clippy::if_same_then_else, + clippy::equatable_if_let, + clippy::needless_if, + clippy::needless_else +)] use std::task::Poll::{Pending, Ready}; fn main() { diff --git a/tests/ui/redundant_pattern_matching_drop_order.rs b/tests/ui/redundant_pattern_matching_drop_order.rs index 86e46d41e65..d144086e791 100644 --- a/tests/ui/redundant_pattern_matching_drop_order.rs +++ b/tests/ui/redundant_pattern_matching_drop_order.rs @@ -2,7 +2,12 @@ // Issue #5746 #![warn(clippy::redundant_pattern_matching)] -#![allow(clippy::if_same_then_else, clippy::equatable_if_let, clippy::needless_else)] +#![allow( + clippy::if_same_then_else, + clippy::equatable_if_let, + clippy::needless_if, + clippy::needless_else +)] use std::task::Poll::{Pending, Ready}; fn main() { diff --git a/tests/ui/redundant_pattern_matching_drop_order.stderr b/tests/ui/redundant_pattern_matching_drop_order.stderr index 23f08103f35..e9ea3f2e688 100644 --- a/tests/ui/redundant_pattern_matching_drop_order.stderr +++ b/tests/ui/redundant_pattern_matching_drop_order.stderr @@ -1,5 +1,5 @@ error: redundant pattern matching, consider using `is_ok()` - --> $DIR/redundant_pattern_matching_drop_order.rs:12:12 + --> $DIR/redundant_pattern_matching_drop_order.rs:17:12 | LL | if let Ok(_) = m.lock() {} | -------^^^^^----------- help: try this: `if m.lock().is_ok()` @@ -9,7 +9,7 @@ LL | if let Ok(_) = m.lock() {} = note: `-D clippy::redundant-pattern-matching` implied by `-D warnings` error: redundant pattern matching, consider using `is_err()` - --> $DIR/redundant_pattern_matching_drop_order.rs:13:12 + --> $DIR/redundant_pattern_matching_drop_order.rs:18:12 | LL | if let Err(_) = Err::<(), _>(m.lock().unwrap().0) {} | -------^^^^^^------------------------------------ help: try this: `if Err::<(), _>(m.lock().unwrap().0).is_err()` @@ -18,7 +18,7 @@ LL | if let Err(_) = Err::<(), _>(m.lock().unwrap().0) {} = note: add `#[allow(clippy::redundant_pattern_matching)]` if this is important error: redundant pattern matching, consider using `is_ok()` - --> $DIR/redundant_pattern_matching_drop_order.rs:16:16 + --> $DIR/redundant_pattern_matching_drop_order.rs:21:16 | LL | if let Ok(_) = Ok::<_, std::sync::MutexGuard<()>>(()) {} | -------^^^^^----------------------------------------- help: try this: `if Ok::<_, std::sync::MutexGuard<()>>(()).is_ok()` @@ -27,7 +27,7 @@ LL | if let Ok(_) = Ok::<_, std::sync::MutexGuard<()>>(()) {} = note: add `#[allow(clippy::redundant_pattern_matching)]` if this is important error: redundant pattern matching, consider using `is_ok()` - --> $DIR/redundant_pattern_matching_drop_order.rs:18:12 + --> $DIR/redundant_pattern_matching_drop_order.rs:23:12 | LL | if let Ok(_) = Ok::<_, std::sync::MutexGuard<()>>(()) { | -------^^^^^----------------------------------------- help: try this: `if Ok::<_, std::sync::MutexGuard<()>>(()).is_ok()` @@ -36,31 +36,31 @@ LL | if let Ok(_) = Ok::<_, std::sync::MutexGuard<()>>(()) { = note: add `#[allow(clippy::redundant_pattern_matching)]` if this is important error: redundant pattern matching, consider using `is_ok()` - --> $DIR/redundant_pattern_matching_drop_order.rs:21:12 + --> $DIR/redundant_pattern_matching_drop_order.rs:26:12 | LL | if let Ok(_) = Ok::<_, std::sync::MutexGuard<()>>(()) {} | -------^^^^^----------------------------------------- help: try this: `if Ok::<_, std::sync::MutexGuard<()>>(()).is_ok()` error: redundant pattern matching, consider using `is_err()` - --> $DIR/redundant_pattern_matching_drop_order.rs:22:12 + --> $DIR/redundant_pattern_matching_drop_order.rs:27:12 | LL | if let Err(_) = Err::, _>(()) {} | -------^^^^^^------------------------------------------ help: try this: `if Err::, _>(()).is_err()` error: redundant pattern matching, consider using `is_ok()` - --> $DIR/redundant_pattern_matching_drop_order.rs:24:12 + --> $DIR/redundant_pattern_matching_drop_order.rs:29:12 | LL | if let Ok(_) = Ok::<_, ()>(String::new()) {} | -------^^^^^----------------------------- help: try this: `if Ok::<_, ()>(String::new()).is_ok()` error: redundant pattern matching, consider using `is_err()` - --> $DIR/redundant_pattern_matching_drop_order.rs:25:12 + --> $DIR/redundant_pattern_matching_drop_order.rs:30:12 | LL | if let Err(_) = Err::<(), _>((String::new(), ())) {} | -------^^^^^^------------------------------------ help: try this: `if Err::<(), _>((String::new(), ())).is_err()` error: redundant pattern matching, consider using `is_some()` - --> $DIR/redundant_pattern_matching_drop_order.rs:28:12 + --> $DIR/redundant_pattern_matching_drop_order.rs:33:12 | LL | if let Some(_) = Some(m.lock()) {} | -------^^^^^^^----------------- help: try this: `if Some(m.lock()).is_some()` @@ -69,7 +69,7 @@ LL | if let Some(_) = Some(m.lock()) {} = note: add `#[allow(clippy::redundant_pattern_matching)]` if this is important error: redundant pattern matching, consider using `is_some()` - --> $DIR/redundant_pattern_matching_drop_order.rs:29:12 + --> $DIR/redundant_pattern_matching_drop_order.rs:34:12 | LL | if let Some(_) = Some(m.lock().unwrap().0) {} | -------^^^^^^^---------------------------- help: try this: `if Some(m.lock().unwrap().0).is_some()` @@ -78,7 +78,7 @@ LL | if let Some(_) = Some(m.lock().unwrap().0) {} = note: add `#[allow(clippy::redundant_pattern_matching)]` if this is important error: redundant pattern matching, consider using `is_none()` - --> $DIR/redundant_pattern_matching_drop_order.rs:32:16 + --> $DIR/redundant_pattern_matching_drop_order.rs:37:16 | LL | if let None = None::> {} | -------^^^^------------------------------------ help: try this: `if None::>.is_none()` @@ -87,7 +87,7 @@ LL | if let None = None::> {} = note: add `#[allow(clippy::redundant_pattern_matching)]` if this is important error: redundant pattern matching, consider using `is_none()` - --> $DIR/redundant_pattern_matching_drop_order.rs:34:12 + --> $DIR/redundant_pattern_matching_drop_order.rs:39:12 | LL | if let None = None::> { | -------^^^^------------------------------------ help: try this: `if None::>.is_none()` @@ -96,25 +96,25 @@ LL | if let None = None::> { = note: add `#[allow(clippy::redundant_pattern_matching)]` if this is important error: redundant pattern matching, consider using `is_none()` - --> $DIR/redundant_pattern_matching_drop_order.rs:38:12 + --> $DIR/redundant_pattern_matching_drop_order.rs:43: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_drop_order.rs:40:12 + --> $DIR/redundant_pattern_matching_drop_order.rs:45:12 | LL | if let Some(_) = Some(String::new()) {} | -------^^^^^^^---------------------- help: try this: `if Some(String::new()).is_some()` error: redundant pattern matching, consider using `is_some()` - --> $DIR/redundant_pattern_matching_drop_order.rs:41:12 + --> $DIR/redundant_pattern_matching_drop_order.rs:46:12 | LL | if let Some(_) = Some((String::new(), ())) {} | -------^^^^^^^---------------------------- help: try this: `if Some((String::new(), ())).is_some()` error: redundant pattern matching, consider using `is_ready()` - --> $DIR/redundant_pattern_matching_drop_order.rs:44:12 + --> $DIR/redundant_pattern_matching_drop_order.rs:49:12 | LL | if let Ready(_) = Ready(m.lock()) {} | -------^^^^^^^^------------------ help: try this: `if Ready(m.lock()).is_ready()` @@ -123,7 +123,7 @@ LL | if let Ready(_) = Ready(m.lock()) {} = note: add `#[allow(clippy::redundant_pattern_matching)]` if this is important error: redundant pattern matching, consider using `is_ready()` - --> $DIR/redundant_pattern_matching_drop_order.rs:45:12 + --> $DIR/redundant_pattern_matching_drop_order.rs:50:12 | LL | if let Ready(_) = Ready(m.lock().unwrap().0) {} | -------^^^^^^^^----------------------------- help: try this: `if Ready(m.lock().unwrap().0).is_ready()` @@ -132,7 +132,7 @@ LL | if let Ready(_) = Ready(m.lock().unwrap().0) {} = note: add `#[allow(clippy::redundant_pattern_matching)]` if this is important error: redundant pattern matching, consider using `is_pending()` - --> $DIR/redundant_pattern_matching_drop_order.rs:48:16 + --> $DIR/redundant_pattern_matching_drop_order.rs:53:16 | LL | if let Pending = Pending::> {} | -------^^^^^^^--------------------------------------- help: try this: `if Pending::>.is_pending()` @@ -141,7 +141,7 @@ LL | if let Pending = Pending::> {} = note: add `#[allow(clippy::redundant_pattern_matching)]` if this is important error: redundant pattern matching, consider using `is_pending()` - --> $DIR/redundant_pattern_matching_drop_order.rs:50:12 + --> $DIR/redundant_pattern_matching_drop_order.rs:55:12 | LL | if let Pending = Pending::> { | -------^^^^^^^--------------------------------------- help: try this: `if Pending::>.is_pending()` @@ -150,19 +150,19 @@ LL | if let Pending = Pending::> { = note: add `#[allow(clippy::redundant_pattern_matching)]` if this is important error: redundant pattern matching, consider using `is_pending()` - --> $DIR/redundant_pattern_matching_drop_order.rs:54:12 + --> $DIR/redundant_pattern_matching_drop_order.rs:59:12 | LL | if let Pending = Pending::> {} | -------^^^^^^^--------------------------------------- help: try this: `if Pending::>.is_pending()` error: redundant pattern matching, consider using `is_ready()` - --> $DIR/redundant_pattern_matching_drop_order.rs:56:12 + --> $DIR/redundant_pattern_matching_drop_order.rs:61:12 | LL | if let Ready(_) = Ready(String::new()) {} | -------^^^^^^^^----------------------- help: try this: `if Ready(String::new()).is_ready()` error: redundant pattern matching, consider using `is_ready()` - --> $DIR/redundant_pattern_matching_drop_order.rs:57:12 + --> $DIR/redundant_pattern_matching_drop_order.rs:62:12 | LL | if let Ready(_) = Ready((String::new(), ())) {} | -------^^^^^^^^----------------------------- help: try this: `if Ready((String::new(), ())).is_ready()` diff --git a/tests/ui/redundant_pattern_matching_ipaddr.fixed b/tests/ui/redundant_pattern_matching_ipaddr.fixed index a9faf12cd5a..75ed143446c 100644 --- a/tests/ui/redundant_pattern_matching_ipaddr.fixed +++ b/tests/ui/redundant_pattern_matching_ipaddr.fixed @@ -4,6 +4,7 @@ #![allow( clippy::match_like_matches_macro, clippy::needless_bool, + clippy::needless_if, clippy::uninlined_format_args )] diff --git a/tests/ui/redundant_pattern_matching_ipaddr.rs b/tests/ui/redundant_pattern_matching_ipaddr.rs index 574671d03d1..9ac77409f79 100644 --- a/tests/ui/redundant_pattern_matching_ipaddr.rs +++ b/tests/ui/redundant_pattern_matching_ipaddr.rs @@ -4,6 +4,7 @@ #![allow( clippy::match_like_matches_macro, clippy::needless_bool, + clippy::needless_if, clippy::uninlined_format_args )] diff --git a/tests/ui/redundant_pattern_matching_ipaddr.stderr b/tests/ui/redundant_pattern_matching_ipaddr.stderr index 536b589de54..6d1fb296463 100644 --- a/tests/ui/redundant_pattern_matching_ipaddr.stderr +++ b/tests/ui/redundant_pattern_matching_ipaddr.stderr @@ -1,5 +1,5 @@ error: redundant pattern matching, consider using `is_ipv4()` - --> $DIR/redundant_pattern_matching_ipaddr.rs:17:12 + --> $DIR/redundant_pattern_matching_ipaddr.rs:18:12 | LL | if let V4(_) = &ipaddr {} | -------^^^^^---------- help: try this: `if ipaddr.is_ipv4()` @@ -7,31 +7,31 @@ LL | if let V4(_) = &ipaddr {} = note: `-D clippy::redundant-pattern-matching` implied by `-D warnings` error: redundant pattern matching, consider using `is_ipv4()` - --> $DIR/redundant_pattern_matching_ipaddr.rs:19:12 + --> $DIR/redundant_pattern_matching_ipaddr.rs:20:12 | LL | if let V4(_) = V4(Ipv4Addr::LOCALHOST) {} | -------^^^^^-------------------------- help: try this: `if V4(Ipv4Addr::LOCALHOST).is_ipv4()` error: redundant pattern matching, consider using `is_ipv6()` - --> $DIR/redundant_pattern_matching_ipaddr.rs:21:12 + --> $DIR/redundant_pattern_matching_ipaddr.rs:22:12 | LL | if let V6(_) = V6(Ipv6Addr::LOCALHOST) {} | -------^^^^^-------------------------- help: try this: `if V6(Ipv6Addr::LOCALHOST).is_ipv6()` error: redundant pattern matching, consider using `is_ipv4()` - --> $DIR/redundant_pattern_matching_ipaddr.rs:23:15 + --> $DIR/redundant_pattern_matching_ipaddr.rs:24:15 | LL | while let V4(_) = V4(Ipv4Addr::LOCALHOST) {} | ----------^^^^^-------------------------- help: try this: `while V4(Ipv4Addr::LOCALHOST).is_ipv4()` error: redundant pattern matching, consider using `is_ipv6()` - --> $DIR/redundant_pattern_matching_ipaddr.rs:25:15 + --> $DIR/redundant_pattern_matching_ipaddr.rs:26:15 | LL | while let V6(_) = V6(Ipv6Addr::LOCALHOST) {} | ----------^^^^^-------------------------- help: try this: `while V6(Ipv6Addr::LOCALHOST).is_ipv6()` error: redundant pattern matching, consider using `is_ipv4()` - --> $DIR/redundant_pattern_matching_ipaddr.rs:35:5 + --> $DIR/redundant_pattern_matching_ipaddr.rs:36:5 | LL | / match V4(Ipv4Addr::LOCALHOST) { LL | | V4(_) => true, @@ -40,7 +40,7 @@ LL | | }; | |_____^ help: try this: `V4(Ipv4Addr::LOCALHOST).is_ipv4()` error: redundant pattern matching, consider using `is_ipv6()` - --> $DIR/redundant_pattern_matching_ipaddr.rs:40:5 + --> $DIR/redundant_pattern_matching_ipaddr.rs:41:5 | LL | / match V4(Ipv4Addr::LOCALHOST) { LL | | V4(_) => false, @@ -49,7 +49,7 @@ LL | | }; | |_____^ help: try this: `V4(Ipv4Addr::LOCALHOST).is_ipv6()` error: redundant pattern matching, consider using `is_ipv6()` - --> $DIR/redundant_pattern_matching_ipaddr.rs:45:5 + --> $DIR/redundant_pattern_matching_ipaddr.rs:46:5 | LL | / match V6(Ipv6Addr::LOCALHOST) { LL | | V4(_) => false, @@ -58,7 +58,7 @@ LL | | }; | |_____^ help: try this: `V6(Ipv6Addr::LOCALHOST).is_ipv6()` error: redundant pattern matching, consider using `is_ipv4()` - --> $DIR/redundant_pattern_matching_ipaddr.rs:50:5 + --> $DIR/redundant_pattern_matching_ipaddr.rs:51:5 | LL | / match V6(Ipv6Addr::LOCALHOST) { LL | | V4(_) => true, @@ -67,49 +67,49 @@ LL | | }; | |_____^ help: try this: `V6(Ipv6Addr::LOCALHOST).is_ipv4()` error: redundant pattern matching, consider using `is_ipv4()` - --> $DIR/redundant_pattern_matching_ipaddr.rs:55:20 + --> $DIR/redundant_pattern_matching_ipaddr.rs:56:20 | LL | let _ = if let V4(_) = V4(Ipv4Addr::LOCALHOST) { | -------^^^^^-------------------------- help: try this: `if V4(Ipv4Addr::LOCALHOST).is_ipv4()` error: redundant pattern matching, consider using `is_ipv4()` - --> $DIR/redundant_pattern_matching_ipaddr.rs:63:20 + --> $DIR/redundant_pattern_matching_ipaddr.rs:64:20 | LL | let _ = if let V4(_) = gen_ipaddr() { | -------^^^^^--------------- help: try this: `if gen_ipaddr().is_ipv4()` error: redundant pattern matching, consider using `is_ipv6()` - --> $DIR/redundant_pattern_matching_ipaddr.rs:65:19 + --> $DIR/redundant_pattern_matching_ipaddr.rs:66:19 | LL | } else if let V6(_) = gen_ipaddr() { | -------^^^^^--------------- help: try this: `if gen_ipaddr().is_ipv6()` error: redundant pattern matching, consider using `is_ipv4()` - --> $DIR/redundant_pattern_matching_ipaddr.rs:77:12 + --> $DIR/redundant_pattern_matching_ipaddr.rs:78:12 | LL | if let V4(_) = V4(Ipv4Addr::LOCALHOST) {} | -------^^^^^-------------------------- help: try this: `if V4(Ipv4Addr::LOCALHOST).is_ipv4()` error: redundant pattern matching, consider using `is_ipv6()` - --> $DIR/redundant_pattern_matching_ipaddr.rs:79:12 + --> $DIR/redundant_pattern_matching_ipaddr.rs:80:12 | LL | if let V6(_) = V6(Ipv6Addr::LOCALHOST) {} | -------^^^^^-------------------------- help: try this: `if V6(Ipv6Addr::LOCALHOST).is_ipv6()` error: redundant pattern matching, consider using `is_ipv4()` - --> $DIR/redundant_pattern_matching_ipaddr.rs:81:15 + --> $DIR/redundant_pattern_matching_ipaddr.rs:82:15 | LL | while let V4(_) = V4(Ipv4Addr::LOCALHOST) {} | ----------^^^^^-------------------------- help: try this: `while V4(Ipv4Addr::LOCALHOST).is_ipv4()` error: redundant pattern matching, consider using `is_ipv6()` - --> $DIR/redundant_pattern_matching_ipaddr.rs:83:15 + --> $DIR/redundant_pattern_matching_ipaddr.rs:84:15 | LL | while let V6(_) = V6(Ipv6Addr::LOCALHOST) {} | ----------^^^^^-------------------------- help: try this: `while V6(Ipv6Addr::LOCALHOST).is_ipv6()` error: redundant pattern matching, consider using `is_ipv4()` - --> $DIR/redundant_pattern_matching_ipaddr.rs:85:5 + --> $DIR/redundant_pattern_matching_ipaddr.rs:86:5 | LL | / match V4(Ipv4Addr::LOCALHOST) { LL | | V4(_) => true, @@ -118,7 +118,7 @@ LL | | }; | |_____^ help: try this: `V4(Ipv4Addr::LOCALHOST).is_ipv4()` error: redundant pattern matching, consider using `is_ipv6()` - --> $DIR/redundant_pattern_matching_ipaddr.rs:90:5 + --> $DIR/redundant_pattern_matching_ipaddr.rs:91:5 | LL | / match V6(Ipv6Addr::LOCALHOST) { LL | | V4(_) => false, diff --git a/tests/ui/redundant_pattern_matching_option.fixed b/tests/ui/redundant_pattern_matching_option.fixed index dae931541d4..a63ba5809e4 100644 --- a/tests/ui/redundant_pattern_matching_option.fixed +++ b/tests/ui/redundant_pattern_matching_option.fixed @@ -5,6 +5,7 @@ #![allow( unused_must_use, clippy::needless_bool, + clippy::needless_if, clippy::match_like_matches_macro, clippy::equatable_if_let, clippy::if_same_then_else diff --git a/tests/ui/redundant_pattern_matching_option.rs b/tests/ui/redundant_pattern_matching_option.rs index 3f2fa3f53ce..631f9091672 100644 --- a/tests/ui/redundant_pattern_matching_option.rs +++ b/tests/ui/redundant_pattern_matching_option.rs @@ -5,6 +5,7 @@ #![allow( unused_must_use, clippy::needless_bool, + clippy::needless_if, clippy::match_like_matches_macro, clippy::equatable_if_let, clippy::if_same_then_else diff --git a/tests/ui/redundant_pattern_matching_option.stderr b/tests/ui/redundant_pattern_matching_option.stderr index 93760ce97a8..717b603c496 100644 --- a/tests/ui/redundant_pattern_matching_option.stderr +++ b/tests/ui/redundant_pattern_matching_option.stderr @@ -1,5 +1,5 @@ error: redundant pattern matching, consider using `is_none()` - --> $DIR/redundant_pattern_matching_option.rs:14:12 + --> $DIR/redundant_pattern_matching_option.rs:15:12 | LL | if let None = None::<()> {} | -------^^^^------------- help: try this: `if None::<()>.is_none()` @@ -7,43 +7,43 @@ LL | if let None = None::<()> {} = note: `-D clippy::redundant-pattern-matching` implied by `-D warnings` error: redundant pattern matching, consider using `is_some()` - --> $DIR/redundant_pattern_matching_option.rs:16:12 + --> $DIR/redundant_pattern_matching_option.rs:17:12 | LL | if let Some(_) = Some(42) {} | -------^^^^^^^----------- help: try this: `if Some(42).is_some()` error: redundant pattern matching, consider using `is_some()` - --> $DIR/redundant_pattern_matching_option.rs:18:12 + --> $DIR/redundant_pattern_matching_option.rs:19:12 | LL | if let Some(_) = Some(42) { | -------^^^^^^^----------- help: try this: `if Some(42).is_some()` error: redundant pattern matching, consider using `is_some()` - --> $DIR/redundant_pattern_matching_option.rs:24:15 + --> $DIR/redundant_pattern_matching_option.rs:25: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:26:15 + --> $DIR/redundant_pattern_matching_option.rs:27:15 | LL | while let None = Some(42) {} | ----------^^^^----------- help: try this: `while Some(42).is_none()` error: redundant pattern matching, consider using `is_none()` - --> $DIR/redundant_pattern_matching_option.rs:28:15 + --> $DIR/redundant_pattern_matching_option.rs:29: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:31:15 + --> $DIR/redundant_pattern_matching_option.rs:32:15 | LL | while let Some(_) = v.pop() { | ----------^^^^^^^---------- help: try this: `while v.pop().is_some()` error: redundant pattern matching, consider using `is_some()` - --> $DIR/redundant_pattern_matching_option.rs:39:5 + --> $DIR/redundant_pattern_matching_option.rs:40:5 | LL | / match Some(42) { LL | | Some(_) => true, @@ -52,7 +52,7 @@ LL | | }; | |_____^ help: try this: `Some(42).is_some()` error: redundant pattern matching, consider using `is_none()` - --> $DIR/redundant_pattern_matching_option.rs:44:5 + --> $DIR/redundant_pattern_matching_option.rs:45:5 | LL | / match None::<()> { LL | | Some(_) => false, @@ -61,7 +61,7 @@ LL | | }; | |_____^ help: try this: `None::<()>.is_none()` error: redundant pattern matching, consider using `is_none()` - --> $DIR/redundant_pattern_matching_option.rs:49:13 + --> $DIR/redundant_pattern_matching_option.rs:50:13 | LL | let _ = match None::<()> { | _____________^ @@ -71,55 +71,55 @@ LL | | }; | |_____^ help: try this: `None::<()>.is_none()` error: redundant pattern matching, consider using `is_some()` - --> $DIR/redundant_pattern_matching_option.rs:55:20 + --> $DIR/redundant_pattern_matching_option.rs:56:20 | LL | let _ = if let Some(_) = opt { true } else { false }; | -------^^^^^^^------ help: try this: `if opt.is_some()` error: redundant pattern matching, consider using `is_some()` - --> $DIR/redundant_pattern_matching_option.rs:61:20 + --> $DIR/redundant_pattern_matching_option.rs:62:20 | LL | let _ = if let Some(_) = gen_opt() { | -------^^^^^^^------------ help: try this: `if gen_opt().is_some()` error: redundant pattern matching, consider using `is_none()` - --> $DIR/redundant_pattern_matching_option.rs:63:19 + --> $DIR/redundant_pattern_matching_option.rs:64:19 | 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:69:12 + --> $DIR/redundant_pattern_matching_option.rs:70: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:84:12 + --> $DIR/redundant_pattern_matching_option.rs:85: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:86:12 + --> $DIR/redundant_pattern_matching_option.rs:87: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:88:15 + --> $DIR/redundant_pattern_matching_option.rs:89: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:90:15 + --> $DIR/redundant_pattern_matching_option.rs:91: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:92:5 + --> $DIR/redundant_pattern_matching_option.rs:93:5 | LL | / match Some(42) { LL | | Some(_) => true, @@ -128,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:97:5 + --> $DIR/redundant_pattern_matching_option.rs:98:5 | LL | / match None::<()> { LL | | Some(_) => false, @@ -137,19 +137,19 @@ LL | | }; | |_____^ help: try this: `None::<()>.is_none()` error: redundant pattern matching, consider using `is_none()` - --> $DIR/redundant_pattern_matching_option.rs:105:12 + --> $DIR/redundant_pattern_matching_option.rs:106: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:106:12 + --> $DIR/redundant_pattern_matching_option.rs:107: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:112:5 + --> $DIR/redundant_pattern_matching_option.rs:113:5 | LL | / match x { LL | | Some(_) => true, @@ -158,7 +158,7 @@ LL | | }; | |_____^ help: try this: `x.is_some()` error: redundant pattern matching, consider using `is_none()` - --> $DIR/redundant_pattern_matching_option.rs:117:5 + --> $DIR/redundant_pattern_matching_option.rs:118:5 | LL | / match x { LL | | None => true, @@ -167,7 +167,7 @@ LL | | }; | |_____^ help: try this: `x.is_none()` error: redundant pattern matching, consider using `is_none()` - --> $DIR/redundant_pattern_matching_option.rs:122:5 + --> $DIR/redundant_pattern_matching_option.rs:123:5 | LL | / match x { LL | | Some(_) => false, @@ -176,7 +176,7 @@ LL | | }; | |_____^ help: try this: `x.is_none()` error: redundant pattern matching, consider using `is_some()` - --> $DIR/redundant_pattern_matching_option.rs:127:5 + --> $DIR/redundant_pattern_matching_option.rs:128:5 | LL | / match x { LL | | None => false, @@ -185,13 +185,13 @@ LL | | }; | |_____^ help: try this: `x.is_some()` error: redundant pattern matching, consider using `is_some()` - --> $DIR/redundant_pattern_matching_option.rs:142:13 + --> $DIR/redundant_pattern_matching_option.rs:143:13 | LL | let _ = matches!(x, Some(_)); | ^^^^^^^^^^^^^^^^^^^^ help: try this: `x.is_some()` error: redundant pattern matching, consider using `is_none()` - --> $DIR/redundant_pattern_matching_option.rs:144:13 + --> $DIR/redundant_pattern_matching_option.rs:145:13 | LL | let _ = matches!(x, None); | ^^^^^^^^^^^^^^^^^ help: try this: `x.is_none()` diff --git a/tests/ui/redundant_pattern_matching_poll.fixed b/tests/ui/redundant_pattern_matching_poll.fixed index bf3e692202c..f739deaf58e 100644 --- a/tests/ui/redundant_pattern_matching_poll.fixed +++ b/tests/ui/redundant_pattern_matching_poll.fixed @@ -5,6 +5,7 @@ #![allow( unused_must_use, clippy::needless_bool, + clippy::needless_if, clippy::match_like_matches_macro, clippy::equatable_if_let, clippy::if_same_then_else diff --git a/tests/ui/redundant_pattern_matching_poll.rs b/tests/ui/redundant_pattern_matching_poll.rs index 892a21d9d29..88dde02b38b 100644 --- a/tests/ui/redundant_pattern_matching_poll.rs +++ b/tests/ui/redundant_pattern_matching_poll.rs @@ -5,6 +5,7 @@ #![allow( unused_must_use, clippy::needless_bool, + clippy::needless_if, clippy::match_like_matches_macro, clippy::equatable_if_let, clippy::if_same_then_else diff --git a/tests/ui/redundant_pattern_matching_poll.stderr b/tests/ui/redundant_pattern_matching_poll.stderr index 1b480f3157f..b89fde35fcf 100644 --- a/tests/ui/redundant_pattern_matching_poll.stderr +++ b/tests/ui/redundant_pattern_matching_poll.stderr @@ -1,5 +1,5 @@ error: redundant pattern matching, consider using `is_pending()` - --> $DIR/redundant_pattern_matching_poll.rs:16:12 + --> $DIR/redundant_pattern_matching_poll.rs:17:12 | LL | if let Pending = Pending::<()> {} | -------^^^^^^^---------------- help: try this: `if Pending::<()>.is_pending()` @@ -7,37 +7,37 @@ LL | if let Pending = Pending::<()> {} = note: `-D clippy::redundant-pattern-matching` implied by `-D warnings` error: redundant pattern matching, consider using `is_ready()` - --> $DIR/redundant_pattern_matching_poll.rs:18:12 + --> $DIR/redundant_pattern_matching_poll.rs:19:12 | LL | if let Ready(_) = Ready(42) {} | -------^^^^^^^^------------ help: try this: `if Ready(42).is_ready()` error: redundant pattern matching, consider using `is_ready()` - --> $DIR/redundant_pattern_matching_poll.rs:20:12 + --> $DIR/redundant_pattern_matching_poll.rs:21:12 | LL | if let Ready(_) = Ready(42) { | -------^^^^^^^^------------ help: try this: `if Ready(42).is_ready()` error: redundant pattern matching, consider using `is_ready()` - --> $DIR/redundant_pattern_matching_poll.rs:26:15 + --> $DIR/redundant_pattern_matching_poll.rs:27:15 | LL | while let Ready(_) = Ready(42) {} | ----------^^^^^^^^------------ help: try this: `while Ready(42).is_ready()` error: redundant pattern matching, consider using `is_pending()` - --> $DIR/redundant_pattern_matching_poll.rs:28:15 + --> $DIR/redundant_pattern_matching_poll.rs:29:15 | LL | while let Pending = Ready(42) {} | ----------^^^^^^^------------ help: try this: `while Ready(42).is_pending()` error: redundant pattern matching, consider using `is_pending()` - --> $DIR/redundant_pattern_matching_poll.rs:30:15 + --> $DIR/redundant_pattern_matching_poll.rs:31:15 | LL | while let Pending = Pending::<()> {} | ----------^^^^^^^---------------- help: try this: `while Pending::<()>.is_pending()` error: redundant pattern matching, consider using `is_ready()` - --> $DIR/redundant_pattern_matching_poll.rs:36:5 + --> $DIR/redundant_pattern_matching_poll.rs:37:5 | LL | / match Ready(42) { LL | | Ready(_) => true, @@ -46,7 +46,7 @@ LL | | }; | |_____^ help: try this: `Ready(42).is_ready()` error: redundant pattern matching, consider using `is_pending()` - --> $DIR/redundant_pattern_matching_poll.rs:41:5 + --> $DIR/redundant_pattern_matching_poll.rs:42:5 | LL | / match Pending::<()> { LL | | Ready(_) => false, @@ -55,7 +55,7 @@ LL | | }; | |_____^ help: try this: `Pending::<()>.is_pending()` error: redundant pattern matching, consider using `is_pending()` - --> $DIR/redundant_pattern_matching_poll.rs:46:13 + --> $DIR/redundant_pattern_matching_poll.rs:47:13 | LL | let _ = match Pending::<()> { | _____________^ @@ -65,49 +65,49 @@ LL | | }; | |_____^ help: try this: `Pending::<()>.is_pending()` error: redundant pattern matching, consider using `is_ready()` - --> $DIR/redundant_pattern_matching_poll.rs:52:20 + --> $DIR/redundant_pattern_matching_poll.rs:53:20 | LL | let _ = if let Ready(_) = poll { true } else { false }; | -------^^^^^^^^------- help: try this: `if poll.is_ready()` error: redundant pattern matching, consider using `is_ready()` - --> $DIR/redundant_pattern_matching_poll.rs:56:20 + --> $DIR/redundant_pattern_matching_poll.rs:57:20 | LL | let _ = if let Ready(_) = gen_poll() { | -------^^^^^^^^------------- help: try this: `if gen_poll().is_ready()` error: redundant pattern matching, consider using `is_pending()` - --> $DIR/redundant_pattern_matching_poll.rs:58:19 + --> $DIR/redundant_pattern_matching_poll.rs:59:19 | LL | } else if let Pending = gen_poll() { | -------^^^^^^^------------- help: try this: `if gen_poll().is_pending()` error: redundant pattern matching, consider using `is_ready()` - --> $DIR/redundant_pattern_matching_poll.rs:74:12 + --> $DIR/redundant_pattern_matching_poll.rs:75:12 | LL | if let Ready(_) = Ready(42) {} | -------^^^^^^^^------------ help: try this: `if Ready(42).is_ready()` error: redundant pattern matching, consider using `is_pending()` - --> $DIR/redundant_pattern_matching_poll.rs:76:12 + --> $DIR/redundant_pattern_matching_poll.rs:77:12 | LL | if let Pending = Pending::<()> {} | -------^^^^^^^---------------- help: try this: `if Pending::<()>.is_pending()` error: redundant pattern matching, consider using `is_ready()` - --> $DIR/redundant_pattern_matching_poll.rs:78:15 + --> $DIR/redundant_pattern_matching_poll.rs:79:15 | LL | while let Ready(_) = Ready(42) {} | ----------^^^^^^^^------------ help: try this: `while Ready(42).is_ready()` error: redundant pattern matching, consider using `is_pending()` - --> $DIR/redundant_pattern_matching_poll.rs:80:15 + --> $DIR/redundant_pattern_matching_poll.rs:81:15 | LL | while let Pending = Pending::<()> {} | ----------^^^^^^^---------------- help: try this: `while Pending::<()>.is_pending()` error: redundant pattern matching, consider using `is_ready()` - --> $DIR/redundant_pattern_matching_poll.rs:82:5 + --> $DIR/redundant_pattern_matching_poll.rs:83:5 | LL | / match Ready(42) { LL | | Ready(_) => true, @@ -116,7 +116,7 @@ LL | | }; | |_____^ help: try this: `Ready(42).is_ready()` error: redundant pattern matching, consider using `is_pending()` - --> $DIR/redundant_pattern_matching_poll.rs:87:5 + --> $DIR/redundant_pattern_matching_poll.rs:88:5 | LL | / match Pending::<()> { LL | | Ready(_) => false, diff --git a/tests/ui/redundant_pattern_matching_result.fixed b/tests/ui/redundant_pattern_matching_result.fixed index d77a2af7616..343e0d04340 100644 --- a/tests/ui/redundant_pattern_matching_result.fixed +++ b/tests/ui/redundant_pattern_matching_result.fixed @@ -6,6 +6,7 @@ clippy::if_same_then_else, clippy::match_like_matches_macro, clippy::needless_bool, + clippy::needless_if, clippy::uninlined_format_args, clippy::unnecessary_wraps )] diff --git a/tests/ui/redundant_pattern_matching_result.rs b/tests/ui/redundant_pattern_matching_result.rs index aa884ac6bb1..4d64eafe590 100644 --- a/tests/ui/redundant_pattern_matching_result.rs +++ b/tests/ui/redundant_pattern_matching_result.rs @@ -6,6 +6,7 @@ clippy::if_same_then_else, clippy::match_like_matches_macro, clippy::needless_bool, + clippy::needless_if, clippy::uninlined_format_args, clippy::unnecessary_wraps )] diff --git a/tests/ui/redundant_pattern_matching_result.stderr b/tests/ui/redundant_pattern_matching_result.stderr index b462f7f41b9..f6ce666bb4f 100644 --- a/tests/ui/redundant_pattern_matching_result.stderr +++ b/tests/ui/redundant_pattern_matching_result.stderr @@ -1,5 +1,5 @@ error: redundant pattern matching, consider using `is_ok()` - --> $DIR/redundant_pattern_matching_result.rs:15:12 + --> $DIR/redundant_pattern_matching_result.rs:16:12 | LL | if let Ok(_) = &result {} | -------^^^^^---------- help: try this: `if result.is_ok()` @@ -7,31 +7,31 @@ LL | if let Ok(_) = &result {} = note: `-D clippy::redundant-pattern-matching` implied by `-D warnings` error: redundant pattern matching, consider using `is_ok()` - --> $DIR/redundant_pattern_matching_result.rs:17:12 + --> $DIR/redundant_pattern_matching_result.rs:18:12 | LL | if let Ok(_) = Ok::(42) {} | -------^^^^^--------------------- help: try this: `if Ok::(42).is_ok()` error: redundant pattern matching, consider using `is_err()` - --> $DIR/redundant_pattern_matching_result.rs:19:12 + --> $DIR/redundant_pattern_matching_result.rs:20:12 | LL | if let Err(_) = Err::(42) {} | -------^^^^^^---------------------- help: try this: `if Err::(42).is_err()` error: redundant pattern matching, consider using `is_ok()` - --> $DIR/redundant_pattern_matching_result.rs:21:15 + --> $DIR/redundant_pattern_matching_result.rs:22:15 | LL | while let Ok(_) = Ok::(10) {} | ----------^^^^^--------------------- help: try this: `while Ok::(10).is_ok()` error: redundant pattern matching, consider using `is_err()` - --> $DIR/redundant_pattern_matching_result.rs:23:15 + --> $DIR/redundant_pattern_matching_result.rs:24:15 | LL | while let Err(_) = Ok::(10) {} | ----------^^^^^^--------------------- help: try this: `while Ok::(10).is_err()` error: redundant pattern matching, consider using `is_ok()` - --> $DIR/redundant_pattern_matching_result.rs:33:5 + --> $DIR/redundant_pattern_matching_result.rs:34:5 | LL | / match Ok::(42) { LL | | Ok(_) => true, @@ -40,7 +40,7 @@ LL | | }; | |_____^ help: try this: `Ok::(42).is_ok()` error: redundant pattern matching, consider using `is_err()` - --> $DIR/redundant_pattern_matching_result.rs:38:5 + --> $DIR/redundant_pattern_matching_result.rs:39:5 | LL | / match Ok::(42) { LL | | Ok(_) => false, @@ -49,7 +49,7 @@ LL | | }; | |_____^ help: try this: `Ok::(42).is_err()` error: redundant pattern matching, consider using `is_err()` - --> $DIR/redundant_pattern_matching_result.rs:43:5 + --> $DIR/redundant_pattern_matching_result.rs:44:5 | LL | / match Err::(42) { LL | | Ok(_) => false, @@ -58,7 +58,7 @@ LL | | }; | |_____^ help: try this: `Err::(42).is_err()` error: redundant pattern matching, consider using `is_ok()` - --> $DIR/redundant_pattern_matching_result.rs:48:5 + --> $DIR/redundant_pattern_matching_result.rs:49:5 | LL | / match Err::(42) { LL | | Ok(_) => true, @@ -67,73 +67,73 @@ LL | | }; | |_____^ help: try this: `Err::(42).is_ok()` error: redundant pattern matching, consider using `is_ok()` - --> $DIR/redundant_pattern_matching_result.rs:53:20 + --> $DIR/redundant_pattern_matching_result.rs:54:20 | LL | let _ = if let Ok(_) = Ok::(4) { true } else { false }; | -------^^^^^--------------------- help: try this: `if Ok::(4).is_ok()` error: redundant pattern matching, consider using `is_ok()` - --> $DIR/redundant_pattern_matching_result.rs:61:20 + --> $DIR/redundant_pattern_matching_result.rs:62:20 | LL | let _ = if let Ok(_) = gen_res() { | -------^^^^^------------ help: try this: `if gen_res().is_ok()` error: redundant pattern matching, consider using `is_err()` - --> $DIR/redundant_pattern_matching_result.rs:63:19 + --> $DIR/redundant_pattern_matching_result.rs:64:19 | LL | } else if let Err(_) = gen_res() { | -------^^^^^^------------ help: try this: `if gen_res().is_err()` error: redundant pattern matching, consider using `is_some()` - --> $DIR/redundant_pattern_matching_result.rs:86:19 + --> $DIR/redundant_pattern_matching_result.rs:87:19 | LL | while let Some(_) = r#try!(result_opt()) {} | ----------^^^^^^^----------------------- help: try this: `while r#try!(result_opt()).is_some()` error: redundant pattern matching, consider using `is_some()` - --> $DIR/redundant_pattern_matching_result.rs:87:16 + --> $DIR/redundant_pattern_matching_result.rs:88:16 | LL | if let Some(_) = r#try!(result_opt()) {} | -------^^^^^^^----------------------- help: try this: `if r#try!(result_opt()).is_some()` error: redundant pattern matching, consider using `is_some()` - --> $DIR/redundant_pattern_matching_result.rs:93:12 + --> $DIR/redundant_pattern_matching_result.rs:94:12 | LL | if let Some(_) = m!() {} | -------^^^^^^^------- help: try this: `if m!().is_some()` error: redundant pattern matching, consider using `is_some()` - --> $DIR/redundant_pattern_matching_result.rs:94:15 + --> $DIR/redundant_pattern_matching_result.rs:95:15 | LL | while let Some(_) = m!() {} | ----------^^^^^^^------- help: try this: `while m!().is_some()` error: redundant pattern matching, consider using `is_ok()` - --> $DIR/redundant_pattern_matching_result.rs:112:12 + --> $DIR/redundant_pattern_matching_result.rs:113:12 | LL | if let Ok(_) = Ok::(42) {} | -------^^^^^--------------------- help: try this: `if Ok::(42).is_ok()` error: redundant pattern matching, consider using `is_err()` - --> $DIR/redundant_pattern_matching_result.rs:114:12 + --> $DIR/redundant_pattern_matching_result.rs:115:12 | LL | if let Err(_) = Err::(42) {} | -------^^^^^^---------------------- help: try this: `if Err::(42).is_err()` error: redundant pattern matching, consider using `is_ok()` - --> $DIR/redundant_pattern_matching_result.rs:116:15 + --> $DIR/redundant_pattern_matching_result.rs:117:15 | LL | while let Ok(_) = Ok::(10) {} | ----------^^^^^--------------------- help: try this: `while Ok::(10).is_ok()` error: redundant pattern matching, consider using `is_err()` - --> $DIR/redundant_pattern_matching_result.rs:118:15 + --> $DIR/redundant_pattern_matching_result.rs:119:15 | LL | while let Err(_) = Ok::(10) {} | ----------^^^^^^--------------------- help: try this: `while Ok::(10).is_err()` error: redundant pattern matching, consider using `is_ok()` - --> $DIR/redundant_pattern_matching_result.rs:120:5 + --> $DIR/redundant_pattern_matching_result.rs:121:5 | LL | / match Ok::(42) { LL | | Ok(_) => true, @@ -142,7 +142,7 @@ LL | | }; | |_____^ help: try this: `Ok::(42).is_ok()` error: redundant pattern matching, consider using `is_err()` - --> $DIR/redundant_pattern_matching_result.rs:125:5 + --> $DIR/redundant_pattern_matching_result.rs:126:5 | LL | / match Err::(42) { LL | | Ok(_) => false, @@ -151,7 +151,7 @@ LL | | }; | |_____^ help: try this: `Err::(42).is_err()` error: redundant pattern matching, consider using `is_ok()` - --> $DIR/redundant_pattern_matching_result.rs:135:5 + --> $DIR/redundant_pattern_matching_result.rs:136:5 | LL | / match x { LL | | Ok(_) => true, @@ -160,7 +160,7 @@ LL | | }; | |_____^ help: try this: `x.is_ok()` error: redundant pattern matching, consider using `is_err()` - --> $DIR/redundant_pattern_matching_result.rs:140:5 + --> $DIR/redundant_pattern_matching_result.rs:141:5 | LL | / match x { LL | | Ok(_) => false, @@ -169,7 +169,7 @@ LL | | }; | |_____^ help: try this: `x.is_err()` error: redundant pattern matching, consider using `is_err()` - --> $DIR/redundant_pattern_matching_result.rs:145:5 + --> $DIR/redundant_pattern_matching_result.rs:146:5 | LL | / match x { LL | | Err(_) => true, @@ -178,7 +178,7 @@ LL | | }; | |_____^ help: try this: `x.is_err()` error: redundant pattern matching, consider using `is_ok()` - --> $DIR/redundant_pattern_matching_result.rs:150:5 + --> $DIR/redundant_pattern_matching_result.rs:151:5 | LL | / match x { LL | | Err(_) => false, @@ -187,13 +187,13 @@ LL | | }; | |_____^ help: try this: `x.is_ok()` error: redundant pattern matching, consider using `is_ok()` - --> $DIR/redundant_pattern_matching_result.rs:171:13 + --> $DIR/redundant_pattern_matching_result.rs:172:13 | LL | let _ = matches!(x, Ok(_)); | ^^^^^^^^^^^^^^^^^^ help: try this: `x.is_ok()` error: redundant pattern matching, consider using `is_err()` - --> $DIR/redundant_pattern_matching_result.rs:173:13 + --> $DIR/redundant_pattern_matching_result.rs:174:13 | LL | let _ = matches!(x, Err(_)); | ^^^^^^^^^^^^^^^^^^^ help: try this: `x.is_err()` diff --git a/tests/ui/shadow.rs b/tests/ui/shadow.rs index 2c0fc3e3fd8..c2895718a1a 100644 --- a/tests/ui/shadow.rs +++ b/tests/ui/shadow.rs @@ -1,7 +1,7 @@ //@aux-build:proc_macro_derive.rs #![warn(clippy::shadow_same, clippy::shadow_reuse, clippy::shadow_unrelated)] -#![allow(clippy::let_unit_value)] +#![allow(clippy::let_unit_value, clippy::needless_if)] extern crate proc_macro_derive; diff --git a/tests/ui/single_match.fixed b/tests/ui/single_match.fixed index 77a2cf3b991..a54e658bf23 100644 --- a/tests/ui/single_match.fixed +++ b/tests/ui/single_match.fixed @@ -1,6 +1,11 @@ //@run-rustfix #![warn(clippy::single_match)] -#![allow(unused, clippy::uninlined_format_args, clippy::redundant_pattern_matching)] +#![allow( + unused, + clippy::uninlined_format_args, + clippy::needless_if, + clippy::redundant_pattern_matching +)] fn dummy() {} fn single_match() { diff --git a/tests/ui/single_match.rs b/tests/ui/single_match.rs index 8d0ab5b99ad..f296c6c4d1c 100644 --- a/tests/ui/single_match.rs +++ b/tests/ui/single_match.rs @@ -1,6 +1,11 @@ //@run-rustfix #![warn(clippy::single_match)] -#![allow(unused, clippy::uninlined_format_args, clippy::redundant_pattern_matching)] +#![allow( + unused, + clippy::uninlined_format_args, + clippy::needless_if, + clippy::redundant_pattern_matching +)] fn dummy() {} fn single_match() { diff --git a/tests/ui/single_match.stderr b/tests/ui/single_match.stderr index dad66e2ab2e..ef901513240 100644 --- a/tests/ui/single_match.stderr +++ b/tests/ui/single_match.stderr @@ -1,5 +1,5 @@ error: you seem to be trying to use `match` for destructuring a single pattern. Consider using `if let` - --> $DIR/single_match.rs:9:5 + --> $DIR/single_match.rs:14:5 | LL | / match x { LL | | Some(y) => { @@ -18,7 +18,7 @@ LL ~ }; | error: you seem to be trying to use `match` for destructuring a single pattern. Consider using `if let` - --> $DIR/single_match.rs:17:5 + --> $DIR/single_match.rs:22:5 | LL | / match x { LL | | // Note the missing block braces. @@ -30,7 +30,7 @@ LL | | } | |_____^ help: try this: `if let Some(y) = x { println!("{:?}", y) }` error: you seem to be trying to use `match` for destructuring a single pattern. Consider using `if let` - --> $DIR/single_match.rs:26:5 + --> $DIR/single_match.rs:31:5 | LL | / match z { LL | | (2..=3, 7..=9) => dummy(), @@ -39,7 +39,7 @@ LL | | }; | |_____^ help: try this: `if let (2..=3, 7..=9) = z { dummy() }` error: you seem to be trying to use `match` for destructuring a single pattern. Consider using `if let` - --> $DIR/single_match.rs:55:5 + --> $DIR/single_match.rs:60:5 | LL | / match x { LL | | Some(y) => dummy(), @@ -48,7 +48,7 @@ LL | | }; | |_____^ help: try this: `if let Some(y) = x { dummy() }` error: you seem to be trying to use `match` for destructuring a single pattern. Consider using `if let` - --> $DIR/single_match.rs:60:5 + --> $DIR/single_match.rs:65:5 | LL | / match y { LL | | Ok(y) => dummy(), @@ -57,7 +57,7 @@ LL | | }; | |_____^ help: try this: `if let Ok(y) = y { dummy() }` error: you seem to be trying to use `match` for destructuring a single pattern. Consider using `if let` - --> $DIR/single_match.rs:67:5 + --> $DIR/single_match.rs:72:5 | LL | / match c { LL | | Cow::Borrowed(..) => dummy(), @@ -66,7 +66,7 @@ LL | | }; | |_____^ help: try this: `if let Cow::Borrowed(..) = c { dummy() }` error: you seem to be trying to use `match` for an equality check. Consider using `if` - --> $DIR/single_match.rs:88:5 + --> $DIR/single_match.rs:93:5 | LL | / match x { LL | | "test" => println!(), @@ -75,7 +75,7 @@ LL | | } | |_____^ help: try this: `if x == "test" { println!() }` error: you seem to be trying to use `match` for an equality check. Consider using `if` - --> $DIR/single_match.rs:101:5 + --> $DIR/single_match.rs:106:5 | LL | / match x { LL | | Foo::A => println!(), @@ -84,7 +84,7 @@ LL | | } | |_____^ help: try this: `if x == Foo::A { println!() }` error: you seem to be trying to use `match` for an equality check. Consider using `if` - --> $DIR/single_match.rs:107:5 + --> $DIR/single_match.rs:112:5 | LL | / match x { LL | | FOO_C => println!(), @@ -93,7 +93,7 @@ LL | | } | |_____^ help: try this: `if x == FOO_C { println!() }` error: you seem to be trying to use `match` for an equality check. Consider using `if` - --> $DIR/single_match.rs:112:5 + --> $DIR/single_match.rs:117:5 | LL | / match &&x { LL | | Foo::A => println!(), @@ -102,7 +102,7 @@ LL | | } | |_____^ help: try this: `if x == Foo::A { println!() }` error: you seem to be trying to use `match` for an equality check. Consider using `if` - --> $DIR/single_match.rs:118:5 + --> $DIR/single_match.rs:123:5 | LL | / match &x { LL | | Foo::A => println!(), @@ -111,7 +111,7 @@ LL | | } | |_____^ help: try this: `if x == &Foo::A { println!() }` error: you seem to be trying to use `match` for destructuring a single pattern. Consider using `if let` - --> $DIR/single_match.rs:135:5 + --> $DIR/single_match.rs:140:5 | LL | / match x { LL | | Bar::A => println!(), @@ -120,7 +120,7 @@ LL | | } | |_____^ help: try this: `if let Bar::A = x { println!() }` error: you seem to be trying to use `match` for destructuring a single pattern. Consider using `if let` - --> $DIR/single_match.rs:143:5 + --> $DIR/single_match.rs:148:5 | LL | / match x { LL | | None => println!(), @@ -129,7 +129,7 @@ LL | | }; | |_____^ help: try this: `if let None = x { println!() }` error: you seem to be trying to use `match` for destructuring a single pattern. Consider using `if let` - --> $DIR/single_match.rs:165:5 + --> $DIR/single_match.rs:170:5 | LL | / match x { LL | | (Some(_), _) => {}, @@ -138,7 +138,7 @@ LL | | } | |_____^ help: try this: `if let (Some(_), _) = x {}` error: you seem to be trying to use `match` for destructuring a single pattern. Consider using `if let` - --> $DIR/single_match.rs:171:5 + --> $DIR/single_match.rs:176:5 | LL | / match x { LL | | (Some(E::V), _) => todo!(), @@ -147,7 +147,7 @@ LL | | } | |_____^ help: try this: `if let (Some(E::V), _) = x { todo!() }` error: you seem to be trying to use `match` for destructuring a single pattern. Consider using `if let` - --> $DIR/single_match.rs:177:5 + --> $DIR/single_match.rs:182:5 | LL | / match (Some(42), Some(E::V), Some(42)) { LL | | (.., Some(E::V), _) => {}, @@ -156,7 +156,7 @@ LL | | } | |_____^ help: try this: `if let (.., Some(E::V), _) = (Some(42), Some(E::V), Some(42)) {}` error: you seem to be trying to use `match` for destructuring a single pattern. Consider using `if let` - --> $DIR/single_match.rs:249:5 + --> $DIR/single_match.rs:254:5 | LL | / match bar { LL | | Some(v) => unsafe { @@ -176,7 +176,7 @@ LL + } } | error: you seem to be trying to use `match` for destructuring a single pattern. Consider using `if let` - --> $DIR/single_match.rs:257:5 + --> $DIR/single_match.rs:262:5 | LL | / match bar { LL | | #[rustfmt::skip] diff --git a/tests/ui/starts_ends_with.fixed b/tests/ui/starts_ends_with.fixed index 29d56f852ed..b7237069dc5 100644 --- a/tests/ui/starts_ends_with.fixed +++ b/tests/ui/starts_ends_with.fixed @@ -1,5 +1,5 @@ //@run-rustfix -#![allow(dead_code, unused_must_use)] +#![allow(clippy::needless_if, dead_code, unused_must_use)] fn main() {} diff --git a/tests/ui/starts_ends_with.rs b/tests/ui/starts_ends_with.rs index 56bbe2574d4..658312e87e4 100644 --- a/tests/ui/starts_ends_with.rs +++ b/tests/ui/starts_ends_with.rs @@ -1,5 +1,5 @@ //@run-rustfix -#![allow(dead_code, unused_must_use)] +#![allow(clippy::needless_if, dead_code, unused_must_use)] fn main() {} diff --git a/tests/ui/suspicious_else_formatting.rs b/tests/ui/suspicious_else_formatting.rs index a96cc1b090c..c0856427eae 100644 --- a/tests/ui/suspicious_else_formatting.rs +++ b/tests/ui/suspicious_else_formatting.rs @@ -1,7 +1,12 @@ //@aux-build:proc_macro_suspicious_else_formatting.rs #![warn(clippy::suspicious_else_formatting)] -#![allow(clippy::if_same_then_else, clippy::let_unit_value, clippy::needless_else)] +#![allow( + clippy::if_same_then_else, + clippy::let_unit_value, + clippy::needless_if, + clippy::needless_else +)] extern crate proc_macro_suspicious_else_formatting; use proc_macro_suspicious_else_formatting::DeriveBadSpan; diff --git a/tests/ui/suspicious_else_formatting.stderr b/tests/ui/suspicious_else_formatting.stderr index 2e512b47f12..723fdd7e93e 100644 --- a/tests/ui/suspicious_else_formatting.stderr +++ b/tests/ui/suspicious_else_formatting.stderr @@ -1,5 +1,5 @@ error: this looks like an `else {..}` but the `else` is missing - --> $DIR/suspicious_else_formatting.rs:17:6 + --> $DIR/suspicious_else_formatting.rs:22:6 | LL | } { | ^ @@ -8,7 +8,7 @@ LL | } { = note: `-D clippy::suspicious-else-formatting` implied by `-D warnings` error: this looks like an `else if` but the `else` is missing - --> $DIR/suspicious_else_formatting.rs:21:6 + --> $DIR/suspicious_else_formatting.rs:26:6 | LL | } if foo() { | ^ @@ -16,7 +16,7 @@ LL | } if foo() { = note: to remove this lint, add the missing `else` or add a new line before the second `if` error: this looks like an `else if` but the `else` is missing - --> $DIR/suspicious_else_formatting.rs:28:10 + --> $DIR/suspicious_else_formatting.rs:33:10 | LL | } if foo() { | ^ @@ -24,7 +24,7 @@ LL | } if foo() { = note: to remove this lint, add the missing `else` or add a new line before the second `if` error: this looks like an `else if` but the `else` is missing - --> $DIR/suspicious_else_formatting.rs:36:10 + --> $DIR/suspicious_else_formatting.rs:41:10 | LL | } if foo() { | ^ @@ -32,7 +32,7 @@ LL | } if foo() { = note: to remove this lint, add the missing `else` or add a new line before the second `if` error: this is an `else {..}` but the formatting might hide it - --> $DIR/suspicious_else_formatting.rs:45:6 + --> $DIR/suspicious_else_formatting.rs:50:6 | LL | } else | ______^ @@ -42,7 +42,7 @@ LL | | { = note: to remove this lint, remove the `else` or remove the new line between `else` and `{..}` error: this is an `else if` but the formatting might hide it - --> $DIR/suspicious_else_formatting.rs:57:6 + --> $DIR/suspicious_else_formatting.rs:62:6 | LL | } else | ______^ @@ -52,7 +52,7 @@ LL | | if foo() { // the span of the above error should continue here = note: to remove this lint, remove the `else` or remove the new line between `else` and `if` error: this is an `else if` but the formatting might hide it - --> $DIR/suspicious_else_formatting.rs:62:6 + --> $DIR/suspicious_else_formatting.rs:67:6 | LL | } | ______^ @@ -63,7 +63,7 @@ LL | | if foo() { // the span of the above error should continue here = note: to remove this lint, remove the `else` or remove the new line between `else` and `if` error: this is an `else {..}` but the formatting might hide it - --> $DIR/suspicious_else_formatting.rs:89:6 + --> $DIR/suspicious_else_formatting.rs:94:6 | LL | } | ______^ @@ -75,7 +75,7 @@ LL | | { = note: to remove this lint, remove the `else` or remove the new line between `else` and `{..}` error: this is an `else {..}` but the formatting might hide it - --> $DIR/suspicious_else_formatting.rs:97:6 + --> $DIR/suspicious_else_formatting.rs:102:6 | LL | } | ______^ diff --git a/tests/ui/suspicious_unary_op_formatting.rs b/tests/ui/suspicious_unary_op_formatting.rs index 9564e373c24..3c5ca1762fe 100644 --- a/tests/ui/suspicious_unary_op_formatting.rs +++ b/tests/ui/suspicious_unary_op_formatting.rs @@ -1,4 +1,5 @@ #![warn(clippy::suspicious_unary_op_formatting)] +#![allow(clippy::needless_if)] #[rustfmt::skip] fn main() { diff --git a/tests/ui/suspicious_unary_op_formatting.stderr b/tests/ui/suspicious_unary_op_formatting.stderr index 9f1289ccba0..52b0e99a1d3 100644 --- a/tests/ui/suspicious_unary_op_formatting.stderr +++ b/tests/ui/suspicious_unary_op_formatting.stderr @@ -1,5 +1,5 @@ error: by not having a space between `>` and `-` it looks like `>-` is a single operator - --> $DIR/suspicious_unary_op_formatting.rs:8:9 + --> $DIR/suspicious_unary_op_formatting.rs:9:9 | LL | if a >- 30 {} | ^^^^ @@ -8,7 +8,7 @@ LL | if a >- 30 {} = note: `-D clippy::suspicious-unary-op-formatting` implied by `-D warnings` error: by not having a space between `>=` and `-` it looks like `>=-` is a single operator - --> $DIR/suspicious_unary_op_formatting.rs:9:9 + --> $DIR/suspicious_unary_op_formatting.rs:10:9 | LL | if a >=- 30 {} | ^^^^^ @@ -16,7 +16,7 @@ LL | if a >=- 30 {} = help: put a space between `>=` and `-` and remove the space after `-` error: by not having a space between `&&` and `!` it looks like `&&!` is a single operator - --> $DIR/suspicious_unary_op_formatting.rs:14:9 + --> $DIR/suspicious_unary_op_formatting.rs:15:9 | LL | if b &&! c {} | ^^^^^ @@ -24,7 +24,7 @@ LL | if b &&! c {} = help: put a space between `&&` and `!` and remove the space after `!` error: by not having a space between `>` and `-` it looks like `>-` is a single operator - --> $DIR/suspicious_unary_op_formatting.rs:16:9 + --> $DIR/suspicious_unary_op_formatting.rs:17:9 | LL | if a >- 30 {} | ^^^^^^ diff --git a/tests/ui/unit_cmp.rs b/tests/ui/unit_cmp.rs index 3d271104361..fc75f548a1b 100644 --- a/tests/ui/unit_cmp.rs +++ b/tests/ui/unit_cmp.rs @@ -2,7 +2,8 @@ #![allow( clippy::no_effect, clippy::unnecessary_operation, - clippy::derive_partial_eq_without_eq + clippy::derive_partial_eq_without_eq, + clippy::needless_if )] #[derive(PartialEq)] diff --git a/tests/ui/unit_cmp.stderr b/tests/ui/unit_cmp.stderr index 41cf19ae685..79c890d644c 100644 --- a/tests/ui/unit_cmp.stderr +++ b/tests/ui/unit_cmp.stderr @@ -1,5 +1,5 @@ error: ==-comparison of unit values detected. This will always be true - --> $DIR/unit_cmp.rs:16:8 + --> $DIR/unit_cmp.rs:17:8 | LL | if { | ________^ @@ -12,7 +12,7 @@ LL | | } {} = note: `-D clippy::unit-cmp` implied by `-D warnings` error: >-comparison of unit values detected. This will always be false - --> $DIR/unit_cmp.rs:22:8 + --> $DIR/unit_cmp.rs:23:8 | LL | if { | ________^ @@ -23,7 +23,7 @@ LL | | } {} | |_____^ error: `assert_eq` of unit values detected. This will always succeed - --> $DIR/unit_cmp.rs:28:5 + --> $DIR/unit_cmp.rs:29:5 | LL | / assert_eq!( LL | | { @@ -35,7 +35,7 @@ LL | | ); | |_____^ error: `debug_assert_eq` of unit values detected. This will always succeed - --> $DIR/unit_cmp.rs:36:5 + --> $DIR/unit_cmp.rs:37:5 | LL | / debug_assert_eq!( LL | | { @@ -47,7 +47,7 @@ LL | | ); | |_____^ error: `assert_ne` of unit values detected. This will always fail - --> $DIR/unit_cmp.rs:45:5 + --> $DIR/unit_cmp.rs:46:5 | LL | / assert_ne!( LL | | { @@ -59,7 +59,7 @@ LL | | ); | |_____^ error: `debug_assert_ne` of unit values detected. This will always fail - --> $DIR/unit_cmp.rs:53:5 + --> $DIR/unit_cmp.rs:54:5 | LL | / debug_assert_ne!( LL | | { diff --git a/tests/ui/unnecessary_safety_comment.rs b/tests/ui/unnecessary_safety_comment.rs index 89fedb145f8..d858701ae8a 100644 --- a/tests/ui/unnecessary_safety_comment.rs +++ b/tests/ui/unnecessary_safety_comment.rs @@ -1,5 +1,5 @@ #![warn(clippy::undocumented_unsafe_blocks, clippy::unnecessary_safety_comment)] -#![allow(clippy::let_unit_value, clippy::missing_safety_doc)] +#![allow(clippy::let_unit_value, clippy::missing_safety_doc, clippy::needless_if)] mod unsafe_items_invalid_comment { // SAFETY: diff --git a/tests/ui/unneeded_wildcard_pattern.fixed b/tests/ui/unneeded_wildcard_pattern.fixed index 16c2de760e5..d18c65a7709 100644 --- a/tests/ui/unneeded_wildcard_pattern.fixed +++ b/tests/ui/unneeded_wildcard_pattern.fixed @@ -1,6 +1,7 @@ //@run-rustfix #![feature(stmt_expr_attributes)] #![deny(clippy::unneeded_wildcard_pattern)] +#![allow(clippy::needless_if)] fn main() { let t = (0, 1, 2, 3); diff --git a/tests/ui/unneeded_wildcard_pattern.rs b/tests/ui/unneeded_wildcard_pattern.rs index 9d9eae1d903..c80756c4495 100644 --- a/tests/ui/unneeded_wildcard_pattern.rs +++ b/tests/ui/unneeded_wildcard_pattern.rs @@ -1,6 +1,7 @@ //@run-rustfix #![feature(stmt_expr_attributes)] #![deny(clippy::unneeded_wildcard_pattern)] +#![allow(clippy::needless_if)] fn main() { let t = (0, 1, 2, 3); diff --git a/tests/ui/unneeded_wildcard_pattern.stderr b/tests/ui/unneeded_wildcard_pattern.stderr index 716d9ecff89..8a004b77e94 100644 --- a/tests/ui/unneeded_wildcard_pattern.stderr +++ b/tests/ui/unneeded_wildcard_pattern.stderr @@ -1,5 +1,5 @@ error: this pattern is unneeded as the `..` pattern can match that element - --> $DIR/unneeded_wildcard_pattern.rs:8:18 + --> $DIR/unneeded_wildcard_pattern.rs:9:18 | LL | if let (0, .., _) = t {}; | ^^^ help: remove it @@ -11,79 +11,79 @@ LL | #![deny(clippy::unneeded_wildcard_pattern)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: this pattern is unneeded as the `..` pattern can match that element - --> $DIR/unneeded_wildcard_pattern.rs:9:16 + --> $DIR/unneeded_wildcard_pattern.rs:10:16 | LL | if let (0, _, ..) = t {}; | ^^^ help: remove it error: this pattern is unneeded as the `..` pattern can match that element - --> $DIR/unneeded_wildcard_pattern.rs:10:13 + --> $DIR/unneeded_wildcard_pattern.rs:11:13 | LL | if let (_, .., 0) = t {}; | ^^^ help: remove it error: this pattern is unneeded as the `..` pattern can match that element - --> $DIR/unneeded_wildcard_pattern.rs:11:15 + --> $DIR/unneeded_wildcard_pattern.rs:12:15 | LL | if let (.., _, 0) = t {}; | ^^^ help: remove it error: these patterns are unneeded as the `..` pattern can match those elements - --> $DIR/unneeded_wildcard_pattern.rs:12:16 + --> $DIR/unneeded_wildcard_pattern.rs:13:16 | LL | if let (0, _, _, ..) = t {}; | ^^^^^^ help: remove them error: these patterns are unneeded as the `..` pattern can match those elements - --> $DIR/unneeded_wildcard_pattern.rs:13:18 + --> $DIR/unneeded_wildcard_pattern.rs:14:18 | LL | if let (0, .., _, _) = t {}; | ^^^^^^ help: remove them error: these patterns are unneeded as the `..` pattern can match those elements - --> $DIR/unneeded_wildcard_pattern.rs:22:22 + --> $DIR/unneeded_wildcard_pattern.rs:23:22 | LL | if let (0, .., _, _,) = t {}; | ^^^^^^ help: remove them error: this pattern is unneeded as the `..` pattern can match that element - --> $DIR/unneeded_wildcard_pattern.rs:29:19 + --> $DIR/unneeded_wildcard_pattern.rs:30:19 | LL | if let S(0, .., _) = s {}; | ^^^ help: remove it error: this pattern is unneeded as the `..` pattern can match that element - --> $DIR/unneeded_wildcard_pattern.rs:30:17 + --> $DIR/unneeded_wildcard_pattern.rs:31:17 | LL | if let S(0, _, ..) = s {}; | ^^^ help: remove it error: this pattern is unneeded as the `..` pattern can match that element - --> $DIR/unneeded_wildcard_pattern.rs:31:14 + --> $DIR/unneeded_wildcard_pattern.rs:32:14 | LL | if let S(_, .., 0) = s {}; | ^^^ help: remove it error: this pattern is unneeded as the `..` pattern can match that element - --> $DIR/unneeded_wildcard_pattern.rs:32:16 + --> $DIR/unneeded_wildcard_pattern.rs:33:16 | LL | if let S(.., _, 0) = s {}; | ^^^ help: remove it error: these patterns are unneeded as the `..` pattern can match those elements - --> $DIR/unneeded_wildcard_pattern.rs:33:17 + --> $DIR/unneeded_wildcard_pattern.rs:34:17 | LL | if let S(0, _, _, ..) = s {}; | ^^^^^^ help: remove them error: these patterns are unneeded as the `..` pattern can match those elements - --> $DIR/unneeded_wildcard_pattern.rs:34:19 + --> $DIR/unneeded_wildcard_pattern.rs:35:19 | LL | if let S(0, .., _, _) = s {}; | ^^^^^^ help: remove them error: these patterns are unneeded as the `..` pattern can match those elements - --> $DIR/unneeded_wildcard_pattern.rs:43:23 + --> $DIR/unneeded_wildcard_pattern.rs:44:23 | LL | if let S(0, .., _, _,) = s {}; | ^^^^^^ help: remove them diff --git a/tests/ui/unnested_or_patterns.fixed b/tests/ui/unnested_or_patterns.fixed index 8ec35ba4eea..4ce6e866695 100644 --- a/tests/ui/unnested_or_patterns.fixed +++ b/tests/ui/unnested_or_patterns.fixed @@ -2,7 +2,12 @@ #![feature(box_patterns)] #![warn(clippy::unnested_or_patterns)] -#![allow(clippy::cognitive_complexity, clippy::match_ref_pats, clippy::upper_case_acronyms)] +#![allow( + clippy::cognitive_complexity, + clippy::match_ref_pats, + clippy::upper_case_acronyms, + clippy::needless_if +)] #![allow(unreachable_patterns, irrefutable_let_patterns, unused)] fn main() { diff --git a/tests/ui/unnested_or_patterns.rs b/tests/ui/unnested_or_patterns.rs index efdb91b2402..07d60fac082 100644 --- a/tests/ui/unnested_or_patterns.rs +++ b/tests/ui/unnested_or_patterns.rs @@ -2,7 +2,12 @@ #![feature(box_patterns)] #![warn(clippy::unnested_or_patterns)] -#![allow(clippy::cognitive_complexity, clippy::match_ref_pats, clippy::upper_case_acronyms)] +#![allow( + clippy::cognitive_complexity, + clippy::match_ref_pats, + clippy::upper_case_acronyms, + clippy::needless_if +)] #![allow(unreachable_patterns, irrefutable_let_patterns, unused)] fn main() { diff --git a/tests/ui/unnested_or_patterns.stderr b/tests/ui/unnested_or_patterns.stderr index a1f193db555..d7b582fc8bd 100644 --- a/tests/ui/unnested_or_patterns.stderr +++ b/tests/ui/unnested_or_patterns.stderr @@ -1,5 +1,5 @@ error: unnested or-patterns - --> $DIR/unnested_or_patterns.rs:12:12 + --> $DIR/unnested_or_patterns.rs:17:12 | LL | if let box 0 | box 2 = Box::new(0) {} | ^^^^^^^^^^^^^ @@ -11,7 +11,7 @@ LL | if let box (0 | 2) = Box::new(0) {} | ~~~~~~~~~~~ error: unnested or-patterns - --> $DIR/unnested_or_patterns.rs:13:12 + --> $DIR/unnested_or_patterns.rs:18:12 | LL | if let box ((0 | 1)) | box (2 | 3) | box 4 = Box::new(0) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -22,7 +22,7 @@ LL | if let box (0 | 1 | 2 | 3 | 4) = Box::new(0) {} | ~~~~~~~~~~~~~~~~~~~~~~~ error: unnested or-patterns - --> $DIR/unnested_or_patterns.rs:15:12 + --> $DIR/unnested_or_patterns.rs:20:12 | LL | if let Some(1) | C0 | Some(2) = None {} | ^^^^^^^^^^^^^^^^^^^^^^ @@ -33,7 +33,7 @@ LL | if let Some(1 | 2) | C0 = None {} | ~~~~~~~~~~~~~~~~ error: unnested or-patterns - --> $DIR/unnested_or_patterns.rs:16:12 + --> $DIR/unnested_or_patterns.rs:21:12 | LL | if let &mut 0 | &mut 2 = &mut 0 {} | ^^^^^^^^^^^^^^^ @@ -44,7 +44,7 @@ LL | if let &mut (0 | 2) = &mut 0 {} | ~~~~~~~~~~~~ error: unnested or-patterns - --> $DIR/unnested_or_patterns.rs:17:12 + --> $DIR/unnested_or_patterns.rs:22:12 | LL | if let x @ 0 | x @ 2 = 0 {} | ^^^^^^^^^^^^^ @@ -55,7 +55,7 @@ LL | if let x @ (0 | 2) = 0 {} | ~~~~~~~~~~~ error: unnested or-patterns - --> $DIR/unnested_or_patterns.rs:18:12 + --> $DIR/unnested_or_patterns.rs:23:12 | LL | if let (0, 1) | (0, 2) | (0, 3) = (0, 0) {} | ^^^^^^^^^^^^^^^^^^^^^^^^ @@ -66,7 +66,7 @@ LL | if let (0, 1 | 2 | 3) = (0, 0) {} | ~~~~~~~~~~~~~~ error: unnested or-patterns - --> $DIR/unnested_or_patterns.rs:19:12 + --> $DIR/unnested_or_patterns.rs:24:12 | LL | if let (1, 0) | (2, 0) | (3, 0) = (0, 0) {} | ^^^^^^^^^^^^^^^^^^^^^^^^ @@ -77,7 +77,7 @@ LL | if let (1 | 2 | 3, 0) = (0, 0) {} | ~~~~~~~~~~~~~~ error: unnested or-patterns - --> $DIR/unnested_or_patterns.rs:20:12 + --> $DIR/unnested_or_patterns.rs:25:12 | LL | if let (x, ..) | (x, 1) | (x, 2) = (0, 1) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -88,7 +88,7 @@ LL | if let (x, ..) | (x, 1 | 2) = (0, 1) {} | ~~~~~~~~~~~~~~~~~~~~ error: unnested or-patterns - --> $DIR/unnested_or_patterns.rs:21:12 + --> $DIR/unnested_or_patterns.rs:26:12 | LL | if let [0] | [1] = [0] {} | ^^^^^^^^^ @@ -99,7 +99,7 @@ LL | if let [0 | 1] = [0] {} | ~~~~~~~ error: unnested or-patterns - --> $DIR/unnested_or_patterns.rs:22:12 + --> $DIR/unnested_or_patterns.rs:27:12 | LL | if let [x, 0] | [x, 1] = [0, 1] {} | ^^^^^^^^^^^^^^^ @@ -110,7 +110,7 @@ LL | if let [x, 0 | 1] = [0, 1] {} | ~~~~~~~~~~ error: unnested or-patterns - --> $DIR/unnested_or_patterns.rs:23:12 + --> $DIR/unnested_or_patterns.rs:28:12 | LL | if let [x, 0] | [x, 1] | [x, 2] = [0, 1] {} | ^^^^^^^^^^^^^^^^^^^^^^^^ @@ -121,7 +121,7 @@ LL | if let [x, 0 | 1 | 2] = [0, 1] {} | ~~~~~~~~~~~~~~ error: unnested or-patterns - --> $DIR/unnested_or_patterns.rs:24:12 + --> $DIR/unnested_or_patterns.rs:29:12 | LL | if let [x, ..] | [x, 1] | [x, 2] = [0, 1] {} | ^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -132,7 +132,7 @@ LL | if let [x, ..] | [x, 1 | 2] = [0, 1] {} | ~~~~~~~~~~~~~~~~~~~~ error: unnested or-patterns - --> $DIR/unnested_or_patterns.rs:26:12 + --> $DIR/unnested_or_patterns.rs:31:12 | LL | if let TS(0, x) | TS(1, x) = TS(0, 0) {} | ^^^^^^^^^^^^^^^^^^^ @@ -143,7 +143,7 @@ LL | if let TS(0 | 1, x) = TS(0, 0) {} | ~~~~~~~~~~~~ error: unnested or-patterns - --> $DIR/unnested_or_patterns.rs:27:12 + --> $DIR/unnested_or_patterns.rs:32:12 | LL | if let TS(1, 0) | TS(2, 0) | TS(3, 0) = TS(0, 0) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -154,7 +154,7 @@ LL | if let TS(1 | 2 | 3, 0) = TS(0, 0) {} | ~~~~~~~~~~~~~~~~ error: unnested or-patterns - --> $DIR/unnested_or_patterns.rs:28:12 + --> $DIR/unnested_or_patterns.rs:33:12 | LL | if let TS(x, ..) | TS(x, 1) | TS(x, 2) = TS(0, 0) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -165,7 +165,7 @@ LL | if let TS(x, ..) | TS(x, 1 | 2) = TS(0, 0) {} | ~~~~~~~~~~~~~~~~~~~~~~~~ error: unnested or-patterns - --> $DIR/unnested_or_patterns.rs:33:12 + --> $DIR/unnested_or_patterns.rs:38:12 | LL | if let S { x: 0, y } | S { y, x: 1 } = (S { x: 0, y: 1 }) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -176,7 +176,7 @@ LL | if let S { x: 0 | 1, y } = (S { x: 0, y: 1 }) {} | ~~~~~~~~~~~~~~~~~ error: unnested or-patterns - --> $DIR/unnested_or_patterns.rs:44:12 + --> $DIR/unnested_or_patterns.rs:49:12 | LL | if let [1] | [53] = [0] {} | ^^^^^^^^^^ diff --git a/tests/ui/unnested_or_patterns2.fixed b/tests/ui/unnested_or_patterns2.fixed index de40e936747..a88d7f51ac0 100644 --- a/tests/ui/unnested_or_patterns2.fixed +++ b/tests/ui/unnested_or_patterns2.fixed @@ -2,7 +2,7 @@ #![feature(box_patterns)] #![warn(clippy::unnested_or_patterns)] -#![allow(clippy::cognitive_complexity, clippy::match_ref_pats)] +#![allow(clippy::cognitive_complexity, clippy::match_ref_pats, clippy::needless_if)] #![allow(unreachable_patterns, irrefutable_let_patterns, unused_variables)] fn main() { diff --git a/tests/ui/unnested_or_patterns2.rs b/tests/ui/unnested_or_patterns2.rs index 87f66d26c46..f6029eee441 100644 --- a/tests/ui/unnested_or_patterns2.rs +++ b/tests/ui/unnested_or_patterns2.rs @@ -2,7 +2,7 @@ #![feature(box_patterns)] #![warn(clippy::unnested_or_patterns)] -#![allow(clippy::cognitive_complexity, clippy::match_ref_pats)] +#![allow(clippy::cognitive_complexity, clippy::match_ref_pats, clippy::needless_if)] #![allow(unreachable_patterns, irrefutable_let_patterns, unused_variables)] fn main() { diff --git a/tests/ui/useless_conversion.fixed b/tests/ui/useless_conversion.fixed index e9563b8a60a..5d2c5b11658 100644 --- a/tests/ui/useless_conversion.fixed +++ b/tests/ui/useless_conversion.fixed @@ -1,7 +1,7 @@ //@run-rustfix #![deny(clippy::useless_conversion)] -#![allow(clippy::unnecessary_wraps)] +#![allow(clippy::needless_if, clippy::unnecessary_wraps)] fn test_generic(val: T) -> T { let _ = val; diff --git a/tests/ui/useless_conversion.rs b/tests/ui/useless_conversion.rs index c2f4e3117d2..03a3e3f95ba 100644 --- a/tests/ui/useless_conversion.rs +++ b/tests/ui/useless_conversion.rs @@ -1,7 +1,7 @@ //@run-rustfix #![deny(clippy::useless_conversion)] -#![allow(clippy::unnecessary_wraps)] +#![allow(clippy::needless_if, clippy::unnecessary_wraps)] fn test_generic(val: T) -> T { let _ = T::from(val); diff --git a/tests/ui/useless_conversion_try.rs b/tests/ui/useless_conversion_try.rs index 4acf5b5fa2d..ec0512ce210 100644 --- a/tests/ui/useless_conversion_try.rs +++ b/tests/ui/useless_conversion_try.rs @@ -1,4 +1,5 @@ #![deny(clippy::useless_conversion)] +#![allow(clippy::needless_if)] fn test_generic(val: T) -> T { let _ = T::try_from(val).unwrap(); diff --git a/tests/ui/useless_conversion_try.stderr b/tests/ui/useless_conversion_try.stderr index 9aef9dda6f6..54189f8d286 100644 --- a/tests/ui/useless_conversion_try.stderr +++ b/tests/ui/useless_conversion_try.stderr @@ -1,5 +1,5 @@ error: useless conversion to the same type: `T` - --> $DIR/useless_conversion_try.rs:4:13 + --> $DIR/useless_conversion_try.rs:5:13 | LL | let _ = T::try_from(val).unwrap(); | ^^^^^^^^^^^^^^^^ @@ -12,7 +12,7 @@ LL | #![deny(clippy::useless_conversion)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^ error: useless conversion to the same type: `T` - --> $DIR/useless_conversion_try.rs:5:5 + --> $DIR/useless_conversion_try.rs:6:5 | LL | val.try_into().unwrap() | ^^^^^^^^^^^^^^ @@ -20,7 +20,7 @@ LL | val.try_into().unwrap() = help: consider removing `.try_into()` error: useless conversion to the same type: `std::string::String` - --> $DIR/useless_conversion_try.rs:27:21 + --> $DIR/useless_conversion_try.rs:28:21 | LL | let _: String = "foo".to_string().try_into().unwrap(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -28,7 +28,7 @@ LL | let _: String = "foo".to_string().try_into().unwrap(); = help: consider removing `.try_into()` error: useless conversion to the same type: `std::string::String` - --> $DIR/useless_conversion_try.rs:28:21 + --> $DIR/useless_conversion_try.rs:29:21 | LL | let _: String = TryFrom::try_from("foo".to_string()).unwrap(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -36,7 +36,7 @@ LL | let _: String = TryFrom::try_from("foo".to_string()).unwrap(); = help: consider removing `TryFrom::try_from()` error: useless conversion to the same type: `std::string::String` - --> $DIR/useless_conversion_try.rs:29:13 + --> $DIR/useless_conversion_try.rs:30:13 | LL | let _ = String::try_from("foo".to_string()).unwrap(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -44,7 +44,7 @@ LL | let _ = String::try_from("foo".to_string()).unwrap(); = help: consider removing `String::try_from()` error: useless conversion to the same type: `std::string::String` - --> $DIR/useless_conversion_try.rs:30:13 + --> $DIR/useless_conversion_try.rs:31:13 | LL | let _ = String::try_from(format!("A: {:04}", 123)).unwrap(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -52,7 +52,7 @@ LL | let _ = String::try_from(format!("A: {:04}", 123)).unwrap(); = help: consider removing `String::try_from()` error: useless conversion to the same type: `std::string::String` - --> $DIR/useless_conversion_try.rs:31:21 + --> $DIR/useless_conversion_try.rs:32:21 | LL | let _: String = format!("Hello {}", "world").try_into().unwrap(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -60,7 +60,7 @@ LL | let _: String = format!("Hello {}", "world").try_into().unwrap(); = help: consider removing `.try_into()` error: useless conversion to the same type: `std::string::String` - --> $DIR/useless_conversion_try.rs:32:21 + --> $DIR/useless_conversion_try.rs:33:21 | LL | let _: String = String::new().try_into().unwrap(); | ^^^^^^^^^^^^^^^^^^^^^^^^ @@ -68,7 +68,7 @@ LL | let _: String = String::new().try_into().unwrap(); = help: consider removing `.try_into()` error: useless conversion to the same type: `std::string::String` - --> $DIR/useless_conversion_try.rs:33:27 + --> $DIR/useless_conversion_try.rs:34:27 | LL | let _: String = match String::from("_").try_into() { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ From b303e2053cc0629c58419b80d9655027f06f255e Mon Sep 17 00:00:00 2001 From: Centri3 <114838443+Centri3@users.noreply.github.com> Date: Fri, 9 Jun 2023 14:27:34 -0500 Subject: [PATCH 126/310] allow disabling module inception on private modules allow disabling module inception on private modules --- book/src/lint_configuration.md | 10 ++++++ clippy_lints/src/enum_variants.rs | 31 +++++++++-------- clippy_lints/src/lib.rs | 2 ++ clippy_lints/src/utils/conf.rs | 4 +++ tests/ui-toml/module_inception/clippy.toml | 1 + .../module_inception/module_inception.rs | 34 +++++++++++++++++++ .../module_inception/module_inception.stderr | 20 +++++++++++ .../toml_unknown_key/conf_unknown_key.stderr | 2 ++ tests/ui/module_inception.rs | 12 +++++++ tests/ui/module_inception.stderr | 22 ++++++++++-- 10 files changed, 121 insertions(+), 17 deletions(-) create mode 100644 tests/ui-toml/module_inception/clippy.toml create mode 100644 tests/ui-toml/module_inception/module_inception.rs create mode 100644 tests/ui-toml/module_inception/module_inception.stderr diff --git a/book/src/lint_configuration.md b/book/src/lint_configuration.md index 4c888b63793..2777119984e 100644 --- a/book/src/lint_configuration.md +++ b/book/src/lint_configuration.md @@ -643,3 +643,13 @@ The byte size a `T` in `Box` can have, below which it triggers the `clippy::u * [`unnecessary_box_returns`](https://rust-lang.github.io/rust-clippy/master/index.html#unnecessary_box_returns) +## `allow-private-module-inception` +Whether to allow module inception if it's not public. + +**Default Value:** `false` (`bool`) + +--- +**Affected lints:** +* [`module_inception`](https://rust-lang.github.io/rust-clippy/master/index.html#module_inception) + + diff --git a/clippy_lints/src/enum_variants.rs b/clippy_lints/src/enum_variants.rs index faac6340419..d4df6f7aa2d 100644 --- a/clippy_lints/src/enum_variants.rs +++ b/clippy_lints/src/enum_variants.rs @@ -3,7 +3,7 @@ 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}; +use rustc_hir::{EnumDef, Item, ItemKind, OwnerId, Variant}; use rustc_lint::{LateContext, LateLintPass}; use rustc_session::{declare_tool_lint, impl_lint_pass}; use rustc_span::source_map::Span; @@ -105,18 +105,20 @@ declare_clippy_lint! { } pub struct EnumVariantNames { - modules: Vec<(Symbol, String)>, + modules: Vec<(Symbol, String, OwnerId)>, threshold: u64, avoid_breaking_exported_api: bool, + allow_private_module_inception: bool, } impl EnumVariantNames { #[must_use] - pub fn new(threshold: u64, avoid_breaking_exported_api: bool) -> Self { + pub fn new(threshold: u64, avoid_breaking_exported_api: bool, allow_private_module_inception: bool) -> Self { Self { modules: Vec::new(), threshold, avoid_breaking_exported_api, + allow_private_module_inception, } } } @@ -252,18 +254,19 @@ impl LateLintPass<'_> for EnumVariantNames { let item_name = item.ident.name.as_str(); let item_camel = to_camel_case(item_name); if !item.span.from_expansion() && is_present_in_source(cx, item.span) { - if let Some((mod_name, mod_camel)) = self.modules.last() { + if let [.., (mod_name, mod_camel, owner_id)] = &*self.modules { // constants don't have surrounding modules if !mod_camel.is_empty() { - if mod_name == &item.ident.name { - if let ItemKind::Mod(..) = item.kind { - span_lint( - cx, - MODULE_INCEPTION, - item.span, - "module has the same name as its containing module", - ); - } + if mod_name == &item.ident.name + && let ItemKind::Mod(..) = item.kind + && (!self.allow_private_module_inception || cx.tcx.visibility(owner_id.def_id).is_public()) + { + span_lint( + cx, + MODULE_INCEPTION, + item.span, + "module has the same name as its containing module", + ); } // The `module_name_repetitions` lint should only trigger if the item has the module in its // name. Having the same name is accepted. @@ -302,6 +305,6 @@ impl LateLintPass<'_> for EnumVariantNames { check_variant(cx, self.threshold, def, item_name, item.span); } } - self.modules.push((item.ident.name, item_camel)); + self.modules.push((item.ident.name, item_camel, item.owner_id)); } } diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index 43ab8a96d86..3517d2f64f0 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -813,10 +813,12 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: )) }); let enum_variant_name_threshold = conf.enum_variant_name_threshold; + let allow_private_module_inception = conf.allow_private_module_inception; store.register_late_pass(move |_| { Box::new(enum_variants::EnumVariantNames::new( enum_variant_name_threshold, avoid_breaking_exported_api, + allow_private_module_inception, )) }); store.register_early_pass(|| Box::new(tabs_in_doc_comments::TabsInDocComments)); diff --git a/clippy_lints/src/utils/conf.rs b/clippy_lints/src/utils/conf.rs index 35f40830681..3952ec7389f 100644 --- a/clippy_lints/src/utils/conf.rs +++ b/clippy_lints/src/utils/conf.rs @@ -514,6 +514,10 @@ define_Conf! { /// /// The byte size a `T` in `Box` can have, below which it triggers the `clippy::unnecessary_box` lint (unnecessary_box_size: u64 = 128), + /// Lint: MODULE_INCEPTION. + /// + /// Whether to allow module inception if it's not public. + (allow_private_module_inception: bool = false), } /// Search for the configuration file. diff --git a/tests/ui-toml/module_inception/clippy.toml b/tests/ui-toml/module_inception/clippy.toml new file mode 100644 index 00000000000..787620d865c --- /dev/null +++ b/tests/ui-toml/module_inception/clippy.toml @@ -0,0 +1 @@ +allow-private-module-inception = true diff --git a/tests/ui-toml/module_inception/module_inception.rs b/tests/ui-toml/module_inception/module_inception.rs new file mode 100644 index 00000000000..cd495c884a4 --- /dev/null +++ b/tests/ui-toml/module_inception/module_inception.rs @@ -0,0 +1,34 @@ +#![warn(clippy::module_inception)] + +// Lint +pub mod foo2 { + pub mod bar2 { + pub mod bar2 { + pub mod foo2 {} + } + pub mod foo2 {} + } + pub mod foo2 { + pub mod bar2 {} + } +} + +// Don't lint +mod foo { + pub mod bar { + pub mod foo { + pub mod bar {} + } + } + pub mod foo { + pub mod bar {} + } +} + +// No warning. See . +pub mod bar { + #[allow(clippy::module_inception)] + pub mod bar {} +} + +fn main() {} diff --git a/tests/ui-toml/module_inception/module_inception.stderr b/tests/ui-toml/module_inception/module_inception.stderr new file mode 100644 index 00000000000..a5a09c322e1 --- /dev/null +++ b/tests/ui-toml/module_inception/module_inception.stderr @@ -0,0 +1,20 @@ +error: module has the same name as its containing module + --> $DIR/module_inception.rs:6:9 + | +LL | / pub mod bar2 { +LL | | pub mod foo2 {} +LL | | } + | |_________^ + | + = note: `-D clippy::module-inception` implied by `-D warnings` + +error: module has the same name as its containing module + --> $DIR/module_inception.rs:11:5 + | +LL | / pub mod foo2 { +LL | | pub mod bar2 {} +LL | | } + | |_____^ + +error: aborting due to 2 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 b6038f031f3..22ea45d0622 100644 --- a/tests/ui-toml/toml_unknown_key/conf_unknown_key.stderr +++ b/tests/ui-toml/toml_unknown_key/conf_unknown_key.stderr @@ -3,6 +3,7 @@ error: error reading Clippy's configuration file: unknown field `foobar`, expect allow-expect-in-tests allow-mixed-uninlined-format-args allow-print-in-tests + allow-private-module-inception allow-unwrap-in-tests allowed-scripts arithmetic-side-effects-allowed @@ -64,6 +65,7 @@ error: error reading Clippy's configuration file: unknown field `barfoo`, expect allow-expect-in-tests allow-mixed-uninlined-format-args allow-print-in-tests + allow-private-module-inception allow-unwrap-in-tests allowed-scripts arithmetic-side-effects-allowed diff --git a/tests/ui/module_inception.rs b/tests/ui/module_inception.rs index a23aba9164a..802c3ec39b6 100644 --- a/tests/ui/module_inception.rs +++ b/tests/ui/module_inception.rs @@ -1,5 +1,17 @@ #![warn(clippy::module_inception)] +pub mod foo2 { + pub mod bar2 { + pub mod bar2 { + pub mod foo2 {} + } + pub mod foo2 {} + } + pub mod foo2 { + pub mod bar2 {} + } +} + mod foo { mod bar { mod bar { diff --git a/tests/ui/module_inception.stderr b/tests/ui/module_inception.stderr index 77564dce9eb..ebb8e296f46 100644 --- a/tests/ui/module_inception.stderr +++ b/tests/ui/module_inception.stderr @@ -1,8 +1,8 @@ error: module has the same name as its containing module --> $DIR/module_inception.rs:5:9 | -LL | / mod bar { -LL | | mod foo {} +LL | / pub mod bar2 { +LL | | pub mod foo2 {} LL | | } | |_________^ | @@ -11,10 +11,26 @@ LL | | } error: module has the same name as its containing module --> $DIR/module_inception.rs:10:5 | +LL | / pub mod foo2 { +LL | | pub mod bar2 {} +LL | | } + | |_____^ + +error: module has the same name as its containing module + --> $DIR/module_inception.rs:17:9 + | +LL | / mod bar { +LL | | mod foo {} +LL | | } + | |_________^ + +error: module has the same name as its containing module + --> $DIR/module_inception.rs:22:5 + | LL | / mod foo { LL | | mod bar {} LL | | } | |_____^ -error: aborting due to 2 previous errors +error: aborting due to 4 previous errors From 7ba904245dc76091c8c49880de82273b66a6bb1c Mon Sep 17 00:00:00 2001 From: Centri3 <114838443+Centri3@users.noreply.github.com> Date: Sat, 10 Jun 2023 06:54:00 -0500 Subject: [PATCH 127/310] make cargo test pass --- lintcheck/lintcheck_crates.toml | 35 ++++++++- .../excessive_nesting/excessive_nesting.rs | 1 + .../excessive_nesting.stderr | 74 +++++++++---------- tests/ui/needless_collect_indirect.stderr | 32 ++++---- 4 files changed, 87 insertions(+), 55 deletions(-) diff --git a/lintcheck/lintcheck_crates.toml b/lintcheck/lintcheck_crates.toml index 066b2657d03..52f7fee47b6 100644 --- a/lintcheck/lintcheck_crates.toml +++ b/lintcheck/lintcheck_crates.toml @@ -1,7 +1,38 @@ [crates] # some of these are from cargotest -bevy = {name = "bevy", versions = ['0.10.1']} -deno = {name = "deno", versions = ['1.34.2']} +cargo = {name = "cargo", versions = ['0.64.0']} +iron = {name = "iron", versions = ['0.6.1']} +ripgrep = {name = "ripgrep", versions = ['12.1.1']} +xsv = {name = "xsv", versions = ['0.13.0']} +# commented out because of 173K clippy::match_same_arms msgs in language_type.rs +#tokei = { name = "tokei", versions = ['12.0.4']} +rayon = {name = "rayon", versions = ['1.5.0']} +serde = {name = "serde", versions = ['1.0.118']} +# top 10 crates.io dls +bitflags = {name = "bitflags", versions = ['1.2.1']} +# crash = {name = "clippy_crash", path = "/tmp/clippy_crash"} +libc = {name = "libc", versions = ['0.2.81']} +log = {name = "log", versions = ['0.4.11']} +proc-macro2 = {name = "proc-macro2", versions = ['1.0.24']} +quote = {name = "quote", versions = ['1.0.7']} +rand = {name = "rand", versions = ['0.7.3']} +rand_core = {name = "rand_core", versions = ['0.6.0']} +regex = {name = "regex", versions = ['1.3.2']} +syn = {name = "syn", versions = ['1.0.54']} +unicode-xid = {name = "unicode-xid", versions = ['0.2.1']} +# some more of dtolnays crates +anyhow = {name = "anyhow", versions = ['1.0.38']} +async-trait = {name = "async-trait", versions = ['0.1.42']} +cxx = {name = "cxx", versions = ['1.0.32']} +ryu = {name = "ryu", versions = ['1.0.5']} +serde_yaml = {name = "serde_yaml", versions = ['0.8.17']} +thiserror = {name = "thiserror", versions = ['1.0.24']} +# some embark crates, there are other interesting crates but +# unfortunately adding them increases lintcheck runtime drastically +cfg-expr = {name = "cfg-expr", versions = ['0.7.1']} +puffin = {name = "puffin", git_url = "https://github.com/EmbarkStudios/puffin", git_hash = "02dd4a3"} +rpmalloc = {name = "rpmalloc", versions = ['0.2.0']} +tame-oidc = {name = "tame-oidc", versions = ['0.1.0']} [recursive] ignore = [ diff --git a/tests/ui-toml/excessive_nesting/excessive_nesting.rs b/tests/ui-toml/excessive_nesting/excessive_nesting.rs index d771cb9b55e..25f0d0d6230 100644 --- a/tests/ui-toml/excessive_nesting/excessive_nesting.rs +++ b/tests/ui-toml/excessive_nesting/excessive_nesting.rs @@ -7,6 +7,7 @@ #![allow(clippy::no_effect)] #![allow(clippy::unnecessary_operation)] #![allow(clippy::never_loop)] +#![allow(clippy::needless_if)] #![warn(clippy::excessive_nesting)] #![allow(clippy::collapsible_if)] diff --git a/tests/ui-toml/excessive_nesting/excessive_nesting.stderr b/tests/ui-toml/excessive_nesting/excessive_nesting.stderr index a9fb159ef2a..1a7311b33e8 100644 --- a/tests/ui-toml/excessive_nesting/excessive_nesting.stderr +++ b/tests/ui-toml/excessive_nesting/excessive_nesting.stderr @@ -1,5 +1,5 @@ error: this block is too nested - --> $DIR/excessive_nesting.rs:20:25 + --> $DIR/excessive_nesting.rs:21:25 | LL | let w = { 3 }; | ^^^^^ @@ -8,7 +8,7 @@ LL | let w = { 3 }; = note: `-D clippy::excessive-nesting` implied by `-D warnings` error: this block is too nested - --> $DIR/excessive_nesting.rs:66:17 + --> $DIR/excessive_nesting.rs:67:17 | LL | / impl C { LL | | pub fn c() {} @@ -18,7 +18,7 @@ LL | | } = help: try refactoring your code to minimize nesting error: this block is too nested - --> $DIR/excessive_nesting.rs:80:25 + --> $DIR/excessive_nesting.rs:81:25 | LL | let x = { 1 }; // not a warning, but cc is | ^^^^^ @@ -26,7 +26,7 @@ LL | let x = { 1 }; // not a warning, but cc is = help: try refactoring your code to minimize nesting error: this block is too nested - --> $DIR/excessive_nesting.rs:97:17 + --> $DIR/excessive_nesting.rs:98:17 | LL | / pub mod e { LL | | pub mod f {} @@ -36,7 +36,7 @@ LL | | } // not here = help: try refactoring your code to minimize nesting error: this block is too nested - --> $DIR/excessive_nesting.rs:110:18 + --> $DIR/excessive_nesting.rs:111:18 | LL | a_but_not({{{{{{{{0}}}}}}}}); | ^^^^^^^^^^^ @@ -44,7 +44,7 @@ LL | a_but_not({{{{{{{{0}}}}}}}}); = help: try refactoring your code to minimize nesting error: this block is too nested - --> $DIR/excessive_nesting.rs:111:12 + --> $DIR/excessive_nesting.rs:112:12 | LL | a.a({{{{{{{{{0}}}}}}}}}); | ^^^^^^^^^^^^^ @@ -52,7 +52,7 @@ LL | a.a({{{{{{{{{0}}}}}}}}}); = help: try refactoring your code to minimize nesting error: this block is too nested - --> $DIR/excessive_nesting.rs:112:12 + --> $DIR/excessive_nesting.rs:113:12 | LL | (0, {{{{{{{1}}}}}}}); | ^^^^^^^^^ @@ -60,7 +60,7 @@ LL | (0, {{{{{{{1}}}}}}}); = help: try refactoring your code to minimize nesting error: this block is too nested - --> $DIR/excessive_nesting.rs:117:25 + --> $DIR/excessive_nesting.rs:118:25 | LL | if true { | _________________________^ @@ -73,7 +73,7 @@ LL | | } = help: try refactoring your code to minimize nesting error: this block is too nested - --> $DIR/excessive_nesting.rs:129:29 + --> $DIR/excessive_nesting.rs:130:29 | LL | let z = (|| { | _____________________________^ @@ -85,7 +85,7 @@ LL | | })(); = help: try refactoring your code to minimize nesting error: this block is too nested - --> $DIR/excessive_nesting.rs:148:13 + --> $DIR/excessive_nesting.rs:149:13 | LL | y += {{{{{5}}}}}; | ^^^^^ @@ -93,7 +93,7 @@ LL | y += {{{{{5}}}}}; = help: try refactoring your code to minimize nesting error: this block is too nested - --> $DIR/excessive_nesting.rs:149:20 + --> $DIR/excessive_nesting.rs:150:20 | LL | let z = y + {{{{{{{{{5}}}}}}}}}; | ^^^^^^^^^^^^^ @@ -101,7 +101,7 @@ LL | let z = y + {{{{{{{{{5}}}}}}}}}; = help: try refactoring your code to minimize nesting error: this block is too nested - --> $DIR/excessive_nesting.rs:150:12 + --> $DIR/excessive_nesting.rs:151:12 | LL | [0, {{{{{{{{{{0}}}}}}}}}}]; | ^^^^^^^^^^^^^^^ @@ -109,7 +109,7 @@ LL | [0, {{{{{{{{{{0}}}}}}}}}}]; = help: try refactoring your code to minimize nesting error: this block is too nested - --> $DIR/excessive_nesting.rs:151:25 + --> $DIR/excessive_nesting.rs:152:25 | LL | let mut xx = [0; {{{{{{{{100}}}}}}}}]; | ^^^^^^^^^^^^^ @@ -117,7 +117,7 @@ LL | let mut xx = [0; {{{{{{{{100}}}}}}}}]; = help: try refactoring your code to minimize nesting error: this block is too nested - --> $DIR/excessive_nesting.rs:152:11 + --> $DIR/excessive_nesting.rs:153:11 | LL | xx[{{{{{{{{{{{{{{{{{{{{{{{{3}}}}}}}}}}}}}}}}}}}}}}}}]; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -125,7 +125,7 @@ LL | xx[{{{{{{{{{{{{{{{{{{{{{{{{3}}}}}}}}}}}}}}}}}}}}}}}}]; = help: try refactoring your code to minimize nesting error: this block is too nested - --> $DIR/excessive_nesting.rs:153:13 + --> $DIR/excessive_nesting.rs:154:13 | LL | &mut {{{{{{{{{{y}}}}}}}}}}; | ^^^^^^^^^^^^^^^ @@ -133,7 +133,7 @@ LL | &mut {{{{{{{{{{y}}}}}}}}}}; = help: try refactoring your code to minimize nesting error: this block is too nested - --> $DIR/excessive_nesting.rs:155:17 + --> $DIR/excessive_nesting.rs:156:17 | LL | for i in {{{{xx}}}} {{{{{{{{}}}}}}}} | ^^^^ @@ -141,7 +141,7 @@ LL | for i in {{{{xx}}}} {{{{{{{{}}}}}}}} = help: try refactoring your code to minimize nesting error: this block is too nested - --> $DIR/excessive_nesting.rs:155:28 + --> $DIR/excessive_nesting.rs:156:28 | LL | for i in {{{{xx}}}} {{{{{{{{}}}}}}}} | ^^^^^^^^^^ @@ -149,7 +149,7 @@ LL | for i in {{{{xx}}}} {{{{{{{{}}}}}}}} = help: try refactoring your code to minimize nesting error: this block is too nested - --> $DIR/excessive_nesting.rs:157:28 + --> $DIR/excessive_nesting.rs:158:28 | LL | while let Some(i) = {{{{{{Some(1)}}}}}} {{{{{{{}}}}}}} | ^^^^^^^^^^^^^ @@ -157,7 +157,7 @@ LL | while let Some(i) = {{{{{{Some(1)}}}}}} {{{{{{{}}}}}}} = help: try refactoring your code to minimize nesting error: this block is too nested - --> $DIR/excessive_nesting.rs:157:48 + --> $DIR/excessive_nesting.rs:158:48 | LL | while let Some(i) = {{{{{{Some(1)}}}}}} {{{{{{{}}}}}}} | ^^^^^^^^ @@ -165,7 +165,7 @@ LL | while let Some(i) = {{{{{{Some(1)}}}}}} {{{{{{{}}}}}}} = help: try refactoring your code to minimize nesting error: this block is too nested - --> $DIR/excessive_nesting.rs:159:14 + --> $DIR/excessive_nesting.rs:160:14 | LL | while {{{{{{{{true}}}}}}}} {{{{{{{{{}}}}}}}}} | ^^^^^^^^^^^^^^ @@ -173,7 +173,7 @@ LL | while {{{{{{{{true}}}}}}}} {{{{{{{{{}}}}}}}}} = help: try refactoring your code to minimize nesting error: this block is too nested - --> $DIR/excessive_nesting.rs:159:35 + --> $DIR/excessive_nesting.rs:160:35 | LL | while {{{{{{{{true}}}}}}}} {{{{{{{{{}}}}}}}}} | ^^^^^^^^^^^^ @@ -181,7 +181,7 @@ LL | while {{{{{{{{true}}}}}}}} {{{{{{{{{}}}}}}}}} = help: try refactoring your code to minimize nesting error: this block is too nested - --> $DIR/excessive_nesting.rs:161:23 + --> $DIR/excessive_nesting.rs:162:23 | LL | let d = D { d: {{{{{{{{{{{{{{{{{{{{{{{3}}}}}}}}}}}}}}}}}}}}}}} }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -189,7 +189,7 @@ LL | let d = D { d: {{{{{{{{{{{{{{{{{{{{{{{3}}}}}}}}}}}}}}}}}}}}}}} }; = help: try refactoring your code to minimize nesting error: this block is too nested - --> $DIR/excessive_nesting.rs:163:8 + --> $DIR/excessive_nesting.rs:164:8 | LL | {{{{1;}}}}..{{{{{{3}}}}}}; | ^^^^ @@ -197,7 +197,7 @@ LL | {{{{1;}}}}..{{{{{{3}}}}}}; = help: try refactoring your code to minimize nesting error: this block is too nested - --> $DIR/excessive_nesting.rs:163:20 + --> $DIR/excessive_nesting.rs:164:20 | LL | {{{{1;}}}}..{{{{{{3}}}}}}; | ^^^^^^^ @@ -205,7 +205,7 @@ LL | {{{{1;}}}}..{{{{{{3}}}}}}; = help: try refactoring your code to minimize nesting error: this block is too nested - --> $DIR/excessive_nesting.rs:164:8 + --> $DIR/excessive_nesting.rs:165:8 | LL | {{{{1;}}}}..={{{{{{{{{{{{{{{{{{{{{{{{{{6}}}}}}}}}}}}}}}}}}}}}}}}}}; | ^^^^ @@ -213,7 +213,7 @@ LL | {{{{1;}}}}..={{{{{{{{{{{{{{{{{{{{{{{{{{6}}}}}}}}}}}}}}}}}}}}}}}}}}; = help: try refactoring your code to minimize nesting error: this block is too nested - --> $DIR/excessive_nesting.rs:164:21 + --> $DIR/excessive_nesting.rs:165:21 | LL | {{{{1;}}}}..={{{{{{{{{{{{{{{{{{{{{{{{{{6}}}}}}}}}}}}}}}}}}}}}}}}}}; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -221,7 +221,7 @@ LL | {{{{1;}}}}..={{{{{{{{{{{{{{{{{{{{{{{{{{6}}}}}}}}}}}}}}}}}}}}}}}}}}; = help: try refactoring your code to minimize nesting error: this block is too nested - --> $DIR/excessive_nesting.rs:165:10 + --> $DIR/excessive_nesting.rs:166:10 | LL | ..{{{{{{{5}}}}}}}; | ^^^^^^^^^ @@ -229,7 +229,7 @@ LL | ..{{{{{{{5}}}}}}}; = help: try refactoring your code to minimize nesting error: this block is too nested - --> $DIR/excessive_nesting.rs:166:11 + --> $DIR/excessive_nesting.rs:167:11 | LL | ..={{{{{3}}}}}; | ^^^^^ @@ -237,7 +237,7 @@ LL | ..={{{{{3}}}}}; = help: try refactoring your code to minimize nesting error: this block is too nested - --> $DIR/excessive_nesting.rs:167:8 + --> $DIR/excessive_nesting.rs:168:8 | LL | {{{{{1;}}}}}..; | ^^^^^^ @@ -245,7 +245,7 @@ LL | {{{{{1;}}}}}..; = help: try refactoring your code to minimize nesting error: this block is too nested - --> $DIR/excessive_nesting.rs:169:20 + --> $DIR/excessive_nesting.rs:170:20 | LL | loop { break {{{{1}}}} }; | ^^^^^ @@ -253,7 +253,7 @@ LL | loop { break {{{{1}}}} }; = help: try refactoring your code to minimize nesting error: this block is too nested - --> $DIR/excessive_nesting.rs:170:13 + --> $DIR/excessive_nesting.rs:171:13 | LL | loop {{{{{{}}}}}} | ^^^^^^ @@ -261,7 +261,7 @@ LL | loop {{{{{{}}}}}} = help: try refactoring your code to minimize nesting error: this block is too nested - --> $DIR/excessive_nesting.rs:172:14 + --> $DIR/excessive_nesting.rs:173:14 | LL | match {{{{{{true}}}}}} { | ^^^^^^^^^^ @@ -269,7 +269,7 @@ LL | match {{{{{{true}}}}}} { = help: try refactoring your code to minimize nesting error: this block is too nested - --> $DIR/excessive_nesting.rs:173:20 + --> $DIR/excessive_nesting.rs:174:20 | LL | true => {{{{}}}}, | ^^ @@ -277,7 +277,7 @@ LL | true => {{{{}}}}, = help: try refactoring your code to minimize nesting error: this block is too nested - --> $DIR/excessive_nesting.rs:174:21 + --> $DIR/excessive_nesting.rs:175:21 | LL | false => {{{{}}}}, | ^^ @@ -285,7 +285,7 @@ LL | false => {{{{}}}}, = help: try refactoring your code to minimize nesting error: this block is too nested - --> $DIR/excessive_nesting.rs:180:17 + --> $DIR/excessive_nesting.rs:181:17 | LL | / { LL | | println!("warning! :)"); @@ -295,7 +295,7 @@ LL | | } = help: try refactoring your code to minimize nesting error: this block is too nested - --> $DIR/excessive_nesting.rs:189:28 + --> $DIR/excessive_nesting.rs:190:28 | LL | async fn c() -> u32 {{{{{{{0}}}}}}} | ^^^^^^^^^ @@ -303,7 +303,7 @@ LL | async fn c() -> u32 {{{{{{{0}}}}}}} = help: try refactoring your code to minimize nesting error: this block is too nested - --> $DIR/excessive_nesting.rs:195:8 + --> $DIR/excessive_nesting.rs:196:8 | LL | {{{{b().await}}}}; | ^^^^^^^^^^^ diff --git a/tests/ui/needless_collect_indirect.stderr b/tests/ui/needless_collect_indirect.stderr index 790d725907f..8f84c559688 100644 --- a/tests/ui/needless_collect_indirect.stderr +++ b/tests/ui/needless_collect_indirect.stderr @@ -1,5 +1,5 @@ error: avoid using `collect()` when not needed - --> $DIR/needless_collect_indirect.rs:8:39 + --> $DIR/needless_collect_indirect.rs:9:39 | LL | let indirect_iter = sample.iter().collect::>(); | ^^^^^^^ @@ -14,7 +14,7 @@ LL ~ sample.iter().map(|x| (x, x + 1)).collect::>(); | error: avoid using `collect()` when not needed - --> $DIR/needless_collect_indirect.rs:10:38 + --> $DIR/needless_collect_indirect.rs:11:38 | LL | let indirect_len = sample.iter().collect::>(); | ^^^^^^^ @@ -28,7 +28,7 @@ LL ~ sample.iter().count(); | error: avoid using `collect()` when not needed - --> $DIR/needless_collect_indirect.rs:12:40 + --> $DIR/needless_collect_indirect.rs:13:40 | LL | let indirect_empty = sample.iter().collect::>(); | ^^^^^^^ @@ -42,7 +42,7 @@ LL ~ sample.iter().next().is_none(); | error: avoid using `collect()` when not needed - --> $DIR/needless_collect_indirect.rs:14:43 + --> $DIR/needless_collect_indirect.rs:15:43 | LL | let indirect_contains = sample.iter().collect::>(); | ^^^^^^^ @@ -56,7 +56,7 @@ LL ~ sample.iter().any(|x| x == &5); | error: avoid using `collect()` when not needed - --> $DIR/needless_collect_indirect.rs:26:48 + --> $DIR/needless_collect_indirect.rs:27:48 | LL | let non_copy_contains = sample.into_iter().collect::>(); | ^^^^^^^ @@ -70,7 +70,7 @@ LL ~ sample.into_iter().any(|x| x == a); | error: avoid using `collect()` when not needed - --> $DIR/needless_collect_indirect.rs:55:51 + --> $DIR/needless_collect_indirect.rs:56:51 | LL | let buffer: Vec<&str> = string.split('/').collect(); | ^^^^^^^ @@ -84,7 +84,7 @@ LL ~ string.split('/').count() | error: avoid using `collect()` when not needed - --> $DIR/needless_collect_indirect.rs:60:55 + --> $DIR/needless_collect_indirect.rs:61:55 | LL | let indirect_len: VecDeque<_> = sample.iter().collect(); | ^^^^^^^ @@ -98,7 +98,7 @@ LL ~ sample.iter().count() | error: avoid using `collect()` when not needed - --> $DIR/needless_collect_indirect.rs:65:57 + --> $DIR/needless_collect_indirect.rs:66:57 | LL | let indirect_len: LinkedList<_> = sample.iter().collect(); | ^^^^^^^ @@ -112,7 +112,7 @@ LL ~ sample.iter().count() | error: avoid using `collect()` when not needed - --> $DIR/needless_collect_indirect.rs:70:57 + --> $DIR/needless_collect_indirect.rs:71:57 | LL | let indirect_len: BinaryHeap<_> = sample.iter().collect(); | ^^^^^^^ @@ -126,7 +126,7 @@ LL ~ sample.iter().count() | error: avoid using `collect()` when not needed - --> $DIR/needless_collect_indirect.rs:130:59 + --> $DIR/needless_collect_indirect.rs:131:59 | LL | let y: Vec = vec.iter().map(|k| k * k).collect(); | ^^^^^^^ @@ -143,7 +143,7 @@ LL ~ vec.iter().map(|k| k * k).any(|x| x == i); | error: avoid using `collect()` when not needed - --> $DIR/needless_collect_indirect.rs:155:59 + --> $DIR/needless_collect_indirect.rs:156:59 | LL | let y: Vec = vec.iter().map(|k| k * k).collect(); | ^^^^^^^ @@ -160,7 +160,7 @@ LL ~ vec.iter().map(|k| k * k).any(|x| x == n); | error: avoid using `collect()` when not needed - --> $DIR/needless_collect_indirect.rs:184:63 + --> $DIR/needless_collect_indirect.rs:185:63 | LL | let y: Vec = vec.iter().map(|k| k * k).collect(); | ^^^^^^^ @@ -177,7 +177,7 @@ LL ~ vec.iter().map(|k| k * k).any(|x| x == n); | error: avoid using `collect()` when not needed - --> $DIR/needless_collect_indirect.rs:220:59 + --> $DIR/needless_collect_indirect.rs:221:59 | LL | let y: Vec = vec.iter().map(|k| k * k).collect(); | ^^^^^^^ @@ -195,7 +195,7 @@ LL ~ vec.iter().map(|k| k * k).any(|x| x == n); | error: avoid using `collect()` when not needed - --> $DIR/needless_collect_indirect.rs:245:26 + --> $DIR/needless_collect_indirect.rs:246:26 | LL | let w = v.iter().collect::>(); | ^^^^^^^ @@ -211,7 +211,7 @@ LL ~ for _ in 0..v.iter().count() { | error: avoid using `collect()` when not needed - --> $DIR/needless_collect_indirect.rs:267:30 + --> $DIR/needless_collect_indirect.rs:268:30 | LL | let mut w = v.iter().collect::>(); | ^^^^^^^ @@ -227,7 +227,7 @@ LL ~ while 1 == v.iter().count() { | error: avoid using `collect()` when not needed - --> $DIR/needless_collect_indirect.rs:289:30 + --> $DIR/needless_collect_indirect.rs:290:30 | LL | let mut w = v.iter().collect::>(); | ^^^^^^^ From b2bdc37a558e4686e9e1c4eb5d967bdc69485826 Mon Sep 17 00:00:00 2001 From: Centri3 <114838443+Centri3@users.noreply.github.com> Date: Sun, 11 Jun 2023 04:55:02 -0500 Subject: [PATCH 128/310] add description add description --- clippy_lints/src/needless_if.rs | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/clippy_lints/src/needless_if.rs b/clippy_lints/src/needless_if.rs index 1568c3533a0..8e27d3a4009 100644 --- a/clippy_lints/src/needless_if.rs +++ b/clippy_lints/src/needless_if.rs @@ -7,16 +7,24 @@ use rustc_session::{declare_lint_pass, declare_tool_lint}; declare_clippy_lint! { /// ### What it does + /// Checks for empty `if` statements with no else branch. /// /// ### Why is this bad? + /// It can be entirely omitted, and often the condition too. + /// + /// ### Known issues + /// This will only suggest to remove the `if` statement, not the condition. Other lints such as + /// `no_effect` will take care of removing the condition if it's unnecessary. /// /// ### Example - /// ```rust - /// // example code where clippy issues a warning + /// ```rust,ignore + /// if really_expensive_condition(&i) {} + /// if really_expensive_condition_with_side_effects(&mut i) {} /// ``` /// Use instead: - /// ```rust - /// // example code which does not raise clippy warning + /// ```rust,ignore + /// // + /// really_expensive_condition_with_side_effects(&mut i); /// ``` #[clippy::version = "1.72.0"] pub NEEDLESS_IF, From 4c7bc1785d137cb2de667be58d50b89d252c9707 Mon Sep 17 00:00:00 2001 From: Centri3 <114838443+Centri3@users.noreply.github.com> Date: Sun, 11 Jun 2023 06:21:31 -0500 Subject: [PATCH 129/310] ignore more type aliases in unnecessary_cast ignore more type aliases in unnecessary_cast --- clippy_lints/src/casts/unnecessary_cast.rs | 29 +++++++++++++- tests/ui/unnecessary_cast.fixed | 12 +++++- tests/ui/unnecessary_cast.rs | 12 +++++- tests/ui/unnecessary_cast.stderr | 46 +++++++++++----------- 4 files changed, 72 insertions(+), 27 deletions(-) diff --git a/clippy_lints/src/casts/unnecessary_cast.rs b/clippy_lints/src/casts/unnecessary_cast.rs index d3d80ff4100..41055c168fc 100644 --- a/clippy_lints/src/casts/unnecessary_cast.rs +++ b/clippy_lints/src/casts/unnecessary_cast.rs @@ -6,13 +6,14 @@ use if_chain::if_chain; use rustc_ast::{LitFloatType, LitIntType, LitKind}; use rustc_errors::Applicability; use rustc_hir::def::Res; -use rustc_hir::{Expr, ExprKind, Lit, QPath, TyKind, UnOp}; +use rustc_hir::{Expr, ExprKind, Lit, Node, Path, QPath, TyKind, UnOp}; use rustc_lint::{LateContext, LintContext}; use rustc_middle::lint::in_external_macro; use rustc_middle::ty::{self, FloatTy, InferTy, Ty}; use super::UNNECESSARY_CAST; +#[expect(clippy::too_many_lines)] pub(super) fn check<'tcx>( cx: &LateContext<'tcx>, expr: &Expr<'tcx>, @@ -58,7 +59,31 @@ pub(super) fn check<'tcx>( } } - // skip non-primitive type cast + // skip cast of local to type alias + if let ExprKind::Cast(inner, ..) = expr.kind + && let ExprKind::Path(qpath) = inner.kind + && let QPath::Resolved(None, Path { res, .. }) = qpath + && let Res::Local(hir_id) = res + && let parent = cx.tcx.hir().get_parent(*hir_id) + && let Node::Local(local) = parent + { + if let Some(ty) = local.ty + && let TyKind::Path(qpath) = ty.kind + && is_ty_alias(&qpath) + { + return false; + } + + if let Some(expr) = local.init + && let ExprKind::Cast(.., cast_to) = expr.kind + && let TyKind::Path(qpath) = cast_to.kind + && is_ty_alias(&qpath) + { + return false; + } + } + + // skip cast to non-primitive type if_chain! { if let ExprKind::Cast(_, cast_to) = expr.kind; if let TyKind::Path(QPath::Resolved(_, path)) = &cast_to.kind; diff --git a/tests/ui/unnecessary_cast.fixed b/tests/ui/unnecessary_cast.fixed index e74476044d9..f56cee3a364 100644 --- a/tests/ui/unnecessary_cast.fixed +++ b/tests/ui/unnecessary_cast.fixed @@ -66,12 +66,22 @@ fn main() { foo!(b, f32); foo!(c, f64); + // do not lint cast from cfg-dependant type + let x = 0 as std::ffi::c_ulong; + let y = x as u64; + let x: std::ffi::c_ulong = 0; + let y = x as u64; + // do not lint cast to cfg-dependant type - 1 as std::os::raw::c_char; + let x = 1 as std::os::raw::c_char; + let y = x as u64; // do not lint cast to alias type 1 as I32Alias; &1 as &I32Alias; + // or from + let x: I32Alias = 1; + let y = x as u64; let i8_ptr: *const i8 = &1; let u8_ptr: *const u8 = &1; diff --git a/tests/ui/unnecessary_cast.rs b/tests/ui/unnecessary_cast.rs index a577fd79899..b4623df6909 100644 --- a/tests/ui/unnecessary_cast.rs +++ b/tests/ui/unnecessary_cast.rs @@ -66,12 +66,22 @@ fn main() { foo!(b, f32); foo!(c, f64); + // do not lint cast from cfg-dependant type + let x = 0 as std::ffi::c_ulong; + let y = x as u64; + let x: std::ffi::c_ulong = 0; + let y = x as u64; + // do not lint cast to cfg-dependant type - 1 as std::os::raw::c_char; + let x = 1 as std::os::raw::c_char; + let y = x as u64; // do not lint cast to alias type 1 as I32Alias; &1 as &I32Alias; + // or from + let x: I32Alias = 1; + let y = x as u64; let i8_ptr: *const i8 = &1; let u8_ptr: *const u8 = &1; diff --git a/tests/ui/unnecessary_cast.stderr b/tests/ui/unnecessary_cast.stderr index 7f748fcf4c2..b52e5c32c8a 100644 --- a/tests/ui/unnecessary_cast.stderr +++ b/tests/ui/unnecessary_cast.stderr @@ -91,139 +91,139 @@ LL | uwu::([1u32].as_ptr()) as *const u32; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `uwu::([1u32].as_ptr())` error: casting integer literal to `f32` is unnecessary - --> $DIR/unnecessary_cast.rs:106:9 + --> $DIR/unnecessary_cast.rs:117:9 | LL | 100 as f32; | ^^^^^^^^^^ help: try: `100_f32` error: casting integer literal to `f64` is unnecessary - --> $DIR/unnecessary_cast.rs:107:9 + --> $DIR/unnecessary_cast.rs:118:9 | LL | 100 as f64; | ^^^^^^^^^^ help: try: `100_f64` error: casting integer literal to `f64` is unnecessary - --> $DIR/unnecessary_cast.rs:108:9 + --> $DIR/unnecessary_cast.rs:119:9 | LL | 100_i32 as f64; | ^^^^^^^^^^^^^^ help: try: `100_f64` error: casting integer literal to `f32` is unnecessary - --> $DIR/unnecessary_cast.rs:109:17 + --> $DIR/unnecessary_cast.rs:120:17 | LL | let _ = -100 as f32; | ^^^^^^^^^^^ help: try: `-100_f32` error: casting integer literal to `f64` is unnecessary - --> $DIR/unnecessary_cast.rs:110:17 + --> $DIR/unnecessary_cast.rs:121:17 | LL | let _ = -100 as f64; | ^^^^^^^^^^^ help: try: `-100_f64` error: casting integer literal to `f64` is unnecessary - --> $DIR/unnecessary_cast.rs:111:17 + --> $DIR/unnecessary_cast.rs:122:17 | LL | let _ = -100_i32 as f64; | ^^^^^^^^^^^^^^^ help: try: `-100_f64` error: casting float literal to `f32` is unnecessary - --> $DIR/unnecessary_cast.rs:112:9 + --> $DIR/unnecessary_cast.rs:123:9 | LL | 100. as f32; | ^^^^^^^^^^^ help: try: `100_f32` error: casting float literal to `f64` is unnecessary - --> $DIR/unnecessary_cast.rs:113:9 + --> $DIR/unnecessary_cast.rs:124:9 | LL | 100. as f64; | ^^^^^^^^^^^ help: try: `100_f64` error: casting integer literal to `u32` is unnecessary - --> $DIR/unnecessary_cast.rs:125:9 + --> $DIR/unnecessary_cast.rs:136:9 | LL | 1 as u32; | ^^^^^^^^ help: try: `1_u32` error: casting integer literal to `i32` is unnecessary - --> $DIR/unnecessary_cast.rs:126:9 + --> $DIR/unnecessary_cast.rs:137:9 | LL | 0x10 as i32; | ^^^^^^^^^^^ help: try: `0x10_i32` error: casting integer literal to `usize` is unnecessary - --> $DIR/unnecessary_cast.rs:127:9 + --> $DIR/unnecessary_cast.rs:138:9 | LL | 0b10 as usize; | ^^^^^^^^^^^^^ help: try: `0b10_usize` error: casting integer literal to `u16` is unnecessary - --> $DIR/unnecessary_cast.rs:128:9 + --> $DIR/unnecessary_cast.rs:139:9 | LL | 0o73 as u16; | ^^^^^^^^^^^ help: try: `0o73_u16` error: casting integer literal to `u32` is unnecessary - --> $DIR/unnecessary_cast.rs:129:9 + --> $DIR/unnecessary_cast.rs:140:9 | LL | 1_000_000_000 as u32; | ^^^^^^^^^^^^^^^^^^^^ help: try: `1_000_000_000_u32` error: casting float literal to `f64` is unnecessary - --> $DIR/unnecessary_cast.rs:131:9 + --> $DIR/unnecessary_cast.rs:142:9 | LL | 1.0 as f64; | ^^^^^^^^^^ help: try: `1.0_f64` error: casting float literal to `f32` is unnecessary - --> $DIR/unnecessary_cast.rs:132:9 + --> $DIR/unnecessary_cast.rs:143:9 | LL | 0.5 as f32; | ^^^^^^^^^^ help: try: `0.5_f32` error: casting integer literal to `i32` is unnecessary - --> $DIR/unnecessary_cast.rs:136:17 + --> $DIR/unnecessary_cast.rs:147:17 | LL | let _ = -1 as i32; | ^^^^^^^^^ help: try: `-1_i32` error: casting float literal to `f32` is unnecessary - --> $DIR/unnecessary_cast.rs:137:17 + --> $DIR/unnecessary_cast.rs:148:17 | LL | let _ = -1.0 as f32; | ^^^^^^^^^^^ help: try: `-1.0_f32` error: casting to the same type is unnecessary (`i32` -> `i32`) - --> $DIR/unnecessary_cast.rs:143:18 + --> $DIR/unnecessary_cast.rs:154:18 | LL | let _ = &(x as i32); | ^^^^^^^^^^ help: try: `{ x }` error: casting integer literal to `i32` is unnecessary - --> $DIR/unnecessary_cast.rs:149:22 + --> $DIR/unnecessary_cast.rs:160:22 | LL | let _: i32 = -(1) as i32; | ^^^^^^^^^^^ help: try: `-1_i32` error: casting integer literal to `i64` is unnecessary - --> $DIR/unnecessary_cast.rs:151:22 + --> $DIR/unnecessary_cast.rs:162:22 | LL | let _: i64 = -(1) as i64; | ^^^^^^^^^^^ help: try: `-1_i64` error: casting float literal to `f64` is unnecessary - --> $DIR/unnecessary_cast.rs:158:22 + --> $DIR/unnecessary_cast.rs:169:22 | LL | let _: f64 = (-8.0 as f64).exp(); | ^^^^^^^^^^^^^ help: try: `(-8.0_f64)` error: casting float literal to `f64` is unnecessary - --> $DIR/unnecessary_cast.rs:160:23 + --> $DIR/unnecessary_cast.rs:171:23 | LL | let _: f64 = -(8.0 as f64).exp(); // should suggest `-8.0_f64.exp()` here not to change code behavior | ^^^^^^^^^^^^ help: try: `8.0_f64` error: casting to the same type is unnecessary (`f32` -> `f32`) - --> $DIR/unnecessary_cast.rs:168:20 + --> $DIR/unnecessary_cast.rs:179:20 | LL | let _num = foo() as f32; | ^^^^^^^^^^^^ help: try: `foo()` From 59bca098f906ecf7bef2f0cab95afbcc2d2e66ca Mon Sep 17 00:00:00 2001 From: Centri3 <114838443+Centri3@users.noreply.github.com> Date: Sun, 11 Jun 2023 06:50:03 -0500 Subject: [PATCH 130/310] don't lint on `if let` don't lint on `if let` --- clippy_lints/src/needless_if.rs | 51 ++++++++++++++++++++++++++------- tests/ui/needless_if.fixed | 30 +++++++++++++++---- tests/ui/needless_if.rs | 29 +++++++++++++++++-- tests/ui/needless_if.stderr | 24 ++++++++++++---- 4 files changed, 109 insertions(+), 25 deletions(-) diff --git a/clippy_lints/src/needless_if.rs b/clippy_lints/src/needless_if.rs index 8e27d3a4009..b118516e09b 100644 --- a/clippy_lints/src/needless_if.rs +++ b/clippy_lints/src/needless_if.rs @@ -1,20 +1,23 @@ use clippy_utils::{diagnostics::span_lint_and_sugg, is_from_proc_macro, source::snippet_with_applicability}; use rustc_errors::Applicability; -use rustc_hir::{Expr, ExprKind, Node}; +use rustc_hir::{ + intravisit::{walk_expr, Visitor}, + Expr, ExprKind, Node, +}; use rustc_lint::{LateContext, LateLintPass, LintContext}; use rustc_middle::lint::in_external_macro; use rustc_session::{declare_lint_pass, declare_tool_lint}; declare_clippy_lint! { /// ### What it does - /// Checks for empty `if` statements with no else branch. + /// Checks for empty `if` branches with no else branch. /// /// ### Why is this bad? /// It can be entirely omitted, and often the condition too. /// /// ### Known issues - /// This will only suggest to remove the `if` statement, not the condition. Other lints such as - /// `no_effect` will take care of removing the condition if it's unnecessary. + /// This will usually only suggest to remove the `if` statement, not the condition. Other lints + /// such as `no_effect` will take care of removing the condition if it's unnecessary. /// /// ### Example /// ```rust,ignore @@ -42,9 +45,6 @@ impl LateLintPass<'_> for NeedlessIf { && else_expr.is_none() && !in_external_macro(cx.sess(), expr.span) { - let mut app = Applicability::MachineApplicable; - let snippet = snippet_with_applicability(cx, if_expr.span, "{ ... }", &mut app); - // Ignore `else if` if let Some(parent_id) = cx.tcx.hir().opt_parent_id(expr.hir_id) && let Some(Node::Expr(Expr { @@ -56,19 +56,48 @@ impl LateLintPass<'_> for NeedlessIf { return; } - if is_from_proc_macro(cx, expr) { + if is_any_if_let(if_expr) || is_from_proc_macro(cx, expr) { return; } + let mut app = Applicability::MachineApplicable; + let snippet = snippet_with_applicability(cx, if_expr.span, "{ ... }", &mut app); + span_lint_and_sugg( cx, NEEDLESS_IF, expr.span, - "this if branch is empty", + "this `if` branch is empty", "you can remove it", - format!("{snippet};"), - Applicability::MachineApplicable, + if if_expr.can_have_side_effects() { + format!("{snippet};") + } else { + String::new() + }, + app, ); } } } + +/// Returns true if any `Expr` contained within this `Expr` is a `Let`, else false. +/// +/// Really wish `Expr` had a `walk` method... +fn is_any_if_let(expr: &Expr<'_>) -> bool { + let mut v = IsAnyLetVisitor(false); + + v.visit_expr(expr); + v.0 +} + +struct IsAnyLetVisitor(bool); + +impl Visitor<'_> for IsAnyLetVisitor { + fn visit_expr(&mut self, expr: &Expr<'_>) { + if matches!(expr.kind, ExprKind::Let(..)) { + self.0 = true; + } + + walk_expr(self, expr); + } +} diff --git a/tests/ui/needless_if.fixed b/tests/ui/needless_if.fixed index 7587a397dc9..2abde2ad422 100644 --- a/tests/ui/needless_if.fixed +++ b/tests/ui/needless_if.fixed @@ -1,11 +1,13 @@ //@run-rustfix //@aux-build:proc_macros.rs +#![feature(let_chains)] #![allow( clippy::blocks_in_if_conditions, clippy::if_same_then_else, clippy::ifs_same_cond, clippy::needless_else, clippy::no_effect, + clippy::nonminimal_bool, unused )] #![warn(clippy::needless_if)] @@ -14,21 +16,39 @@ extern crate proc_macros; use proc_macros::external; use proc_macros::with_span; +fn no_side_effects() -> bool { + true +} + +fn has_side_effects(a: &mut u32) -> bool { + *a = 1; + true +} + fn main() { // Lint - (true); + + // Do not remove the condition + no_side_effects(); + let mut x = 0; + has_side_effects(&mut x); + assert_eq!(x, 1); // Do not lint if (true) { } else { } + { + return; + }; // Do not lint if `else if` is present if (true) { } else if (true) { } - // Ensure clippy does not bork this up, other cases should be added - { - return; - }; + // Do not lint if any `let` is present + if let true = true {} + if let true = true && true {} + if true && let true = true {} + if { if let true = true && true { true } else { false } } && true {} external! { if (true) {} } with_span! { span diff --git a/tests/ui/needless_if.rs b/tests/ui/needless_if.rs index 3006995e09d..1608d261a36 100644 --- a/tests/ui/needless_if.rs +++ b/tests/ui/needless_if.rs @@ -1,11 +1,13 @@ //@run-rustfix //@aux-build:proc_macros.rs +#![feature(let_chains)] #![allow( clippy::blocks_in_if_conditions, clippy::if_same_then_else, clippy::ifs_same_cond, clippy::needless_else, clippy::no_effect, + clippy::nonminimal_bool, unused )] #![warn(clippy::needless_if)] @@ -14,21 +16,42 @@ extern crate proc_macros; use proc_macros::external; use proc_macros::with_span; +fn no_side_effects() -> bool { + true +} + +fn has_side_effects(a: &mut u32) -> bool { + *a = 1; + true +} + fn main() { // Lint if (true) {} + // Do not remove the condition + if no_side_effects() {} + let mut x = 0; + if has_side_effects(&mut x) {} + assert_eq!(x, 1); // Do not lint if (true) { } else { } + if { + return; + } {} // Do not lint if `else if` is present if (true) { } else if (true) { } - // Ensure clippy does not bork this up, other cases should be added + // Do not lint if any `let` is present + if let true = true {} + if let true = true && true {} + if true && let true = true {} if { - return; - } {} + if let true = true && true { true } else { false } + } && true + {} external! { if (true) {} } with_span! { span diff --git a/tests/ui/needless_if.stderr b/tests/ui/needless_if.stderr index bbb2a035668..4236b0053eb 100644 --- a/tests/ui/needless_if.stderr +++ b/tests/ui/needless_if.stderr @@ -1,13 +1,25 @@ -error: this if branch is empty - --> $DIR/needless_if.rs:19:5 +error: this `if` branch is empty + --> $DIR/needless_if.rs:30:5 | LL | if (true) {} - | ^^^^^^^^^^^^ help: you can remove it: `(true);` + | ^^^^^^^^^^^^ help: you can remove it | = note: `-D clippy::needless-if` implied by `-D warnings` -error: this if branch is empty - --> $DIR/needless_if.rs:29:5 +error: this `if` branch is empty + --> $DIR/needless_if.rs:32:5 + | +LL | if no_side_effects() {} + | ^^^^^^^^^^^^^^^^^^^^^^^ help: you can remove it: `no_side_effects();` + +error: this `if` branch is empty + --> $DIR/needless_if.rs:34:5 + | +LL | if has_side_effects(&mut x) {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: you can remove it: `has_side_effects(&mut x);` + +error: this `if` branch is empty + --> $DIR/needless_if.rs:40:5 | LL | / if { LL | | return; @@ -21,5 +33,5 @@ LL + return; LL + }; | -error: aborting due to 2 previous errors +error: aborting due to 4 previous errors From 3822441335ffc761c31e553c42bbfbdacfd8da96 Mon Sep 17 00:00:00 2001 From: Centri3 <114838443+Centri3@users.noreply.github.com> Date: Sun, 11 Jun 2023 07:06:44 -0500 Subject: [PATCH 131/310] Update unnecessary_cast.stderr --- tests/ui/unnecessary_cast.stderr | 46 ++++++++++++++++---------------- 1 file changed, 23 insertions(+), 23 deletions(-) diff --git a/tests/ui/unnecessary_cast.stderr b/tests/ui/unnecessary_cast.stderr index b52e5c32c8a..618fbd4faaf 100644 --- a/tests/ui/unnecessary_cast.stderr +++ b/tests/ui/unnecessary_cast.stderr @@ -91,139 +91,139 @@ LL | uwu::([1u32].as_ptr()) as *const u32; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `uwu::([1u32].as_ptr())` error: casting integer literal to `f32` is unnecessary - --> $DIR/unnecessary_cast.rs:117:9 + --> $DIR/unnecessary_cast.rs:116:9 | LL | 100 as f32; | ^^^^^^^^^^ help: try: `100_f32` error: casting integer literal to `f64` is unnecessary - --> $DIR/unnecessary_cast.rs:118:9 + --> $DIR/unnecessary_cast.rs:117:9 | LL | 100 as f64; | ^^^^^^^^^^ help: try: `100_f64` error: casting integer literal to `f64` is unnecessary - --> $DIR/unnecessary_cast.rs:119:9 + --> $DIR/unnecessary_cast.rs:118:9 | LL | 100_i32 as f64; | ^^^^^^^^^^^^^^ help: try: `100_f64` error: casting integer literal to `f32` is unnecessary - --> $DIR/unnecessary_cast.rs:120:17 + --> $DIR/unnecessary_cast.rs:119:17 | LL | let _ = -100 as f32; | ^^^^^^^^^^^ help: try: `-100_f32` error: casting integer literal to `f64` is unnecessary - --> $DIR/unnecessary_cast.rs:121:17 + --> $DIR/unnecessary_cast.rs:120:17 | LL | let _ = -100 as f64; | ^^^^^^^^^^^ help: try: `-100_f64` error: casting integer literal to `f64` is unnecessary - --> $DIR/unnecessary_cast.rs:122:17 + --> $DIR/unnecessary_cast.rs:121:17 | LL | let _ = -100_i32 as f64; | ^^^^^^^^^^^^^^^ help: try: `-100_f64` error: casting float literal to `f32` is unnecessary - --> $DIR/unnecessary_cast.rs:123:9 + --> $DIR/unnecessary_cast.rs:122:9 | LL | 100. as f32; | ^^^^^^^^^^^ help: try: `100_f32` error: casting float literal to `f64` is unnecessary - --> $DIR/unnecessary_cast.rs:124:9 + --> $DIR/unnecessary_cast.rs:123:9 | LL | 100. as f64; | ^^^^^^^^^^^ help: try: `100_f64` error: casting integer literal to `u32` is unnecessary - --> $DIR/unnecessary_cast.rs:136:9 + --> $DIR/unnecessary_cast.rs:135:9 | LL | 1 as u32; | ^^^^^^^^ help: try: `1_u32` error: casting integer literal to `i32` is unnecessary - --> $DIR/unnecessary_cast.rs:137:9 + --> $DIR/unnecessary_cast.rs:136:9 | LL | 0x10 as i32; | ^^^^^^^^^^^ help: try: `0x10_i32` error: casting integer literal to `usize` is unnecessary - --> $DIR/unnecessary_cast.rs:138:9 + --> $DIR/unnecessary_cast.rs:137:9 | LL | 0b10 as usize; | ^^^^^^^^^^^^^ help: try: `0b10_usize` error: casting integer literal to `u16` is unnecessary - --> $DIR/unnecessary_cast.rs:139:9 + --> $DIR/unnecessary_cast.rs:138:9 | LL | 0o73 as u16; | ^^^^^^^^^^^ help: try: `0o73_u16` error: casting integer literal to `u32` is unnecessary - --> $DIR/unnecessary_cast.rs:140:9 + --> $DIR/unnecessary_cast.rs:139:9 | LL | 1_000_000_000 as u32; | ^^^^^^^^^^^^^^^^^^^^ help: try: `1_000_000_000_u32` error: casting float literal to `f64` is unnecessary - --> $DIR/unnecessary_cast.rs:142:9 + --> $DIR/unnecessary_cast.rs:141:9 | LL | 1.0 as f64; | ^^^^^^^^^^ help: try: `1.0_f64` error: casting float literal to `f32` is unnecessary - --> $DIR/unnecessary_cast.rs:143:9 + --> $DIR/unnecessary_cast.rs:142:9 | LL | 0.5 as f32; | ^^^^^^^^^^ help: try: `0.5_f32` error: casting integer literal to `i32` is unnecessary - --> $DIR/unnecessary_cast.rs:147:17 + --> $DIR/unnecessary_cast.rs:146:17 | LL | let _ = -1 as i32; | ^^^^^^^^^ help: try: `-1_i32` error: casting float literal to `f32` is unnecessary - --> $DIR/unnecessary_cast.rs:148:17 + --> $DIR/unnecessary_cast.rs:147:17 | LL | let _ = -1.0 as f32; | ^^^^^^^^^^^ help: try: `-1.0_f32` error: casting to the same type is unnecessary (`i32` -> `i32`) - --> $DIR/unnecessary_cast.rs:154:18 + --> $DIR/unnecessary_cast.rs:153:18 | LL | let _ = &(x as i32); | ^^^^^^^^^^ help: try: `{ x }` error: casting integer literal to `i32` is unnecessary - --> $DIR/unnecessary_cast.rs:160:22 + --> $DIR/unnecessary_cast.rs:159:22 | LL | let _: i32 = -(1) as i32; | ^^^^^^^^^^^ help: try: `-1_i32` error: casting integer literal to `i64` is unnecessary - --> $DIR/unnecessary_cast.rs:162:22 + --> $DIR/unnecessary_cast.rs:161:22 | LL | let _: i64 = -(1) as i64; | ^^^^^^^^^^^ help: try: `-1_i64` error: casting float literal to `f64` is unnecessary - --> $DIR/unnecessary_cast.rs:169:22 + --> $DIR/unnecessary_cast.rs:168:22 | LL | let _: f64 = (-8.0 as f64).exp(); | ^^^^^^^^^^^^^ help: try: `(-8.0_f64)` error: casting float literal to `f64` is unnecessary - --> $DIR/unnecessary_cast.rs:171:23 + --> $DIR/unnecessary_cast.rs:170:23 | LL | let _: f64 = -(8.0 as f64).exp(); // should suggest `-8.0_f64.exp()` here not to change code behavior | ^^^^^^^^^^^^ help: try: `8.0_f64` error: casting to the same type is unnecessary (`f32` -> `f32`) - --> $DIR/unnecessary_cast.rs:179:20 + --> $DIR/unnecessary_cast.rs:178:20 | LL | let _num = foo() as f32; | ^^^^^^^^^^^^ help: try: `foo()` From d989f432a4c73be55aff9434001d510f6b30c013 Mon Sep 17 00:00:00 2001 From: Centri3 <114838443+Centri3@users.noreply.github.com> Date: Sun, 11 Jun 2023 07:12:46 -0500 Subject: [PATCH 132/310] Update needless_if.fixed --- tests/ui/needless_if.fixed | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/tests/ui/needless_if.fixed b/tests/ui/needless_if.fixed index 2abde2ad422..bee579be1bf 100644 --- a/tests/ui/needless_if.fixed +++ b/tests/ui/needless_if.fixed @@ -48,7 +48,10 @@ fn main() { if let true = true {} if let true = true && true {} if true && let true = true {} - if { if let true = true && true { true } else { false } } && true {} + if { + if let true = true && true { true } else { false } + } && true + {} external! { if (true) {} } with_span! { span From 108c04acf0bdb90e68ec7c12e86c5fbb21548061 Mon Sep 17 00:00:00 2001 From: Centri3 <114838443+Centri3@users.noreply.github.com> Date: Sun, 11 Jun 2023 09:43:26 -0500 Subject: [PATCH 133/310] Stop visiting once it's found `Let` --- clippy_lints/src/needless_if.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/clippy_lints/src/needless_if.rs b/clippy_lints/src/needless_if.rs index b118516e09b..dbffbd6f0d3 100644 --- a/clippy_lints/src/needless_if.rs +++ b/clippy_lints/src/needless_if.rs @@ -96,8 +96,8 @@ impl Visitor<'_> for IsAnyLetVisitor { fn visit_expr(&mut self, expr: &Expr<'_>) { if matches!(expr.kind, ExprKind::Let(..)) { self.0 = true; + } else { + walk_expr(self, expr); } - - walk_expr(self, expr); } } From 4191de3303687b54f9ed5114170c9985b8962fe5 Mon Sep 17 00:00:00 2001 From: Centri3 <114838443+Centri3@users.noreply.github.com> Date: Sun, 11 Jun 2023 14:52:26 -0500 Subject: [PATCH 134/310] Update check_proc_macro.rs --- clippy_utils/src/check_proc_macro.rs | 13 ------------- 1 file changed, 13 deletions(-) diff --git a/clippy_utils/src/check_proc_macro.rs b/clippy_utils/src/check_proc_macro.rs index 05b34986274..bcfac527c8a 100644 --- a/clippy_utils/src/check_proc_macro.rs +++ b/clippy_utils/src/check_proc_macro.rs @@ -319,19 +319,6 @@ fn attr_search_pat(attr: &Attribute) -> (Pat, Pat) { } } -// TODO: Waiting on `ty_search_pat`. -// fn where_pred_search_pat(where_pred: &WherePredicate<'_>) -> (Pat, Pat) { -// match where_pred { -// WherePredicate::BoundPredicate(bound) => { -// todo!(); -// }, -// WherePredicate::RegionPredicate(region) => { -// -// }, -// WherePredicate::EqPredicate(..) => unimplemented!(), -// } -// } - fn ty_search_pat(ty: &Ty<'_>) -> (Pat, Pat) { match ty.kind { TyKind::Slice(..) | TyKind::Array(..) => (Pat::Str("["), Pat::Str("]")), From 7280ad9f7b43755703610ed13dc60a58144a1a0f Mon Sep 17 00:00:00 2001 From: y21 <30553356+y21@users.noreply.github.com> Date: Sun, 11 Jun 2023 23:54:48 +0200 Subject: [PATCH 135/310] [`redundant_closure_call`]: handle nested closures --- clippy_lints/src/lib.rs | 1 - clippy_lints/src/redundant_closure_call.rs | 171 +++++++++++++----- tests/ui/redundant_closure_call_fixable.fixed | 40 ++++ tests/ui/redundant_closure_call_fixable.rs | 40 ++++ .../ui/redundant_closure_call_fixable.stderr | 50 ++++- 5 files changed, 247 insertions(+), 55 deletions(-) diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index 2f5932104c1..3e8d6af5302 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -791,7 +791,6 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: store.register_early_pass(|| Box::new(int_plus_one::IntPlusOne)); store.register_early_pass(|| Box::new(formatting::Formatting)); store.register_early_pass(|| Box::new(misc_early::MiscEarlyLints)); - store.register_early_pass(|| Box::new(redundant_closure_call::RedundantClosureCall)); store.register_late_pass(|_| Box::new(redundant_closure_call::RedundantClosureCall)); store.register_early_pass(|| Box::new(unused_unit::UnusedUnit)); store.register_late_pass(|_| Box::new(returns::Return)); diff --git a/clippy_lints/src/redundant_closure_call.rs b/clippy_lints/src/redundant_closure_call.rs index 2a42e73488f..4e1ffc2fe37 100644 --- a/clippy_lints/src/redundant_closure_call.rs +++ b/clippy_lints/src/redundant_closure_call.rs @@ -1,14 +1,14 @@ +use crate::rustc_lint::LintContext; use clippy_utils::diagnostics::{span_lint, span_lint_and_then}; +use clippy_utils::get_parent_expr; use clippy_utils::sugg::Sugg; use if_chain::if_chain; -use rustc_ast::ast; -use rustc_ast::visit as ast_visit; -use rustc_ast::visit::Visitor as AstVisitor; use rustc_errors::Applicability; use rustc_hir as hir; use rustc_hir::intravisit as hir_visit; use rustc_hir::intravisit::Visitor as HirVisitor; -use rustc_lint::{EarlyContext, EarlyLintPass, LateContext, LateLintPass, LintContext}; +use rustc_hir::intravisit::Visitor; +use rustc_lint::{LateContext, LateLintPass}; use rustc_middle::hir::nested_filter; use rustc_middle::lint::in_external_macro; use rustc_session::{declare_lint_pass, declare_tool_lint}; @@ -51,59 +51,136 @@ impl ReturnVisitor { } } -impl<'ast> ast_visit::Visitor<'ast> for ReturnVisitor { - fn visit_expr(&mut self, ex: &'ast ast::Expr) { - if let ast::ExprKind::Ret(_) | ast::ExprKind::Try(_) = ex.kind { +impl<'tcx> Visitor<'tcx> for ReturnVisitor { + fn visit_expr(&mut self, ex: &'tcx hir::Expr<'tcx>) { + if let hir::ExprKind::Ret(_) | hir::ExprKind::Match(.., hir::MatchSource::TryDesugar) = ex.kind { self.found_return = true; } - ast_visit::walk_expr(self, ex); + hir_visit::walk_expr(self, ex); } } -impl EarlyLintPass for RedundantClosureCall { - fn check_expr(&mut self, cx: &EarlyContext<'_>, expr: &ast::Expr) { - if in_external_macro(cx.sess(), expr.span) { - return; - } - if_chain! { - if let ast::ExprKind::Call(ref paren, _) = expr.kind; - if let ast::ExprKind::Paren(ref closure) = paren.kind; - if let ast::ExprKind::Closure(box ast::Closure { ref asyncness, ref fn_decl, ref body, .. }) = closure.kind; - then { - let mut visitor = ReturnVisitor::new(); - visitor.visit_expr(body); - if !visitor.found_return { - span_lint_and_then( - cx, - REDUNDANT_CLOSURE_CALL, - expr.span, - "try not to call a closure in the expression where it is declared", - |diag| { - if fn_decl.inputs.is_empty() { - let mut app = Applicability::MachineApplicable; - let mut hint = Sugg::ast(cx, body, "..", closure.span.ctxt(), &mut app); - - if asyncness.is_async() { - // `async x` is a syntax error, so it becomes `async { x }` - if !matches!(body.kind, ast::ExprKind::Block(_, _)) { - hint = hint.blockify(); - } - - hint = hint.asyncify(); - } - - diag.span_suggestion(expr.span, "try doing something like", hint.to_string(), app); - } - }, - ); - } - } - } +/// Checks if the body is owned by an async closure +fn is_async_closure(body: &hir::Body<'_>) -> bool { + if let hir::ExprKind::Closure(closure) = body.value.kind + && let [resume_ty] = closure.fn_decl.inputs + && let hir::TyKind::Path(hir::QPath::LangItem(hir::LangItem::ResumeTy, ..)) = resume_ty.kind + { + true + } else { + false } } +/// Tries to find the innermost closure: +/// ```rust +/// (|| || || || 42)()()()() +/// ^^^^^^^^^^^^^^ given this nested closure expression +/// ^^^^^ we want to return this closure +/// ``` +/// It also has a parameter for how many steps to go in at most, so as to +/// not take more closures than there are calls. +fn find_innermost_closure<'tcx>( + cx: &LateContext<'tcx>, + mut expr: &'tcx hir::Expr<'tcx>, + mut steps: usize, +) -> Option<(&'tcx hir::Expr<'tcx>, &'tcx hir::FnDecl<'tcx>, hir::IsAsync)> { + let mut data = None; + + while let hir::ExprKind::Closure(closure) = expr.kind + && let body = cx.tcx.hir().body(closure.body) + && { + let mut visitor = ReturnVisitor::new(); + visitor.visit_expr(body.value); + !visitor.found_return + } + && steps > 0 + { + expr = body.value; + data = Some((body.value, closure.fn_decl, if is_async_closure(body) { + hir::IsAsync::Async + } else { + hir::IsAsync::NotAsync + })); + steps -= 1; + } + + data +} + +/// "Walks up" the chain of calls to find the outermost call expression, and returns the depth: +/// ```rust +/// (|| || || 3)()()() +/// ^^ this is the call expression we were given +/// ^^ this is what we want to return (and the depth is 3) +/// ``` +fn get_parent_call_exprs<'tcx>( + cx: &LateContext<'tcx>, + mut expr: &'tcx hir::Expr<'tcx>, +) -> (&'tcx hir::Expr<'tcx>, usize) { + let mut depth = 1; + while let Some(parent) = get_parent_expr(cx, expr) + && let hir::ExprKind::Call(recv, _) = parent.kind + && let hir::ExprKind::Call(..) = recv.kind + { + expr = parent; + depth += 1; + } + (expr, depth) +} + impl<'tcx> LateLintPass<'tcx> for RedundantClosureCall { + fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx hir::Expr<'tcx>) { + if in_external_macro(cx.sess(), expr.span) { + return; + } + + if let hir::ExprKind::Call(recv, _) = expr.kind + // don't lint if the receiver is a call, too. + // we do this in order to prevent linting multiple times; consider: + // `(|| || 1)()()` + // ^^ we only want to lint for this call (but we walk up the calls to consider both calls). + // without this check, we'd end up linting twice. + && !matches!(recv.kind, hir::ExprKind::Call(..)) + && let (full_expr, call_depth) = get_parent_call_exprs(cx, expr) + && let Some((body, fn_decl, generator_kind)) = find_innermost_closure(cx, recv, call_depth) + { + span_lint_and_then( + cx, + REDUNDANT_CLOSURE_CALL, + full_expr.span, + "try not to call a closure in the expression where it is declared", + |diag| { + if fn_decl.inputs.is_empty() { + let mut applicability = Applicability::MachineApplicable; + let mut hint = Sugg::hir_with_context(cx, body, full_expr.span.ctxt(), "..", &mut applicability); + + if generator_kind.is_async() + && let hir::ExprKind::Closure(closure) = body.kind + { + let async_closure_body = cx.tcx.hir().body(closure.body); + + // `async x` is a syntax error, so it becomes `async { x }` + if !matches!(async_closure_body.value.kind, hir::ExprKind::Block(_, _)) { + hint = hint.blockify(); + } + + hint = hint.asyncify(); + } + + diag.span_suggestion( + full_expr.span, + "try doing something like", + hint.maybe_par(), + applicability + ); + } + } + ); + } + } + fn check_block(&mut self, cx: &LateContext<'tcx>, block: &'tcx hir::Block<'_>) { fn count_closure_usage<'tcx>( cx: &LateContext<'tcx>, diff --git a/tests/ui/redundant_closure_call_fixable.fixed b/tests/ui/redundant_closure_call_fixable.fixed index 61aed2733fe..1a2c1e59261 100644 --- a/tests/ui/redundant_closure_call_fixable.fixed +++ b/tests/ui/redundant_closure_call_fixable.fixed @@ -3,6 +3,7 @@ #![feature(async_closure)] #![warn(clippy::redundant_closure_call)] #![allow(clippy::redundant_async_block)] +#![allow(clippy::type_complexity)] #![allow(unused)] async fn something() -> u32 { @@ -38,4 +39,43 @@ fn main() { }; } m2!(); + issue9956(); +} + +fn issue9956() { + assert_eq!(43, 42); + + // ... and some more interesting cases I've found while implementing the fix + + // not actually immediately calling the closure: + let a = (|| 42); + dbg!(a()); + + // immediately calling it inside of a macro + dbg!(42); + + // immediately calling only one closure, so we can't remove the other ones + let a = (|| || 123); + dbg!(a()()); + + // nested async closures + let a = async { 1 }; + let h = async { a.await }; + + // macro expansion tests + macro_rules! echo { + ($e:expr) => { + $e + }; + } + let a = 1; + assert_eq!(a, 1); + let a = 123; + assert_eq!(a, 123); + + // chaining calls, but not closures + fn x() -> fn() -> fn() -> fn() -> i32 { + || || || 42 + } + let _ = x()()()(); } diff --git a/tests/ui/redundant_closure_call_fixable.rs b/tests/ui/redundant_closure_call_fixable.rs index 56b28663539..fec46652189 100644 --- a/tests/ui/redundant_closure_call_fixable.rs +++ b/tests/ui/redundant_closure_call_fixable.rs @@ -3,6 +3,7 @@ #![feature(async_closure)] #![warn(clippy::redundant_closure_call)] #![allow(clippy::redundant_async_block)] +#![allow(clippy::type_complexity)] #![allow(unused)] async fn something() -> u32 { @@ -38,4 +39,43 @@ fn main() { }; } m2!(); + issue9956(); +} + +fn issue9956() { + assert_eq!((|| || 43)()(), 42); + + // ... and some more interesting cases I've found while implementing the fix + + // not actually immediately calling the closure: + let a = (|| 42); + dbg!(a()); + + // immediately calling it inside of a macro + dbg!((|| 42)()); + + // immediately calling only one closure, so we can't remove the other ones + let a = (|| || || 123)(); + dbg!(a()()); + + // nested async closures + let a = (|| || || || async || 1)()()()()(); + let h = async { a.await }; + + // macro expansion tests + macro_rules! echo { + ($e:expr) => { + $e + }; + } + let a = (|| echo!(|| echo!(|| 1)))()()(); + assert_eq!(a, 1); + let a = (|| echo!((|| 123)))()(); + assert_eq!(a, 123); + + // chaining calls, but not closures + fn x() -> fn() -> fn() -> fn() -> i32 { + || || || 42 + } + let _ = x()()()(); } diff --git a/tests/ui/redundant_closure_call_fixable.stderr b/tests/ui/redundant_closure_call_fixable.stderr index 8a1f0771659..351da54ef31 100644 --- a/tests/ui/redundant_closure_call_fixable.stderr +++ b/tests/ui/redundant_closure_call_fixable.stderr @@ -1,5 +1,5 @@ error: try not to call a closure in the expression where it is declared - --> $DIR/redundant_closure_call_fixable.rs:17:13 + --> $DIR/redundant_closure_call_fixable.rs:18:13 | LL | let a = (|| 42)(); | ^^^^^^^^^ help: try doing something like: `42` @@ -7,7 +7,7 @@ LL | let a = (|| 42)(); = note: `-D clippy::redundant-closure-call` implied by `-D warnings` error: try not to call a closure in the expression where it is declared - --> $DIR/redundant_closure_call_fixable.rs:18:13 + --> $DIR/redundant_closure_call_fixable.rs:19:13 | LL | let b = (async || { | _____________^ @@ -27,7 +27,7 @@ LL ~ }; | error: try not to call a closure in the expression where it is declared - --> $DIR/redundant_closure_call_fixable.rs:23:13 + --> $DIR/redundant_closure_call_fixable.rs:24:13 | LL | let c = (|| { | _____________^ @@ -47,13 +47,13 @@ LL ~ }; | error: try not to call a closure in the expression where it is declared - --> $DIR/redundant_closure_call_fixable.rs:28:13 + --> $DIR/redundant_closure_call_fixable.rs:29:13 | LL | let d = (async || something().await)(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try doing something like: `async { something().await }` error: try not to call a closure in the expression where it is declared - --> $DIR/redundant_closure_call_fixable.rs:37:13 + --> $DIR/redundant_closure_call_fixable.rs:38:13 | LL | (|| m!())() | ^^^^^^^^^^^ help: try doing something like: `m!()` @@ -64,7 +64,7 @@ LL | m2!(); = note: this error originates in the macro `m2` (in Nightly builds, run with -Z macro-backtrace for more info) error: try not to call a closure in the expression where it is declared - --> $DIR/redundant_closure_call_fixable.rs:32:13 + --> $DIR/redundant_closure_call_fixable.rs:33:13 | LL | (|| 0)() | ^^^^^^^^ help: try doing something like: `0` @@ -74,5 +74,41 @@ LL | m2!(); | = note: this error originates in the macro `m` which comes from the expansion of the macro `m2` (in Nightly builds, run with -Z macro-backtrace for more info) -error: aborting due to 6 previous errors +error: try not to call a closure in the expression where it is declared + --> $DIR/redundant_closure_call_fixable.rs:46:16 + | +LL | assert_eq!((|| || 43)()(), 42); + | ^^^^^^^^^^^^^^ help: try doing something like: `43` + +error: try not to call a closure in the expression where it is declared + --> $DIR/redundant_closure_call_fixable.rs:55:10 + | +LL | dbg!((|| 42)()); + | ^^^^^^^^^ help: try doing something like: `42` + +error: try not to call a closure in the expression where it is declared + --> $DIR/redundant_closure_call_fixable.rs:58:13 + | +LL | let a = (|| || || 123)(); + | ^^^^^^^^^^^^^^^^ help: try doing something like: `(|| || 123)` + +error: try not to call a closure in the expression where it is declared + --> $DIR/redundant_closure_call_fixable.rs:62:13 + | +LL | let a = (|| || || || async || 1)()()()()(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try doing something like: `async { 1 }` + +error: try not to call a closure in the expression where it is declared + --> $DIR/redundant_closure_call_fixable.rs:71:13 + | +LL | let a = (|| echo!(|| echo!(|| 1)))()()(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try doing something like: `1` + +error: try not to call a closure in the expression where it is declared + --> $DIR/redundant_closure_call_fixable.rs:73:13 + | +LL | let a = (|| echo!((|| 123)))()(); + | ^^^^^^^^^^^^^^^^^^^^^^^^ help: try doing something like: `123` + +error: aborting due to 12 previous errors From e305b0730fedfe3fa8b54dbb285f498a3277baa9 Mon Sep 17 00:00:00 2001 From: y21 <30553356+y21@users.noreply.github.com> Date: Mon, 12 Jun 2023 00:20:54 +0200 Subject: [PATCH 136/310] fix docs --- clippy_lints/src/redundant_closure_call.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/clippy_lints/src/redundant_closure_call.rs b/clippy_lints/src/redundant_closure_call.rs index 4e1ffc2fe37..d979087a6d7 100644 --- a/clippy_lints/src/redundant_closure_call.rs +++ b/clippy_lints/src/redundant_closure_call.rs @@ -74,7 +74,7 @@ fn is_async_closure(body: &hir::Body<'_>) -> bool { } /// Tries to find the innermost closure: -/// ```rust +/// ```rust,ignore /// (|| || || || 42)()()()() /// ^^^^^^^^^^^^^^ given this nested closure expression /// ^^^^^ we want to return this closure @@ -110,10 +110,10 @@ fn find_innermost_closure<'tcx>( } /// "Walks up" the chain of calls to find the outermost call expression, and returns the depth: -/// ```rust +/// ```rust,ignore /// (|| || || 3)()()() -/// ^^ this is the call expression we were given -/// ^^ this is what we want to return (and the depth is 3) +/// ^^ this is the call expression we were given +/// ^^ this is what we want to return (and the depth is 3) /// ``` fn get_parent_call_exprs<'tcx>( cx: &LateContext<'tcx>, From c9daec2585c464f2e7d37756c341b217ca795bde Mon Sep 17 00:00:00 2001 From: y21 <30553356+y21@users.noreply.github.com> Date: Mon, 12 Jun 2023 02:43:23 +0200 Subject: [PATCH 137/310] [`unnecessary_fold`]: suggest turbofish if necessary --- clippy_lints/src/methods/unnecessary_fold.rs | 124 +++++++++++++++++-- tests/ui/unnecessary_fold.fixed | 24 ++++ tests/ui/unnecessary_fold.rs | 24 ++++ tests/ui/unnecessary_fold.stderr | 56 ++++++++- 4 files changed, 217 insertions(+), 11 deletions(-) diff --git a/clippy_lints/src/methods/unnecessary_fold.rs b/clippy_lints/src/methods/unnecessary_fold.rs index 5a3d12fd790..de29d99cf8d 100644 --- a/clippy_lints/src/methods/unnecessary_fold.rs +++ b/clippy_lints/src/methods/unnecessary_fold.rs @@ -7,10 +7,74 @@ use rustc_errors::Applicability; use rustc_hir as hir; use rustc_hir::PatKind; use rustc_lint::LateContext; +use rustc_middle::ty; use rustc_span::{source_map::Span, sym}; use super::UNNECESSARY_FOLD; +/// No turbofish needed in any case. +fn no_turbofish(_: &LateContext<'_>, _: &hir::Expr<'_>) -> bool { + false +} + +/// Turbofish (`::`) may be needed, but can be omitted if we are certain +/// that the type can be inferred from usage. +fn turbofish_if_not_inferred(cx: &LateContext<'_>, expr: &hir::Expr<'_>) -> bool { + let parent = cx.tcx.hir().get_parent(expr.hir_id); + + // some common cases where turbofish isn't needed: + // - assigned to a local variable with a type annotation + if let hir::Node::Local(local) = parent + && local.ty.is_some() + { + return false; + } + + // - part of a function call argument, can be inferred from the function signature (provided that + // the parameter is not a generic type parameter) + if let hir::Node::Expr(parent_expr) = parent + && let hir::ExprKind::Call(recv, args) = parent_expr.kind + && let hir::ExprKind::Path(ref qpath) = recv.kind + && let Some(fn_def_id) = cx.qpath_res(qpath, recv.hir_id).opt_def_id() + && let fn_sig = cx.tcx.fn_sig(fn_def_id).skip_binder().skip_binder() + && let Some(arg_pos) = args.iter().position(|arg| arg.hir_id == expr.hir_id) + && let Some(ty) = fn_sig.inputs().get(arg_pos) + && !matches!(ty.kind(), ty::Param(_)) + { + return false; + } + + // if it's neither of those, stay on the safe side and suggest turbofish, + // even if it could work! + true +} + +#[derive(Copy, Clone)] +struct Replacement { + method_name: &'static str, + has_args: bool, + requires_turbofish: fn(&LateContext<'_>, &hir::Expr<'_>) -> bool, +} +impl Replacement { + /// `any(f)`, `all(f)` + pub fn non_generic(method_name: &'static str) -> Self { + Self { + method_name, + has_args: true, + requires_turbofish: no_turbofish, + } + } + + /// `sum::()`, `product::()` + pub fn generic(method_name: &'static str) -> Self { + Self { + method_name, + has_args: false, + requires_turbofish: turbofish_if_not_inferred, + } + } +} + pub(super) fn check( cx: &LateContext<'_>, expr: &hir::Expr<'_>, @@ -24,8 +88,7 @@ pub(super) fn check( acc: &hir::Expr<'_>, fold_span: Span, op: hir::BinOpKind, - replacement_method_name: &str, - replacement_has_args: bool, + replacement: Replacement, ) { if_chain! { // Extract the body of the closure passed to fold @@ -43,18 +106,27 @@ pub(super) fn check( if let PatKind::Binding(_, second_arg_id, second_arg_ident, _) = strip_pat_refs(param_b.pat).kind; if path_to_local_id(left_expr, first_arg_id); - if replacement_has_args || path_to_local_id(right_expr, second_arg_id); + if replacement.has_args || path_to_local_id(right_expr, second_arg_id); then { let mut applicability = Applicability::MachineApplicable; - let sugg = if replacement_has_args { + + let turbofish = if (replacement.requires_turbofish)(cx, expr) { + format!("::<{}>", cx.typeck_results().expr_ty_adjusted(right_expr).peel_refs()) + } else { + String::new() + }; + + let sugg = if replacement.has_args { format!( - "{replacement_method_name}(|{second_arg_ident}| {r})", + "{method}{turbofish}(|{second_arg_ident}| {r})", + method = replacement.method_name, r = snippet_with_applicability(cx, right_expr.span, "EXPR", &mut applicability), ) } else { format!( - "{replacement_method_name}()", + "{method}{turbofish}()", + method = replacement.method_name, ) }; @@ -80,11 +152,43 @@ pub(super) fn check( // Check if the first argument to .fold is a suitable literal if let hir::ExprKind::Lit(lit) = init.kind { match lit.node { - ast::LitKind::Bool(false) => check_fold_with_op(cx, expr, acc, fold_span, hir::BinOpKind::Or, "any", true), - ast::LitKind::Bool(true) => check_fold_with_op(cx, expr, acc, fold_span, hir::BinOpKind::And, "all", true), - ast::LitKind::Int(0, _) => check_fold_with_op(cx, expr, acc, fold_span, hir::BinOpKind::Add, "sum", false), + ast::LitKind::Bool(false) => { + check_fold_with_op( + cx, + expr, + acc, + fold_span, + hir::BinOpKind::Or, + Replacement::non_generic("any"), + ); + }, + ast::LitKind::Bool(true) => { + check_fold_with_op( + cx, + expr, + acc, + fold_span, + hir::BinOpKind::And, + Replacement::non_generic("all"), + ); + }, + ast::LitKind::Int(0, _) => check_fold_with_op( + cx, + expr, + acc, + fold_span, + hir::BinOpKind::Add, + Replacement::generic("sum"), + ), ast::LitKind::Int(1, _) => { - check_fold_with_op(cx, expr, acc, fold_span, hir::BinOpKind::Mul, "product", false); + check_fold_with_op( + cx, + expr, + acc, + fold_span, + hir::BinOpKind::Mul, + Replacement::generic("product"), + ); }, _ => (), } diff --git a/tests/ui/unnecessary_fold.fixed b/tests/ui/unnecessary_fold.fixed index 2bed14973ca..bd1d4a152ae 100644 --- a/tests/ui/unnecessary_fold.fixed +++ b/tests/ui/unnecessary_fold.fixed @@ -49,4 +49,28 @@ fn unnecessary_fold_over_multiple_lines() { .any(|x| x > 2); } +fn issue10000() { + use std::collections::HashMap; + use std::hash::BuildHasher; + + fn anything(_: T) {} + fn num(_: i32) {} + fn smoketest_map(mut map: HashMap) { + map.insert(0, 0); + assert_eq!(map.values().sum::(), 0); + + // more cases: + let _ = map.values().sum::(); + let _ = map.values().product::(); + let _: i32 = map.values().sum(); + let _: i32 = map.values().product(); + anything(map.values().sum::()); + anything(map.values().product::()); + num(map.values().sum()); + num(map.values().product()); + } + + smoketest_map(HashMap::new()); +} + fn main() {} diff --git a/tests/ui/unnecessary_fold.rs b/tests/ui/unnecessary_fold.rs index a3cec8ea3d5..d27cc460c44 100644 --- a/tests/ui/unnecessary_fold.rs +++ b/tests/ui/unnecessary_fold.rs @@ -49,4 +49,28 @@ fn unnecessary_fold_over_multiple_lines() { .fold(false, |acc, x| acc || x > 2); } +fn issue10000() { + use std::collections::HashMap; + use std::hash::BuildHasher; + + fn anything(_: T) {} + fn num(_: i32) {} + fn smoketest_map(mut map: HashMap) { + map.insert(0, 0); + assert_eq!(map.values().fold(0, |x, y| x + y), 0); + + // more cases: + let _ = map.values().fold(0, |x, y| x + y); + let _ = map.values().fold(1, |x, y| x * y); + let _: i32 = map.values().fold(0, |x, y| x + y); + let _: i32 = map.values().fold(1, |x, y| x * y); + anything(map.values().fold(0, |x, y| x + y)); + anything(map.values().fold(1, |x, y| x * y)); + num(map.values().fold(0, |x, y| x + y)); + num(map.values().fold(1, |x, y| x * y)); + } + + smoketest_map(HashMap::new()); +} + fn main() {} diff --git a/tests/ui/unnecessary_fold.stderr b/tests/ui/unnecessary_fold.stderr index 22c44588ab7..98979f7477f 100644 --- a/tests/ui/unnecessary_fold.stderr +++ b/tests/ui/unnecessary_fold.stderr @@ -36,5 +36,59 @@ error: this `.fold` can be written more succinctly using another method LL | .fold(false, |acc, x| acc || x > 2); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `any(|x| x > 2)` -error: aborting due to 6 previous errors +error: this `.fold` can be written more succinctly using another method + --> $DIR/unnecessary_fold.rs:60:33 + | +LL | assert_eq!(map.values().fold(0, |x, y| x + y), 0); + | ^^^^^^^^^^^^^^^^^^^^^ help: try: `sum::()` + +error: this `.fold` can be written more succinctly using another method + --> $DIR/unnecessary_fold.rs:63:30 + | +LL | let _ = map.values().fold(0, |x, y| x + y); + | ^^^^^^^^^^^^^^^^^^^^^ help: try: `sum::()` + +error: this `.fold` can be written more succinctly using another method + --> $DIR/unnecessary_fold.rs:64:30 + | +LL | let _ = map.values().fold(1, |x, y| x * y); + | ^^^^^^^^^^^^^^^^^^^^^ help: try: `product::()` + +error: this `.fold` can be written more succinctly using another method + --> $DIR/unnecessary_fold.rs:65:35 + | +LL | let _: i32 = map.values().fold(0, |x, y| x + y); + | ^^^^^^^^^^^^^^^^^^^^^ help: try: `sum()` + +error: this `.fold` can be written more succinctly using another method + --> $DIR/unnecessary_fold.rs:66:35 + | +LL | let _: i32 = map.values().fold(1, |x, y| x * y); + | ^^^^^^^^^^^^^^^^^^^^^ help: try: `product()` + +error: this `.fold` can be written more succinctly using another method + --> $DIR/unnecessary_fold.rs:67:31 + | +LL | anything(map.values().fold(0, |x, y| x + y)); + | ^^^^^^^^^^^^^^^^^^^^^ help: try: `sum::()` + +error: this `.fold` can be written more succinctly using another method + --> $DIR/unnecessary_fold.rs:68:31 + | +LL | anything(map.values().fold(1, |x, y| x * y)); + | ^^^^^^^^^^^^^^^^^^^^^ help: try: `product::()` + +error: this `.fold` can be written more succinctly using another method + --> $DIR/unnecessary_fold.rs:69:26 + | +LL | num(map.values().fold(0, |x, y| x + y)); + | ^^^^^^^^^^^^^^^^^^^^^ help: try: `sum()` + +error: this `.fold` can be written more succinctly using another method + --> $DIR/unnecessary_fold.rs:70:26 + | +LL | num(map.values().fold(1, |x, y| x * y)); + | ^^^^^^^^^^^^^^^^^^^^^ help: try: `product()` + +error: aborting due to 15 previous errors From 52cfc997afbaff3b0e98f82a06b90c8230c9225b Mon Sep 17 00:00:00 2001 From: Centri3 <114838443+Centri3@users.noreply.github.com> Date: Fri, 9 Jun 2023 13:33:30 -0500 Subject: [PATCH 138/310] Add lint `single_letter_idents` --- CHANGELOG.md | 1 + clippy_lints/src/declared_lints.rs | 1 + clippy_lints/src/lib.rs | 7 ++ clippy_lints/src/single_letter_idents.rs | 52 +++++++++ clippy_lints/src/utils/conf.rs | 1 + clippy_utils/src/check_proc_macro.rs | 29 +++-- .../toml_unknown_key/conf_unknown_key.stderr | 2 + tests/ui/single_letter_idents.rs | 59 +++++++++++ tests/ui/single_letter_idents.stderr | 100 ++++++++++++++++++ 9 files changed, 246 insertions(+), 6 deletions(-) create mode 100644 clippy_lints/src/single_letter_idents.rs create mode 100644 tests/ui/single_letter_idents.rs create mode 100644 tests/ui/single_letter_idents.stderr diff --git a/CHANGELOG.md b/CHANGELOG.md index 8a330b35d69..5a03d768fee 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5160,6 +5160,7 @@ Released 2018-09-13 [`single_char_push_str`]: https://rust-lang.github.io/rust-clippy/master/index.html#single_char_push_str [`single_component_path_imports`]: https://rust-lang.github.io/rust-clippy/master/index.html#single_component_path_imports [`single_element_loop`]: https://rust-lang.github.io/rust-clippy/master/index.html#single_element_loop +[`single_letter_idents`]: https://rust-lang.github.io/rust-clippy/master/index.html#single_letter_idents [`single_match`]: https://rust-lang.github.io/rust-clippy/master/index.html#single_match [`single_match_else`]: https://rust-lang.github.io/rust-clippy/master/index.html#single_match_else [`size_of_in_element_count`]: https://rust-lang.github.io/rust-clippy/master/index.html#size_of_in_element_count diff --git a/clippy_lints/src/declared_lints.rs b/clippy_lints/src/declared_lints.rs index 874c173f709..03c3e153a97 100644 --- a/clippy_lints/src/declared_lints.rs +++ b/clippy_lints/src/declared_lints.rs @@ -567,6 +567,7 @@ pub(crate) static LINTS: &[&crate::LintInfo] = &[ crate::significant_drop_tightening::SIGNIFICANT_DROP_TIGHTENING_INFO, crate::single_char_lifetime_names::SINGLE_CHAR_LIFETIME_NAMES_INFO, crate::single_component_path_imports::SINGLE_COMPONENT_PATH_IMPORTS_INFO, + crate::single_letter_idents::SINGLE_LETTER_IDENTS_INFO, crate::size_of_in_element_count::SIZE_OF_IN_ELEMENT_COUNT_INFO, crate::size_of_ref::SIZE_OF_REF_INFO, crate::slow_vector_initialization::SLOW_VECTOR_INITIALIZATION_INFO, diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index fd10a9302c0..9b8edc5d77e 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -286,6 +286,7 @@ mod shadow; mod significant_drop_tightening; mod single_char_lifetime_names; mod single_component_path_imports; +mod single_letter_idents; mod size_of_in_element_count; mod size_of_ref; mod slow_vector_initialization; @@ -1033,6 +1034,12 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: store.register_late_pass(|_| Box::new(redundant_type_annotations::RedundantTypeAnnotations)); store.register_late_pass(|_| Box::new(arc_with_non_send_sync::ArcWithNonSendSync)); store.register_late_pass(|_| Box::new(needless_if::NeedlessIf)); + let allowed_idents = conf.allowed_idents.clone(); + store.register_early_pass(move || { + Box::new(single_letter_idents::SingleLetterIdents { + allowed_idents: allowed_idents.clone(), + }) + }); // add lints here, do not remove this comment, it's used in `new_lint` } diff --git a/clippy_lints/src/single_letter_idents.rs b/clippy_lints/src/single_letter_idents.rs new file mode 100644 index 00000000000..e957b6fec68 --- /dev/null +++ b/clippy_lints/src/single_letter_idents.rs @@ -0,0 +1,52 @@ +use clippy_utils::{diagnostics::span_lint, source::snippet}; +use itertools::Itertools; +use rustc_data_structures::fx::FxHashSet; +use rustc_lint::{EarlyContext, EarlyLintPass, LintContext}; +use rustc_middle::lint::in_external_macro; +use rustc_session::{declare_tool_lint, impl_lint_pass}; +use rustc_span::symbol::Ident; + +declare_clippy_lint! { + /// ### What it does + /// Checks for idents which comprise of a single letter. + /// + /// Note: This lint can be very noisy when enabled; it even lints generics! it may be desirable + /// to only enable it temporarily. + /// + /// ### Why is this bad? + /// In many cases it's not, but at times it can severely hinder readability. Some codebases may + /// wish to disallow this to improve readability. + /// + /// ### Example + /// ```rust,ignore + /// for i in collection { + /// let x = i.x; + /// } + /// ``` + #[clippy::version = "1.72.0"] + pub SINGLE_LETTER_IDENTS, + restriction, + "disallows idents that can be represented as a char" +} +impl_lint_pass!(SingleLetterIdents => [SINGLE_LETTER_IDENTS]); + +#[derive(Clone)] +pub struct SingleLetterIdents { + pub allowed_idents: FxHashSet, +} + +impl EarlyLintPass for SingleLetterIdents { + fn check_ident(&mut self, cx: &EarlyContext<'_>, ident: Ident) { + let str = ident.name.as_str(); + let chars = str.chars(); + if let [char, rest @ ..] = chars.collect_vec().as_slice() + && rest.is_empty() + && self.allowed_idents.get(char).is_none() + && !in_external_macro(cx.sess(), ident.span) + // Ignore proc macros. Let's implement `WithSearchPat` for early lints someday :) + && snippet(cx, ident.span, str) == str + { + span_lint(cx, SINGLE_LETTER_IDENTS, ident.span, "this ident comprises of a single letter"); + } + } +} diff --git a/clippy_lints/src/utils/conf.rs b/clippy_lints/src/utils/conf.rs index 6962299e468..7b5413647c7 100644 --- a/clippy_lints/src/utils/conf.rs +++ b/clippy_lints/src/utils/conf.rs @@ -34,6 +34,7 @@ const DEFAULT_DOC_VALID_IDENTS: &[&str] = &[ "CamelCase", ]; const DEFAULT_DISALLOWED_NAMES: &[&str] = &["foo", "baz", "quux"]; +const DEFAULT_ALLOWED_IDENTS: &[char] = &['i', 'j', 'x', 'y', 'z', 'n']; /// Holds information used by `MISSING_ENFORCED_IMPORT_RENAMES` lint. #[derive(Clone, Debug, Deserialize)] diff --git a/clippy_utils/src/check_proc_macro.rs b/clippy_utils/src/check_proc_macro.rs index bcfac527c8a..c6d0b654f57 100644 --- a/clippy_utils/src/check_proc_macro.rs +++ b/clippy_utils/src/check_proc_macro.rs @@ -25,7 +25,7 @@ use rustc_hir::{ use rustc_lint::{LateContext, LintContext}; use rustc_middle::ty::TyCtxt; use rustc_session::Session; -use rustc_span::{Span, Symbol}; +use rustc_span::{symbol::Ident, Span, Symbol}; use rustc_target::spec::abi::Abi; /// The search pattern to look for. Used by `span_matches_pat` @@ -344,14 +344,18 @@ fn ty_search_pat(ty: &Ty<'_>) -> (Pat, Pat) { } } -pub trait WithSearchPat { +fn ident_search_pat(ident: Ident) -> (Pat, Pat) { + (Pat::OwnedStr(ident.name.as_str().to_owned()), Pat::Str("")) +} + +pub trait WithSearchPat<'cx> { type Context: LintContext; fn search_pat(&self, cx: &Self::Context) -> (Pat, Pat); fn span(&self) -> Span; } macro_rules! impl_with_search_pat { ($cx:ident: $ty:ident with $fn:ident $(($tcx:ident))?) => { - impl<'cx> WithSearchPat for $ty<'cx> { + impl<'cx> WithSearchPat<'cx> for $ty<'cx> { type Context = $cx<'cx>; #[allow(unused_variables)] fn search_pat(&self, cx: &Self::Context) -> (Pat, Pat) { @@ -372,7 +376,7 @@ impl_with_search_pat!(LateContext: FieldDef with field_def_search_pat); impl_with_search_pat!(LateContext: Variant with variant_search_pat); impl_with_search_pat!(LateContext: Ty with ty_search_pat); -impl<'cx> WithSearchPat for (&FnKind<'cx>, &Body<'cx>, HirId, Span) { +impl<'cx> WithSearchPat<'cx> for (&FnKind<'cx>, &Body<'cx>, HirId, Span) { type Context = LateContext<'cx>; fn search_pat(&self, cx: &Self::Context) -> (Pat, Pat) { @@ -385,7 +389,7 @@ impl<'cx> WithSearchPat for (&FnKind<'cx>, &Body<'cx>, HirId, Span) { } // `Attribute` does not have the `hir` associated lifetime, so we cannot use the macro -impl<'cx> WithSearchPat for &'cx Attribute { +impl<'cx> WithSearchPat<'cx> for &'cx Attribute { type Context = LateContext<'cx>; fn search_pat(&self, _cx: &Self::Context) -> (Pat, Pat) { @@ -397,11 +401,24 @@ impl<'cx> WithSearchPat for &'cx Attribute { } } +// `Ident` does not have the `hir` associated lifetime, so we cannot use the macro +impl<'cx> WithSearchPat<'cx> for Ident { + type Context = LateContext<'cx>; + + fn search_pat(&self, _cx: &Self::Context) -> (Pat, Pat) { + ident_search_pat(*self) + } + + fn span(&self) -> Span { + self.span + } +} + /// Checks if the item likely came from a proc-macro. /// /// This should be called after `in_external_macro` and the initial pattern matching of the ast as /// it is significantly slower than both of those. -pub fn is_from_proc_macro(cx: &T::Context, item: &T) -> bool { +pub fn is_from_proc_macro<'cx, T: WithSearchPat<'cx>>(cx: &T::Context, item: &T) -> bool { let (start_pat, end_pat) = item.search_pat(cx); !span_matches_pat(cx.sess(), item.span(), start_pat, end_pat) } 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 c11835f5696..2bc872e07e8 100644 --- a/tests/ui-toml/toml_unknown_key/conf_unknown_key.stderr +++ b/tests/ui-toml/toml_unknown_key/conf_unknown_key.stderr @@ -5,6 +5,7 @@ error: error reading Clippy's configuration file: unknown field `foobar`, expect allow-print-in-tests allow-private-module-inception allow-unwrap-in-tests + allowed-idents allowed-scripts arithmetic-side-effects-allowed arithmetic-side-effects-allowed-binary @@ -68,6 +69,7 @@ error: error reading Clippy's configuration file: unknown field `barfoo`, expect allow-print-in-tests allow-private-module-inception allow-unwrap-in-tests + allowed-idents allowed-scripts arithmetic-side-effects-allowed arithmetic-side-effects-allowed-binary diff --git a/tests/ui/single_letter_idents.rs b/tests/ui/single_letter_idents.rs new file mode 100644 index 00000000000..b33c569d318 --- /dev/null +++ b/tests/ui/single_letter_idents.rs @@ -0,0 +1,59 @@ +//@aux-build:proc_macros.rs +#![allow(nonstandard_style, unused)] +#![warn(clippy::single_letter_idents)] + +extern crate proc_macros; +use proc_macros::external; +use proc_macros::with_span; + +struct A { + a: u32, + i: u32, + A: u32, + I: u32, +} + +struct B(u32); + +struct i; + +enum C { + D, + E, + F, + j, +} + +struct Vec4 { + x: u32, + y: u32, + z: u32, + w: u32, +} + +struct AA(T, E); + +fn main() { + // Allowed idents + let w = 1; + // Ok, not this one + // let i = 1; + let j = 1; + let n = 1; + let x = 1; + let y = 1; + let z = 1; + + for j in 0..1000 {} + + // Do not lint code from external macros + external! { for j in 0..1000 {} } + // Do not lint code from procedural macros + with_span! { + span + for j in 0..1000 {} + } +} + +fn b() {} +fn owo() {} diff --git a/tests/ui/single_letter_idents.stderr b/tests/ui/single_letter_idents.stderr new file mode 100644 index 00000000000..712c1664235 --- /dev/null +++ b/tests/ui/single_letter_idents.stderr @@ -0,0 +1,100 @@ +error: this ident comprises of a single letter + --> $DIR/single_letter_idents.rs:9:8 + | +LL | struct A { + | ^ + | + = note: `-D clippy::single-letter-idents` implied by `-D warnings` + +error: this ident comprises of a single letter + --> $DIR/single_letter_idents.rs:10:5 + | +LL | a: u32, + | ^ + +error: this ident comprises of a single letter + --> $DIR/single_letter_idents.rs:12:5 + | +LL | A: u32, + | ^ + +error: this ident comprises of a single letter + --> $DIR/single_letter_idents.rs:13:5 + | +LL | I: u32, + | ^ + +error: this ident comprises of a single letter + --> $DIR/single_letter_idents.rs:16:8 + | +LL | struct B(u32); + | ^ + +error: this ident comprises of a single letter + --> $DIR/single_letter_idents.rs:20:6 + | +LL | enum C { + | ^ + +error: this ident comprises of a single letter + --> $DIR/single_letter_idents.rs:21:5 + | +LL | D, + | ^ + +error: this ident comprises of a single letter + --> $DIR/single_letter_idents.rs:22:5 + | +LL | E, + | ^ + +error: this ident comprises of a single letter + --> $DIR/single_letter_idents.rs:23:5 + | +LL | F, + | ^ + +error: this ident comprises of a single letter + --> $DIR/single_letter_idents.rs:31:5 + | +LL | w: u32, + | ^ + +error: this ident comprises of a single letter + --> $DIR/single_letter_idents.rs:34:11 + | +LL | struct AA(T, E); + | ^ + +error: this ident comprises of a single letter + --> $DIR/single_letter_idents.rs:34:14 + | +LL | struct AA(T, E); + | ^ + +error: this ident comprises of a single letter + --> $DIR/single_letter_idents.rs:34:17 + | +LL | struct AA(T, E); + | ^ + +error: this ident comprises of a single letter + --> $DIR/single_letter_idents.rs:34:20 + | +LL | struct AA(T, E); + | ^ + +error: this ident comprises of a single letter + --> $DIR/single_letter_idents.rs:38:9 + | +LL | let w = 1; + | ^ + +error: this ident comprises of a single letter + --> $DIR/single_letter_idents.rs:58:4 + | +LL | fn b() {} + | ^ + +error: aborting due to 16 previous errors + From e2ecb132a5ccf238129acdbaff89bed6023a593e Mon Sep 17 00:00:00 2001 From: Centri3 <114838443+Centri3@users.noreply.github.com> Date: Fri, 9 Jun 2023 14:29:34 -0500 Subject: [PATCH 139/310] rename the lint --- CHANGELOG.md | 2 +- clippy_lints/src/declared_lints.rs | 2 +- clippy_lints/src/lib.rs | 4 ++-- ...single_letter_idents.rs => single_char_idents.rs} | 12 ++++++------ 4 files changed, 10 insertions(+), 10 deletions(-) rename clippy_lints/src/{single_letter_idents.rs => single_char_idents.rs} (81%) diff --git a/CHANGELOG.md b/CHANGELOG.md index 5a03d768fee..27a5fc06b07 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5155,12 +5155,12 @@ Released 2018-09-13 [`significant_drop_tightening`]: https://rust-lang.github.io/rust-clippy/master/index.html#significant_drop_tightening [`similar_names`]: https://rust-lang.github.io/rust-clippy/master/index.html#similar_names [`single_char_add_str`]: https://rust-lang.github.io/rust-clippy/master/index.html#single_char_add_str +[`single_char_idents`]: https://rust-lang.github.io/rust-clippy/master/index.html#single_char_idents [`single_char_lifetime_names`]: https://rust-lang.github.io/rust-clippy/master/index.html#single_char_lifetime_names [`single_char_pattern`]: https://rust-lang.github.io/rust-clippy/master/index.html#single_char_pattern [`single_char_push_str`]: https://rust-lang.github.io/rust-clippy/master/index.html#single_char_push_str [`single_component_path_imports`]: https://rust-lang.github.io/rust-clippy/master/index.html#single_component_path_imports [`single_element_loop`]: https://rust-lang.github.io/rust-clippy/master/index.html#single_element_loop -[`single_letter_idents`]: https://rust-lang.github.io/rust-clippy/master/index.html#single_letter_idents [`single_match`]: https://rust-lang.github.io/rust-clippy/master/index.html#single_match [`single_match_else`]: https://rust-lang.github.io/rust-clippy/master/index.html#single_match_else [`size_of_in_element_count`]: https://rust-lang.github.io/rust-clippy/master/index.html#size_of_in_element_count diff --git a/clippy_lints/src/declared_lints.rs b/clippy_lints/src/declared_lints.rs index 03c3e153a97..1c494468226 100644 --- a/clippy_lints/src/declared_lints.rs +++ b/clippy_lints/src/declared_lints.rs @@ -565,9 +565,9 @@ pub(crate) static LINTS: &[&crate::LintInfo] = &[ crate::shadow::SHADOW_SAME_INFO, crate::shadow::SHADOW_UNRELATED_INFO, crate::significant_drop_tightening::SIGNIFICANT_DROP_TIGHTENING_INFO, + crate::single_char_idents::SINGLE_CHAR_IDENTS_INFO, crate::single_char_lifetime_names::SINGLE_CHAR_LIFETIME_NAMES_INFO, crate::single_component_path_imports::SINGLE_COMPONENT_PATH_IMPORTS_INFO, - crate::single_letter_idents::SINGLE_LETTER_IDENTS_INFO, crate::size_of_in_element_count::SIZE_OF_IN_ELEMENT_COUNT_INFO, crate::size_of_ref::SIZE_OF_REF_INFO, crate::slow_vector_initialization::SLOW_VECTOR_INITIALIZATION_INFO, diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index 9b8edc5d77e..463e4a429d1 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -284,9 +284,9 @@ mod semicolon_if_nothing_returned; mod serde_api; mod shadow; mod significant_drop_tightening; +mod single_char_idents; mod single_char_lifetime_names; mod single_component_path_imports; -mod single_letter_idents; mod size_of_in_element_count; mod size_of_ref; mod slow_vector_initialization; @@ -1036,7 +1036,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: store.register_late_pass(|_| Box::new(needless_if::NeedlessIf)); let allowed_idents = conf.allowed_idents.clone(); store.register_early_pass(move || { - Box::new(single_letter_idents::SingleLetterIdents { + Box::new(single_char_idents::SingleCharIdents { allowed_idents: allowed_idents.clone(), }) }); diff --git a/clippy_lints/src/single_letter_idents.rs b/clippy_lints/src/single_char_idents.rs similarity index 81% rename from clippy_lints/src/single_letter_idents.rs rename to clippy_lints/src/single_char_idents.rs index e957b6fec68..0125b576f43 100644 --- a/clippy_lints/src/single_letter_idents.rs +++ b/clippy_lints/src/single_char_idents.rs @@ -24,29 +24,29 @@ declare_clippy_lint! { /// } /// ``` #[clippy::version = "1.72.0"] - pub SINGLE_LETTER_IDENTS, + pub SINGLE_CHAR_IDENTS, restriction, "disallows idents that can be represented as a char" } -impl_lint_pass!(SingleLetterIdents => [SINGLE_LETTER_IDENTS]); +impl_lint_pass!(SingleCharIdents => [SINGLE_CHAR_IDENTS]); #[derive(Clone)] -pub struct SingleLetterIdents { +pub struct SingleCharIdents { pub allowed_idents: FxHashSet, } -impl EarlyLintPass for SingleLetterIdents { +impl EarlyLintPass for SingleCharIdents { fn check_ident(&mut self, cx: &EarlyContext<'_>, ident: Ident) { let str = ident.name.as_str(); let chars = str.chars(); - if let [char, rest @ ..] = chars.collect_vec().as_slice() + if let [char, rest @ ..] = &*chars.collect_vec() && rest.is_empty() && self.allowed_idents.get(char).is_none() && !in_external_macro(cx.sess(), ident.span) // Ignore proc macros. Let's implement `WithSearchPat` for early lints someday :) && snippet(cx, ident.span, str) == str { - span_lint(cx, SINGLE_LETTER_IDENTS, ident.span, "this ident comprises of a single letter"); + span_lint(cx, SINGLE_CHAR_IDENTS, ident.span, "this ident comprises of a single char"); } } } From 03c8db048e97835c3431eac5da90e207b0a458f6 Mon Sep 17 00:00:00 2001 From: Centri3 <114838443+Centri3@users.noreply.github.com> Date: Fri, 9 Jun 2023 14:45:53 -0500 Subject: [PATCH 140/310] make cargo test pass + example --- clippy_lints/src/single_char_idents.rs | 11 +- ...letter_idents.rs => single_char_idents.rs} | 2 +- tests/ui/single_char_idents.stderr | 100 ++++++++++++++++++ tests/ui/single_letter_idents.stderr | 100 ------------------ 4 files changed, 110 insertions(+), 103 deletions(-) rename tests/ui/{single_letter_idents.rs => single_char_idents.rs} (95%) create mode 100644 tests/ui/single_char_idents.stderr delete mode 100644 tests/ui/single_letter_idents.stderr diff --git a/clippy_lints/src/single_char_idents.rs b/clippy_lints/src/single_char_idents.rs index 0125b576f43..17a2ebe93ed 100644 --- a/clippy_lints/src/single_char_idents.rs +++ b/clippy_lints/src/single_char_idents.rs @@ -19,10 +19,17 @@ declare_clippy_lint! { /// /// ### Example /// ```rust,ignore - /// for i in collection { - /// let x = i.x; + /// for m in movies { + /// let title = m.t; /// } /// ``` + /// Use instead: + /// ```rust,ignore + /// for movie in movies { + /// let title = movie.title; + /// } + /// ``` + /// ``` #[clippy::version = "1.72.0"] pub SINGLE_CHAR_IDENTS, restriction, diff --git a/tests/ui/single_letter_idents.rs b/tests/ui/single_char_idents.rs similarity index 95% rename from tests/ui/single_letter_idents.rs rename to tests/ui/single_char_idents.rs index b33c569d318..386633161fe 100644 --- a/tests/ui/single_letter_idents.rs +++ b/tests/ui/single_char_idents.rs @@ -1,6 +1,6 @@ //@aux-build:proc_macros.rs #![allow(nonstandard_style, unused)] -#![warn(clippy::single_letter_idents)] +#![warn(clippy::single_char_idents)] extern crate proc_macros; use proc_macros::external; diff --git a/tests/ui/single_char_idents.stderr b/tests/ui/single_char_idents.stderr new file mode 100644 index 00000000000..ceedab9c0da --- /dev/null +++ b/tests/ui/single_char_idents.stderr @@ -0,0 +1,100 @@ +error: this ident comprises of a single char + --> $DIR/single_char_idents.rs:9:8 + | +LL | struct A { + | ^ + | + = note: `-D clippy::single-char-idents` implied by `-D warnings` + +error: this ident comprises of a single char + --> $DIR/single_char_idents.rs:10:5 + | +LL | a: u32, + | ^ + +error: this ident comprises of a single char + --> $DIR/single_char_idents.rs:12:5 + | +LL | A: u32, + | ^ + +error: this ident comprises of a single char + --> $DIR/single_char_idents.rs:13:5 + | +LL | I: u32, + | ^ + +error: this ident comprises of a single char + --> $DIR/single_char_idents.rs:16:8 + | +LL | struct B(u32); + | ^ + +error: this ident comprises of a single char + --> $DIR/single_char_idents.rs:20:6 + | +LL | enum C { + | ^ + +error: this ident comprises of a single char + --> $DIR/single_char_idents.rs:21:5 + | +LL | D, + | ^ + +error: this ident comprises of a single char + --> $DIR/single_char_idents.rs:22:5 + | +LL | E, + | ^ + +error: this ident comprises of a single char + --> $DIR/single_char_idents.rs:23:5 + | +LL | F, + | ^ + +error: this ident comprises of a single char + --> $DIR/single_char_idents.rs:31:5 + | +LL | w: u32, + | ^ + +error: this ident comprises of a single char + --> $DIR/single_char_idents.rs:34:11 + | +LL | struct AA(T, E); + | ^ + +error: this ident comprises of a single char + --> $DIR/single_char_idents.rs:34:14 + | +LL | struct AA(T, E); + | ^ + +error: this ident comprises of a single char + --> $DIR/single_char_idents.rs:34:17 + | +LL | struct AA(T, E); + | ^ + +error: this ident comprises of a single char + --> $DIR/single_char_idents.rs:34:20 + | +LL | struct AA(T, E); + | ^ + +error: this ident comprises of a single char + --> $DIR/single_char_idents.rs:38:9 + | +LL | let w = 1; + | ^ + +error: this ident comprises of a single char + --> $DIR/single_char_idents.rs:58:4 + | +LL | fn b() {} + | ^ + +error: aborting due to 16 previous errors + diff --git a/tests/ui/single_letter_idents.stderr b/tests/ui/single_letter_idents.stderr deleted file mode 100644 index 712c1664235..00000000000 --- a/tests/ui/single_letter_idents.stderr +++ /dev/null @@ -1,100 +0,0 @@ -error: this ident comprises of a single letter - --> $DIR/single_letter_idents.rs:9:8 - | -LL | struct A { - | ^ - | - = note: `-D clippy::single-letter-idents` implied by `-D warnings` - -error: this ident comprises of a single letter - --> $DIR/single_letter_idents.rs:10:5 - | -LL | a: u32, - | ^ - -error: this ident comprises of a single letter - --> $DIR/single_letter_idents.rs:12:5 - | -LL | A: u32, - | ^ - -error: this ident comprises of a single letter - --> $DIR/single_letter_idents.rs:13:5 - | -LL | I: u32, - | ^ - -error: this ident comprises of a single letter - --> $DIR/single_letter_idents.rs:16:8 - | -LL | struct B(u32); - | ^ - -error: this ident comprises of a single letter - --> $DIR/single_letter_idents.rs:20:6 - | -LL | enum C { - | ^ - -error: this ident comprises of a single letter - --> $DIR/single_letter_idents.rs:21:5 - | -LL | D, - | ^ - -error: this ident comprises of a single letter - --> $DIR/single_letter_idents.rs:22:5 - | -LL | E, - | ^ - -error: this ident comprises of a single letter - --> $DIR/single_letter_idents.rs:23:5 - | -LL | F, - | ^ - -error: this ident comprises of a single letter - --> $DIR/single_letter_idents.rs:31:5 - | -LL | w: u32, - | ^ - -error: this ident comprises of a single letter - --> $DIR/single_letter_idents.rs:34:11 - | -LL | struct AA(T, E); - | ^ - -error: this ident comprises of a single letter - --> $DIR/single_letter_idents.rs:34:14 - | -LL | struct AA(T, E); - | ^ - -error: this ident comprises of a single letter - --> $DIR/single_letter_idents.rs:34:17 - | -LL | struct AA(T, E); - | ^ - -error: this ident comprises of a single letter - --> $DIR/single_letter_idents.rs:34:20 - | -LL | struct AA(T, E); - | ^ - -error: this ident comprises of a single letter - --> $DIR/single_letter_idents.rs:38:9 - | -LL | let w = 1; - | ^ - -error: this ident comprises of a single letter - --> $DIR/single_letter_idents.rs:58:4 - | -LL | fn b() {} - | ^ - -error: aborting due to 16 previous errors - From 7cdd87ca4afe3ab7a1a8eb1544db132678335f87 Mon Sep 17 00:00:00 2001 From: Centri3 <114838443+Centri3@users.noreply.github.com> Date: Fri, 9 Jun 2023 17:49:35 -0500 Subject: [PATCH 141/310] ignore generics and allow arbitrary threshold --- CHANGELOG.md | 2 +- clippy_lints/src/declared_lints.rs | 2 +- clippy_lints/src/lib.rs | 12 +- clippy_lints/src/min_ident_chars.rs | 133 ++++++++++++++++++ clippy_lints/src/single_char_idents.rs | 59 -------- clippy_lints/src/utils/conf.rs | 11 +- .../min_ident_chars/auxiliary/extern_types.rs | 3 + tests/ui-toml/min_ident_chars/clippy.toml | 2 + .../min_ident_chars/min_ident_chars.rs | 17 +++ .../min_ident_chars/min_ident_chars.stderr | 16 +++ .../toml_unknown_key/conf_unknown_key.stderr | 6 +- ...ngle_char_idents.rs => min_ident_chars.rs} | 12 +- tests/ui/min_ident_chars.stderr | 70 +++++++++ tests/ui/single_char_idents.stderr | 100 ------------- 14 files changed, 270 insertions(+), 175 deletions(-) create mode 100644 clippy_lints/src/min_ident_chars.rs delete mode 100644 clippy_lints/src/single_char_idents.rs create mode 100644 tests/ui-toml/min_ident_chars/auxiliary/extern_types.rs create mode 100644 tests/ui-toml/min_ident_chars/clippy.toml create mode 100644 tests/ui-toml/min_ident_chars/min_ident_chars.rs create mode 100644 tests/ui-toml/min_ident_chars/min_ident_chars.stderr rename tests/ui/{single_char_idents.rs => min_ident_chars.rs} (86%) create mode 100644 tests/ui/min_ident_chars.stderr delete mode 100644 tests/ui/single_char_idents.stderr diff --git a/CHANGELOG.md b/CHANGELOG.md index 27a5fc06b07..2d62bfd4f99 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4958,6 +4958,7 @@ Released 2018-09-13 [`mem_replace_option_with_none`]: https://rust-lang.github.io/rust-clippy/master/index.html#mem_replace_option_with_none [`mem_replace_with_default`]: https://rust-lang.github.io/rust-clippy/master/index.html#mem_replace_with_default [`mem_replace_with_uninit`]: https://rust-lang.github.io/rust-clippy/master/index.html#mem_replace_with_uninit +[`min_ident_chars`]: https://rust-lang.github.io/rust-clippy/master/index.html#min_ident_chars [`min_max`]: https://rust-lang.github.io/rust-clippy/master/index.html#min_max [`misaligned_transmute`]: https://rust-lang.github.io/rust-clippy/master/index.html#misaligned_transmute [`mismatched_target_os`]: https://rust-lang.github.io/rust-clippy/master/index.html#mismatched_target_os @@ -5155,7 +5156,6 @@ Released 2018-09-13 [`significant_drop_tightening`]: https://rust-lang.github.io/rust-clippy/master/index.html#significant_drop_tightening [`similar_names`]: https://rust-lang.github.io/rust-clippy/master/index.html#similar_names [`single_char_add_str`]: https://rust-lang.github.io/rust-clippy/master/index.html#single_char_add_str -[`single_char_idents`]: https://rust-lang.github.io/rust-clippy/master/index.html#single_char_idents [`single_char_lifetime_names`]: https://rust-lang.github.io/rust-clippy/master/index.html#single_char_lifetime_names [`single_char_pattern`]: https://rust-lang.github.io/rust-clippy/master/index.html#single_char_pattern [`single_char_push_str`]: https://rust-lang.github.io/rust-clippy/master/index.html#single_char_push_str diff --git a/clippy_lints/src/declared_lints.rs b/clippy_lints/src/declared_lints.rs index 1c494468226..769774b27c4 100644 --- a/clippy_lints/src/declared_lints.rs +++ b/clippy_lints/src/declared_lints.rs @@ -416,6 +416,7 @@ pub(crate) static LINTS: &[&crate::LintInfo] = &[ crate::methods::VERBOSE_FILE_READS_INFO, crate::methods::WRONG_SELF_CONVENTION_INFO, crate::methods::ZST_OFFSET_INFO, + crate::min_ident_chars::MIN_IDENT_CHARS_INFO, crate::minmax::MIN_MAX_INFO, crate::misc::SHORT_CIRCUIT_STATEMENT_INFO, crate::misc::TOPLEVEL_REF_ARG_INFO, @@ -565,7 +566,6 @@ pub(crate) static LINTS: &[&crate::LintInfo] = &[ crate::shadow::SHADOW_SAME_INFO, crate::shadow::SHADOW_UNRELATED_INFO, crate::significant_drop_tightening::SIGNIFICANT_DROP_TIGHTENING_INFO, - crate::single_char_idents::SINGLE_CHAR_IDENTS_INFO, crate::single_char_lifetime_names::SINGLE_CHAR_LIFETIME_NAMES_INFO, crate::single_component_path_imports::SINGLE_COMPONENT_PATH_IMPORTS_INFO, crate::size_of_in_element_count::SIZE_OF_IN_ELEMENT_COUNT_INFO, diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index 463e4a429d1..dcf1c6f64a4 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -197,6 +197,7 @@ mod matches; mod mem_forget; mod mem_replace; mod methods; +mod min_ident_chars; mod minmax; mod misc; mod misc_early; @@ -284,7 +285,6 @@ mod semicolon_if_nothing_returned; mod serde_api; mod shadow; mod significant_drop_tightening; -mod single_char_idents; mod single_char_lifetime_names; mod single_component_path_imports; mod size_of_in_element_count; @@ -1034,10 +1034,12 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: store.register_late_pass(|_| Box::new(redundant_type_annotations::RedundantTypeAnnotations)); store.register_late_pass(|_| Box::new(arc_with_non_send_sync::ArcWithNonSendSync)); store.register_late_pass(|_| Box::new(needless_if::NeedlessIf)); - let allowed_idents = conf.allowed_idents.clone(); - store.register_early_pass(move || { - Box::new(single_char_idents::SingleCharIdents { - allowed_idents: allowed_idents.clone(), + let allowed_idents_below_min_chars = conf.allowed_idents_below_min_chars.clone(); + let min_ident_chars_threshold = conf.min_ident_chars_threshold; + store.register_late_pass(move |_| { + Box::new(min_ident_chars::MinIdentChars { + allowed_idents_below_min_chars: allowed_idents_below_min_chars.clone(), + min_ident_chars_threshold, }) }); // add lints here, do not remove this comment, it's used in `new_lint` diff --git a/clippy_lints/src/min_ident_chars.rs b/clippy_lints/src/min_ident_chars.rs new file mode 100644 index 00000000000..bbe7fc540e9 --- /dev/null +++ b/clippy_lints/src/min_ident_chars.rs @@ -0,0 +1,133 @@ +use clippy_utils::{diagnostics::span_lint, is_from_proc_macro}; +use rustc_data_structures::fx::FxHashSet; +use rustc_hir::{ + def::{DefKind, Res}, + intravisit::{walk_item, Visitor}, + GenericParamKind, HirId, Item, ItemKind, ItemLocalId, Node, +}; +use rustc_lint::{LateContext, LateLintPass, LintContext}; +use rustc_middle::lint::in_external_macro; +use rustc_session::{declare_tool_lint, impl_lint_pass}; +use std::borrow::Cow; + +declare_clippy_lint! { + /// ### What it does + /// Checks for idents which comprise of a single letter. + /// + /// Note: This lint can be very noisy when enabled; it may be desirable to only enable it + /// temporarily. + /// + /// ### Why is this bad? + /// In many cases it's not, but at times it can severely hinder readability. Some codebases may + /// wish to disallow this to improve readability. + /// + /// ### Example + /// ```rust,ignore + /// for m in movies { + /// let title = m.t; + /// } + /// ``` + /// Use instead: + /// ```rust,ignore + /// for movie in movies { + /// let title = movie.title; + /// } + /// ``` + /// ``` + #[clippy::version = "1.72.0"] + pub MIN_IDENT_CHARS, + restriction, + "disallows idents that are too short" +} +impl_lint_pass!(MinIdentChars => [MIN_IDENT_CHARS]); + +#[derive(Clone)] +pub struct MinIdentChars { + pub allowed_idents_below_min_chars: FxHashSet, + pub min_ident_chars_threshold: u64, +} + +impl LateLintPass<'_> for MinIdentChars { + fn check_item(&mut self, cx: &LateContext<'_>, item: &Item<'_>) { + if self.min_ident_chars_threshold == 0 { + return; + } + + walk_item(&mut IdentVisitor { conf: self, cx }, item); + } +} + +struct IdentVisitor<'cx, 'tcx> { + conf: &'cx MinIdentChars, + cx: &'cx LateContext<'tcx>, +} + +#[expect(clippy::cast_possible_truncation)] +impl Visitor<'_> for IdentVisitor<'_, '_> { + fn visit_id(&mut self, hir_id: HirId) { + let Self { conf, cx } = *self; + // Reimplementation of `find`, as it uses indexing, which can (and will in async functions) panic. + // This should probably be fixed on the rustc side, this is just a temporary workaround. + // FIXME: Remove me if/when this is fixed in rustc + let node = if hir_id.local_id == ItemLocalId::from_u32(0) { + // In this case, we can just use `find`, `Owner`'s `node` field is private anyway so we can't + // reimplement it even if we wanted to + cx.tcx.hir().find(hir_id) + } else { + let Some(owner) = cx.tcx.hir_owner_nodes(hir_id.owner).as_owner() else { + return; + }; + owner.nodes.get(hir_id.local_id).copied().flatten().map(|p| p.node) + }; + let Some(node) = node else { + return; + }; + let Some(ident) = node.ident() else { + return; + }; + + let str = ident.as_str(); + if !in_external_macro(cx.sess(), ident.span) + && str.len() <= conf.min_ident_chars_threshold as usize + && !str.is_empty() + && conf.allowed_idents_below_min_chars.get(&str.to_owned()).is_none() + { + if let Node::Item(item) = node && let ItemKind::Use(..) = item.kind { + return; + } + // `struct Awa(T)` + // ^ + if let Node::PathSegment(path) = node { + if let Res::Def(def_kind, ..) = path.res && let DefKind::TyParam = def_kind { + return; + } + if matches!(path.res, Res::PrimTy(..)) || path.res.opt_def_id().is_some_and(|def_id| !def_id.is_local()) + { + return; + } + } + // `struct Awa(T)` + // ^ + if let Node::GenericParam(generic_param) = node + && let GenericParamKind::Type { .. } = generic_param.kind + { + return; + } + + if is_from_proc_macro(cx, &ident) { + return; + } + + let help = if conf.min_ident_chars_threshold == 1 { + Cow::Borrowed("this ident consists of a single char") + } else { + Cow::Owned(format!( + "this ident is too short ({} <= {}) ", + str.len(), + conf.min_ident_chars_threshold + )) + }; + span_lint(cx, MIN_IDENT_CHARS, ident.span, &help); + } + } +} diff --git a/clippy_lints/src/single_char_idents.rs b/clippy_lints/src/single_char_idents.rs deleted file mode 100644 index 17a2ebe93ed..00000000000 --- a/clippy_lints/src/single_char_idents.rs +++ /dev/null @@ -1,59 +0,0 @@ -use clippy_utils::{diagnostics::span_lint, source::snippet}; -use itertools::Itertools; -use rustc_data_structures::fx::FxHashSet; -use rustc_lint::{EarlyContext, EarlyLintPass, LintContext}; -use rustc_middle::lint::in_external_macro; -use rustc_session::{declare_tool_lint, impl_lint_pass}; -use rustc_span::symbol::Ident; - -declare_clippy_lint! { - /// ### What it does - /// Checks for idents which comprise of a single letter. - /// - /// Note: This lint can be very noisy when enabled; it even lints generics! it may be desirable - /// to only enable it temporarily. - /// - /// ### Why is this bad? - /// In many cases it's not, but at times it can severely hinder readability. Some codebases may - /// wish to disallow this to improve readability. - /// - /// ### Example - /// ```rust,ignore - /// for m in movies { - /// let title = m.t; - /// } - /// ``` - /// Use instead: - /// ```rust,ignore - /// for movie in movies { - /// let title = movie.title; - /// } - /// ``` - /// ``` - #[clippy::version = "1.72.0"] - pub SINGLE_CHAR_IDENTS, - restriction, - "disallows idents that can be represented as a char" -} -impl_lint_pass!(SingleCharIdents => [SINGLE_CHAR_IDENTS]); - -#[derive(Clone)] -pub struct SingleCharIdents { - pub allowed_idents: FxHashSet, -} - -impl EarlyLintPass for SingleCharIdents { - fn check_ident(&mut self, cx: &EarlyContext<'_>, ident: Ident) { - let str = ident.name.as_str(); - let chars = str.chars(); - if let [char, rest @ ..] = &*chars.collect_vec() - && rest.is_empty() - && self.allowed_idents.get(char).is_none() - && !in_external_macro(cx.sess(), ident.span) - // Ignore proc macros. Let's implement `WithSearchPat` for early lints someday :) - && snippet(cx, ident.span, str) == str - { - span_lint(cx, SINGLE_CHAR_IDENTS, ident.span, "this ident comprises of a single char"); - } - } -} diff --git a/clippy_lints/src/utils/conf.rs b/clippy_lints/src/utils/conf.rs index 7b5413647c7..c84d8d8d1f0 100644 --- a/clippy_lints/src/utils/conf.rs +++ b/clippy_lints/src/utils/conf.rs @@ -34,7 +34,7 @@ const DEFAULT_DOC_VALID_IDENTS: &[&str] = &[ "CamelCase", ]; const DEFAULT_DISALLOWED_NAMES: &[&str] = &["foo", "baz", "quux"]; -const DEFAULT_ALLOWED_IDENTS: &[char] = &['i', 'j', 'x', 'y', 'z', 'n']; +const DEFAULT_ALLOWED_IDENTS_BELOW_MIN_CHARS: &[&str] = &["i", "j", "x", "y", "z", "n"]; /// Holds information used by `MISSING_ENFORCED_IMPORT_RENAMES` lint. #[derive(Clone, Debug, Deserialize)] @@ -523,6 +523,15 @@ define_Conf! { /// /// Whether to allow module inception if it's not public. (allow_private_module_inception: bool = false), + /// Lint: MIN_IDENT_CHARS. + /// + /// Allowed names below the minimum allowed characters. + (allowed_idents_below_min_chars: rustc_data_structures::fx::FxHashSet = + super::DEFAULT_ALLOWED_IDENTS_BELOW_MIN_CHARS.iter().map(ToString::to_string).collect()), + /// Lint: MIN_IDENT_CHARS. + /// + /// Minimum chars an ident can have, anything below or equal to this will be linted. + (min_ident_chars_threshold: u64 = 1), } /// Search for the configuration file. diff --git a/tests/ui-toml/min_ident_chars/auxiliary/extern_types.rs b/tests/ui-toml/min_ident_chars/auxiliary/extern_types.rs new file mode 100644 index 00000000000..06a144f2218 --- /dev/null +++ b/tests/ui-toml/min_ident_chars/auxiliary/extern_types.rs @@ -0,0 +1,3 @@ +#![allow(nonstandard_style, unused)] + +pub struct Aaa; diff --git a/tests/ui-toml/min_ident_chars/clippy.toml b/tests/ui-toml/min_ident_chars/clippy.toml new file mode 100644 index 00000000000..0114ca75014 --- /dev/null +++ b/tests/ui-toml/min_ident_chars/clippy.toml @@ -0,0 +1,2 @@ +allowed-idents-below-min-chars = ["Owo", "Uwu", "wha", "t_e", "lse", "_do", "_i_", "put", "her", "_e"] +min-ident-chars-threshold = 3 diff --git a/tests/ui-toml/min_ident_chars/min_ident_chars.rs b/tests/ui-toml/min_ident_chars/min_ident_chars.rs new file mode 100644 index 00000000000..33100119ca5 --- /dev/null +++ b/tests/ui-toml/min_ident_chars/min_ident_chars.rs @@ -0,0 +1,17 @@ +//@aux-build:extern_types.rs +#![allow(nonstandard_style, unused)] +#![warn(clippy::min_ident_chars)] + +extern crate extern_types; +use extern_types::Aaa; + +struct Owo { + Uwu: u128, + aaa: Aaa, +} + +fn main() { + let wha = 1; + let vvv = 1; + let uuu = 1; +} diff --git a/tests/ui-toml/min_ident_chars/min_ident_chars.stderr b/tests/ui-toml/min_ident_chars/min_ident_chars.stderr new file mode 100644 index 00000000000..541f5b10051 --- /dev/null +++ b/tests/ui-toml/min_ident_chars/min_ident_chars.stderr @@ -0,0 +1,16 @@ +error: this ident is too short (3 <= 3) + --> $DIR/min_ident_chars.rs:6:19 + | +LL | use extern_types::Aaa; + | ^^^ + | + = note: `-D clippy::min-ident-chars` implied by `-D warnings` + +error: this ident is too short (3 <= 3) + --> $DIR/min_ident_chars.rs:10:5 + | +LL | aaa: Aaa, + | ^^^ + +error: aborting due to 2 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 2bc872e07e8..c546d95eb46 100644 --- a/tests/ui-toml/toml_unknown_key/conf_unknown_key.stderr +++ b/tests/ui-toml/toml_unknown_key/conf_unknown_key.stderr @@ -5,7 +5,7 @@ error: error reading Clippy's configuration file: unknown field `foobar`, expect allow-print-in-tests allow-private-module-inception allow-unwrap-in-tests - allowed-idents + allowed-idents-below-min-chars allowed-scripts arithmetic-side-effects-allowed arithmetic-side-effects-allowed-binary @@ -37,6 +37,7 @@ error: error reading Clippy's configuration file: unknown field `foobar`, expect max-struct-bools max-suggested-slice-pattern-length max-trait-bounds + min-ident-chars-threshold missing-docs-in-crate-items msrv pass-by-value-size-limit @@ -69,7 +70,7 @@ error: error reading Clippy's configuration file: unknown field `barfoo`, expect allow-print-in-tests allow-private-module-inception allow-unwrap-in-tests - allowed-idents + allowed-idents-below-min-chars allowed-scripts arithmetic-side-effects-allowed arithmetic-side-effects-allowed-binary @@ -101,6 +102,7 @@ error: error reading Clippy's configuration file: unknown field `barfoo`, expect max-struct-bools max-suggested-slice-pattern-length max-trait-bounds + min-ident-chars-threshold missing-docs-in-crate-items msrv pass-by-value-size-limit diff --git a/tests/ui/single_char_idents.rs b/tests/ui/min_ident_chars.rs similarity index 86% rename from tests/ui/single_char_idents.rs rename to tests/ui/min_ident_chars.rs index 386633161fe..134c17c553f 100644 --- a/tests/ui/single_char_idents.rs +++ b/tests/ui/min_ident_chars.rs @@ -1,6 +1,6 @@ //@aux-build:proc_macros.rs #![allow(nonstandard_style, unused)] -#![warn(clippy::single_char_idents)] +#![warn(clippy::min_ident_chars)] extern crate proc_macros; use proc_macros::external; @@ -38,11 +38,11 @@ fn main() { let w = 1; // Ok, not this one // let i = 1; - let j = 1; - let n = 1; - let x = 1; - let y = 1; - let z = 1; + let jz = 1; + let nz = 1; + let zx = 1; + let yz = 1; + let zz = 1; for j in 0..1000 {} diff --git a/tests/ui/min_ident_chars.stderr b/tests/ui/min_ident_chars.stderr new file mode 100644 index 00000000000..4b887617058 --- /dev/null +++ b/tests/ui/min_ident_chars.stderr @@ -0,0 +1,70 @@ +error: this ident consists of a single char + --> $DIR/min_ident_chars.rs:9:8 + | +LL | struct A { + | ^ + | + = note: `-D clippy::min-ident-chars` implied by `-D warnings` + +error: this ident consists of a single char + --> $DIR/min_ident_chars.rs:10:5 + | +LL | a: u32, + | ^ + +error: this ident consists of a single char + --> $DIR/min_ident_chars.rs:12:5 + | +LL | A: u32, + | ^ + +error: this ident consists of a single char + --> $DIR/min_ident_chars.rs:13:5 + | +LL | I: u32, + | ^ + +error: this ident consists of a single char + --> $DIR/min_ident_chars.rs:16:8 + | +LL | struct B(u32); + | ^ + +error: this ident consists of a single char + --> $DIR/min_ident_chars.rs:20:6 + | +LL | enum C { + | ^ + +error: this ident consists of a single char + --> $DIR/min_ident_chars.rs:21:5 + | +LL | D, + | ^ + +error: this ident consists of a single char + --> $DIR/min_ident_chars.rs:22:5 + | +LL | E, + | ^ + +error: this ident consists of a single char + --> $DIR/min_ident_chars.rs:23:5 + | +LL | F, + | ^ + +error: this ident consists of a single char + --> $DIR/min_ident_chars.rs:31:5 + | +LL | w: u32, + | ^ + +error: this ident consists of a single char + --> $DIR/min_ident_chars.rs:58:4 + | +LL | fn b() {} + | ^ + +error: aborting due to 11 previous errors + diff --git a/tests/ui/single_char_idents.stderr b/tests/ui/single_char_idents.stderr deleted file mode 100644 index ceedab9c0da..00000000000 --- a/tests/ui/single_char_idents.stderr +++ /dev/null @@ -1,100 +0,0 @@ -error: this ident comprises of a single char - --> $DIR/single_char_idents.rs:9:8 - | -LL | struct A { - | ^ - | - = note: `-D clippy::single-char-idents` implied by `-D warnings` - -error: this ident comprises of a single char - --> $DIR/single_char_idents.rs:10:5 - | -LL | a: u32, - | ^ - -error: this ident comprises of a single char - --> $DIR/single_char_idents.rs:12:5 - | -LL | A: u32, - | ^ - -error: this ident comprises of a single char - --> $DIR/single_char_idents.rs:13:5 - | -LL | I: u32, - | ^ - -error: this ident comprises of a single char - --> $DIR/single_char_idents.rs:16:8 - | -LL | struct B(u32); - | ^ - -error: this ident comprises of a single char - --> $DIR/single_char_idents.rs:20:6 - | -LL | enum C { - | ^ - -error: this ident comprises of a single char - --> $DIR/single_char_idents.rs:21:5 - | -LL | D, - | ^ - -error: this ident comprises of a single char - --> $DIR/single_char_idents.rs:22:5 - | -LL | E, - | ^ - -error: this ident comprises of a single char - --> $DIR/single_char_idents.rs:23:5 - | -LL | F, - | ^ - -error: this ident comprises of a single char - --> $DIR/single_char_idents.rs:31:5 - | -LL | w: u32, - | ^ - -error: this ident comprises of a single char - --> $DIR/single_char_idents.rs:34:11 - | -LL | struct AA(T, E); - | ^ - -error: this ident comprises of a single char - --> $DIR/single_char_idents.rs:34:14 - | -LL | struct AA(T, E); - | ^ - -error: this ident comprises of a single char - --> $DIR/single_char_idents.rs:34:17 - | -LL | struct AA(T, E); - | ^ - -error: this ident comprises of a single char - --> $DIR/single_char_idents.rs:34:20 - | -LL | struct AA(T, E); - | ^ - -error: this ident comprises of a single char - --> $DIR/single_char_idents.rs:38:9 - | -LL | let w = 1; - | ^ - -error: this ident comprises of a single char - --> $DIR/single_char_idents.rs:58:4 - | -LL | fn b() {} - | ^ - -error: aborting due to 16 previous errors - From 243943ff56c755822968a48d5949f79c1d3a7dfa Mon Sep 17 00:00:00 2001 From: Centri3 <114838443+Centri3@users.noreply.github.com> Date: Sat, 10 Jun 2023 04:00:59 -0500 Subject: [PATCH 142/310] make it work for locals as well oopos --- book/src/lint_configuration.md | 19 --- clippy_lints/src/min_ident_chars.rs | 31 ++++- clippy_lints/src/utils/conf.rs | 2 +- .../min_ident_chars/min_ident_chars.rs | 2 + .../min_ident_chars/min_ident_chars.stderr | 36 +++++- tests/ui/min_ident_chars.rs | 34 +++++- tests/ui/min_ident_chars.stderr | 114 ++++++++++++++++-- 7 files changed, 196 insertions(+), 42 deletions(-) diff --git a/book/src/lint_configuration.md b/book/src/lint_configuration.md index 16dc5dcef42..1812d50ed1b 100644 --- a/book/src/lint_configuration.md +++ b/book/src/lint_configuration.md @@ -644,22 +644,3 @@ The maximum byte size a `Future` can have, before it triggers the `clippy::large ## `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`) - ---- -**Affected lints:** -* [`unnecessary_box_returns`](https://rust-lang.github.io/rust-clippy/master/index.html#unnecessary_box_returns) - - -## `allow-private-module-inception` -Whether to allow module inception if it's not public. - -**Default Value:** `false` (`bool`) - ---- -**Affected lints:** -* [`module_inception`](https://rust-lang.github.io/rust-clippy/master/index.html#module_inception) - - diff --git a/clippy_lints/src/min_ident_chars.rs b/clippy_lints/src/min_ident_chars.rs index bbe7fc540e9..cc027b6f498 100644 --- a/clippy_lints/src/min_ident_chars.rs +++ b/clippy_lints/src/min_ident_chars.rs @@ -3,7 +3,7 @@ use rustc_data_structures::fx::FxHashSet; use rustc_hir::{ def::{DefKind, Res}, intravisit::{walk_item, Visitor}, - GenericParamKind, HirId, Item, ItemKind, ItemLocalId, Node, + GenericParamKind, HirId, Item, ItemKind, ItemLocalId, Node, Pat, PatKind, }; use rustc_lint::{LateContext, LateLintPass, LintContext}; use rustc_middle::lint::in_external_macro; @@ -55,6 +55,29 @@ impl LateLintPass<'_> for MinIdentChars { walk_item(&mut IdentVisitor { conf: self, cx }, item); } + + // This is necessary as bindings are not visited in `visit_id`. :/ + #[expect(clippy::cast_possible_truncation)] + fn check_pat(&mut self, cx: &LateContext<'_>, pat: &Pat<'_>) { + if let PatKind::Binding(_, _, ident, ..) = pat.kind + && let str = ident.as_str() + && !in_external_macro(cx.sess(), ident.span) + && str.len() <= self.min_ident_chars_threshold as usize + && !str.is_empty() + && self.allowed_idents_below_min_chars.get(&str.to_owned()).is_none() + { + let help = if self.min_ident_chars_threshold == 1 { + Cow::Borrowed("this ident consists of a single char") + } else { + Cow::Owned(format!( + "this ident is too short ({} <= {})", + str.len(), + self.min_ident_chars_threshold, + )) + }; + span_lint(cx, MIN_IDENT_CHARS, ident.span, &help); + } + } } struct IdentVisitor<'cx, 'tcx> { @@ -62,8 +85,8 @@ struct IdentVisitor<'cx, 'tcx> { cx: &'cx LateContext<'tcx>, } -#[expect(clippy::cast_possible_truncation)] impl Visitor<'_> for IdentVisitor<'_, '_> { + #[expect(clippy::cast_possible_truncation)] fn visit_id(&mut self, hir_id: HirId) { let Self { conf, cx } = *self; // Reimplementation of `find`, as it uses indexing, which can (and will in async functions) panic. @@ -122,9 +145,9 @@ impl Visitor<'_> for IdentVisitor<'_, '_> { Cow::Borrowed("this ident consists of a single char") } else { Cow::Owned(format!( - "this ident is too short ({} <= {}) ", + "this ident is too short ({} <= {})", str.len(), - conf.min_ident_chars_threshold + conf.min_ident_chars_threshold, )) }; span_lint(cx, MIN_IDENT_CHARS, ident.span, &help); diff --git a/clippy_lints/src/utils/conf.rs b/clippy_lints/src/utils/conf.rs index c84d8d8d1f0..f050782a16d 100644 --- a/clippy_lints/src/utils/conf.rs +++ b/clippy_lints/src/utils/conf.rs @@ -34,7 +34,7 @@ const DEFAULT_DOC_VALID_IDENTS: &[&str] = &[ "CamelCase", ]; const DEFAULT_DISALLOWED_NAMES: &[&str] = &["foo", "baz", "quux"]; -const DEFAULT_ALLOWED_IDENTS_BELOW_MIN_CHARS: &[&str] = &["i", "j", "x", "y", "z", "n"]; +const DEFAULT_ALLOWED_IDENTS_BELOW_MIN_CHARS: &[&str] = &["i", "j", "x", "y", "z", "w", "n"]; /// Holds information used by `MISSING_ENFORCED_IMPORT_RENAMES` lint. #[derive(Clone, Debug, Deserialize)] diff --git a/tests/ui-toml/min_ident_chars/min_ident_chars.rs b/tests/ui-toml/min_ident_chars/min_ident_chars.rs index 33100119ca5..4326c7159c8 100644 --- a/tests/ui-toml/min_ident_chars/min_ident_chars.rs +++ b/tests/ui-toml/min_ident_chars/min_ident_chars.rs @@ -14,4 +14,6 @@ fn main() { let wha = 1; let vvv = 1; let uuu = 1; + let (mut a, mut b) = (1, 2); + for i in 0..1000 {} } diff --git a/tests/ui-toml/min_ident_chars/min_ident_chars.stderr b/tests/ui-toml/min_ident_chars/min_ident_chars.stderr index 541f5b10051..d9a27628ddb 100644 --- a/tests/ui-toml/min_ident_chars/min_ident_chars.stderr +++ b/tests/ui-toml/min_ident_chars/min_ident_chars.stderr @@ -1,4 +1,4 @@ -error: this ident is too short (3 <= 3) +error: this ident is too short (3 <= 3) --> $DIR/min_ident_chars.rs:6:19 | LL | use extern_types::Aaa; @@ -6,11 +6,41 @@ LL | use extern_types::Aaa; | = note: `-D clippy::min-ident-chars` implied by `-D warnings` -error: this ident is too short (3 <= 3) +error: this ident is too short (3 <= 3) --> $DIR/min_ident_chars.rs:10:5 | LL | aaa: Aaa, | ^^^ -error: aborting due to 2 previous errors +error: this ident is too short (3 <= 3) + --> $DIR/min_ident_chars.rs:15:9 + | +LL | let vvv = 1; + | ^^^ + +error: this ident is too short (3 <= 3) + --> $DIR/min_ident_chars.rs:16:9 + | +LL | let uuu = 1; + | ^^^ + +error: this ident is too short (1 <= 3) + --> $DIR/min_ident_chars.rs:17:14 + | +LL | let (mut a, mut b) = (1, 2); + | ^ + +error: this ident is too short (1 <= 3) + --> $DIR/min_ident_chars.rs:17:21 + | +LL | let (mut a, mut b) = (1, 2); + | ^ + +error: this ident is too short (1 <= 3) + --> $DIR/min_ident_chars.rs:18:9 + | +LL | for i in 0..1000 {} + | ^ + +error: aborting due to 7 previous errors diff --git a/tests/ui/min_ident_chars.rs b/tests/ui/min_ident_chars.rs index 134c17c553f..85608d030ed 100644 --- a/tests/ui/min_ident_chars.rs +++ b/tests/ui/min_ident_chars.rs @@ -1,5 +1,5 @@ //@aux-build:proc_macros.rs -#![allow(nonstandard_style, unused)] +#![allow(irrefutable_let_patterns, nonstandard_style, unused)] #![warn(clippy::min_ident_chars)] extern crate proc_macros; @@ -15,6 +15,10 @@ struct A { struct B(u32); +struct O { + o: u32, +} + struct i; enum C { @@ -38,11 +42,29 @@ fn main() { let w = 1; // Ok, not this one // let i = 1; - let jz = 1; - let nz = 1; - let zx = 1; - let yz = 1; - let zz = 1; + let j = 1; + let n = 1; + let z = 1; + let y = 1; + let z = 1; + // Implicitly disallowed idents + let h = 1; + let e = 2; + let l = 3; + let l = 4; + let o = 6; + // 2 len does not lint + let hi = 0; + // Lint + let (h, o, w) = (1, 2, 3); + for (a, (r, e)) in (0..1000).enumerate().enumerate() {} + let you = Vec4 { x: 1, y: 2, z: 3, w: 4 }; + while let (d, o, _i, n, g) = (true, true, false, false, true) {} + let today = true; + // Ideally this wouldn't lint, but this would (likely) require global analysis, outta scope + // of this lint regardless + let o = 1; + let o = O { o }; for j in 0..1000 {} diff --git a/tests/ui/min_ident_chars.stderr b/tests/ui/min_ident_chars.stderr index 4b887617058..cd8825634c3 100644 --- a/tests/ui/min_ident_chars.stderr +++ b/tests/ui/min_ident_chars.stderr @@ -31,40 +31,136 @@ LL | struct B(u32); | ^ error: this ident consists of a single char - --> $DIR/min_ident_chars.rs:20:6 + --> $DIR/min_ident_chars.rs:18:8 + | +LL | struct O { + | ^ + +error: this ident consists of a single char + --> $DIR/min_ident_chars.rs:19:5 + | +LL | o: u32, + | ^ + +error: this ident consists of a single char + --> $DIR/min_ident_chars.rs:24:6 | LL | enum C { | ^ error: this ident consists of a single char - --> $DIR/min_ident_chars.rs:21:5 + --> $DIR/min_ident_chars.rs:25:5 | LL | D, | ^ error: this ident consists of a single char - --> $DIR/min_ident_chars.rs:22:5 + --> $DIR/min_ident_chars.rs:26:5 | LL | E, | ^ error: this ident consists of a single char - --> $DIR/min_ident_chars.rs:23:5 + --> $DIR/min_ident_chars.rs:27:5 | LL | F, | ^ error: this ident consists of a single char - --> $DIR/min_ident_chars.rs:31:5 + --> $DIR/min_ident_chars.rs:51:9 | -LL | w: u32, - | ^ +LL | let h = 1; + | ^ error: this ident consists of a single char - --> $DIR/min_ident_chars.rs:58:4 + --> $DIR/min_ident_chars.rs:52:9 + | +LL | let e = 2; + | ^ + +error: this ident consists of a single char + --> $DIR/min_ident_chars.rs:53:9 + | +LL | let l = 3; + | ^ + +error: this ident consists of a single char + --> $DIR/min_ident_chars.rs:54:9 + | +LL | let l = 4; + | ^ + +error: this ident consists of a single char + --> $DIR/min_ident_chars.rs:55:9 + | +LL | let o = 6; + | ^ + +error: this ident consists of a single char + --> $DIR/min_ident_chars.rs:59:10 + | +LL | let (h, o, w) = (1, 2, 3); + | ^ + +error: this ident consists of a single char + --> $DIR/min_ident_chars.rs:59:13 + | +LL | let (h, o, w) = (1, 2, 3); + | ^ + +error: this ident consists of a single char + --> $DIR/min_ident_chars.rs:60:10 + | +LL | for (a, (r, e)) in (0..1000).enumerate().enumerate() {} + | ^ + +error: this ident consists of a single char + --> $DIR/min_ident_chars.rs:60:14 + | +LL | for (a, (r, e)) in (0..1000).enumerate().enumerate() {} + | ^ + +error: this ident consists of a single char + --> $DIR/min_ident_chars.rs:60:17 + | +LL | for (a, (r, e)) in (0..1000).enumerate().enumerate() {} + | ^ + +error: this ident consists of a single char + --> $DIR/min_ident_chars.rs:62:16 + | +LL | while let (d, o, _i, n, g) = (true, true, false, false, true) {} + | ^ + +error: this ident consists of a single char + --> $DIR/min_ident_chars.rs:62:19 + | +LL | while let (d, o, _i, n, g) = (true, true, false, false, true) {} + | ^ + +error: this ident consists of a single char + --> $DIR/min_ident_chars.rs:62:29 + | +LL | while let (d, o, _i, n, g) = (true, true, false, false, true) {} + | ^ + +error: this ident consists of a single char + --> $DIR/min_ident_chars.rs:66:9 + | +LL | let o = 1; + | ^ + +error: this ident consists of a single char + --> $DIR/min_ident_chars.rs:67:9 + | +LL | let o = O { o }; + | ^ + +error: this ident consists of a single char + --> $DIR/min_ident_chars.rs:80:4 | LL | fn b() {} | ^ -error: aborting due to 11 previous errors +error: aborting due to 27 previous errors From 95d1bff2251ff33e1e8ca2bc0c1941c4e91bc2e4 Mon Sep 17 00:00:00 2001 From: Centri3 <114838443+Centri3@users.noreply.github.com> Date: Sat, 10 Jun 2023 09:13:04 -0500 Subject: [PATCH 143/310] add to tests and configuration --- clippy_lints/src/min_ident_chars.rs | 40 ++++++++++++++--------------- clippy_lints/src/utils/conf.rs | 10 +++++++- tests/ui/min_ident_chars.rs | 5 +++- tests/ui/min_ident_chars.stderr | 16 ++++++++++-- 4 files changed, 46 insertions(+), 25 deletions(-) diff --git a/clippy_lints/src/min_ident_chars.rs b/clippy_lints/src/min_ident_chars.rs index cc027b6f498..316c2bf122c 100644 --- a/clippy_lints/src/min_ident_chars.rs +++ b/clippy_lints/src/min_ident_chars.rs @@ -8,6 +8,7 @@ use rustc_hir::{ use rustc_lint::{LateContext, LateLintPass, LintContext}; use rustc_middle::lint::in_external_macro; use rustc_session::{declare_tool_lint, impl_lint_pass}; +use rustc_span::Span; use std::borrow::Cow; declare_clippy_lint! { @@ -56,26 +57,18 @@ impl LateLintPass<'_> for MinIdentChars { walk_item(&mut IdentVisitor { conf: self, cx }, item); } - // This is necessary as bindings are not visited in `visit_id`. :/ + // This is necessary as `Node::Pat`s are not visited in `visit_id`. :/ #[expect(clippy::cast_possible_truncation)] fn check_pat(&mut self, cx: &LateContext<'_>, pat: &Pat<'_>) { if let PatKind::Binding(_, _, ident, ..) = pat.kind && let str = ident.as_str() && !in_external_macro(cx.sess(), ident.span) && str.len() <= self.min_ident_chars_threshold as usize + && !str.starts_with('_') && !str.is_empty() && self.allowed_idents_below_min_chars.get(&str.to_owned()).is_none() { - let help = if self.min_ident_chars_threshold == 1 { - Cow::Borrowed("this ident consists of a single char") - } else { - Cow::Owned(format!( - "this ident is too short ({} <= {})", - str.len(), - self.min_ident_chars_threshold, - )) - }; - span_lint(cx, MIN_IDENT_CHARS, ident.span, &help); + emit_min_ident_chars(self, cx, str, ident.span); } } } @@ -112,6 +105,7 @@ impl Visitor<'_> for IdentVisitor<'_, '_> { let str = ident.as_str(); if !in_external_macro(cx.sess(), ident.span) && str.len() <= conf.min_ident_chars_threshold as usize + && !str.starts_with('_') && !str.is_empty() && conf.allowed_idents_below_min_chars.get(&str.to_owned()).is_none() { @@ -141,16 +135,20 @@ impl Visitor<'_> for IdentVisitor<'_, '_> { return; } - let help = if conf.min_ident_chars_threshold == 1 { - Cow::Borrowed("this ident consists of a single char") - } else { - Cow::Owned(format!( - "this ident is too short ({} <= {})", - str.len(), - conf.min_ident_chars_threshold, - )) - }; - span_lint(cx, MIN_IDENT_CHARS, ident.span, &help); + emit_min_ident_chars(conf, cx, str, ident.span); } } } + +fn emit_min_ident_chars(conf: &MinIdentChars, cx: &impl LintContext, ident: &str, span: Span) { + let help = if conf.min_ident_chars_threshold == 1 { + Cow::Borrowed("this ident consists of a single char") + } else { + Cow::Owned(format!( + "this ident is too short ({} <= {})", + ident.len(), + conf.min_ident_chars_threshold, + )) + }; + span_lint(cx, MIN_IDENT_CHARS, span, &help); +} diff --git a/clippy_lints/src/utils/conf.rs b/clippy_lints/src/utils/conf.rs index f050782a16d..0a581e0ab9b 100644 --- a/clippy_lints/src/utils/conf.rs +++ b/clippy_lints/src/utils/conf.rs @@ -525,7 +525,9 @@ define_Conf! { (allow_private_module_inception: bool = false), /// Lint: MIN_IDENT_CHARS. /// - /// Allowed names below the minimum allowed characters. + /// Allowed names below the minimum allowed characters. 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. (allowed_idents_below_min_chars: rustc_data_structures::fx::FxHashSet = super::DEFAULT_ALLOWED_IDENTS_BELOW_MIN_CHARS.iter().map(ToString::to_string).collect()), /// Lint: MIN_IDENT_CHARS. @@ -599,6 +601,12 @@ pub fn read(sess: &Session, path: &Path) -> TryConf { Ok(mut conf) => { extend_vec_if_indicator_present(&mut conf.conf.doc_valid_idents, DEFAULT_DOC_VALID_IDENTS); extend_vec_if_indicator_present(&mut conf.conf.disallowed_names, DEFAULT_DISALLOWED_NAMES); + // TODO: THIS SHOULD BE TESTED, this comment will be gone soon + if conf.conf.allowed_idents_below_min_chars.contains(&"..".to_owned()) { + conf.conf + .allowed_idents_below_min_chars + .extend(DEFAULT_ALLOWED_IDENTS_BELOW_MIN_CHARS.iter().map(ToString::to_string)); + } conf }, diff --git a/tests/ui/min_ident_chars.rs b/tests/ui/min_ident_chars.rs index 85608d030ed..c5e03468ef9 100644 --- a/tests/ui/min_ident_chars.rs +++ b/tests/ui/min_ident_chars.rs @@ -67,6 +67,7 @@ fn main() { let o = O { o }; for j in 0..1000 {} + for _ in 0..10 {} // Do not lint code from external macros external! { for j in 0..1000 {} } @@ -78,4 +79,6 @@ fn main() { } fn b() {} -fn owo() {} +fn wrong_pythagoras(a: f32, b: f32) -> f32 { + a * a + a * b +} diff --git a/tests/ui/min_ident_chars.stderr b/tests/ui/min_ident_chars.stderr index cd8825634c3..66a63f65756 100644 --- a/tests/ui/min_ident_chars.stderr +++ b/tests/ui/min_ident_chars.stderr @@ -157,10 +157,22 @@ LL | let o = O { o }; | ^ error: this ident consists of a single char - --> $DIR/min_ident_chars.rs:80:4 + --> $DIR/min_ident_chars.rs:81:4 | LL | fn b() {} | ^ -error: aborting due to 27 previous errors +error: this ident consists of a single char + --> $DIR/min_ident_chars.rs:82:21 + | +LL | fn wrong_pythagoras(a: f32, b: f32) -> f32 { + | ^ + +error: this ident consists of a single char + --> $DIR/min_ident_chars.rs:82:29 + | +LL | fn wrong_pythagoras(a: f32, b: f32) -> f32 { + | ^ + +error: aborting due to 29 previous errors From 203e875189647fa986e5d31998a7ecc4f3340c01 Mon Sep 17 00:00:00 2001 From: Centri3 <114838443+Centri3@users.noreply.github.com> Date: Sat, 10 Jun 2023 09:35:42 -0500 Subject: [PATCH 144/310] `cargo collect-metadata` --- book/src/lint_configuration.md | 41 ++++++++++++++++++++++++++++++++++ 1 file changed, 41 insertions(+) diff --git a/book/src/lint_configuration.md b/book/src/lint_configuration.md index 1812d50ed1b..b2e11d8de67 100644 --- a/book/src/lint_configuration.md +++ b/book/src/lint_configuration.md @@ -644,3 +644,44 @@ The maximum byte size a `Future` can have, before it triggers the `clippy::large ## `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`) + +--- +**Affected lints:** +* [`unnecessary_box_returns`](https://rust-lang.github.io/rust-clippy/master/index.html#unnecessary_box_returns) + + +## `allow-private-module-inception` +Whether to allow module inception if it's not public. + +**Default Value:** `false` (`bool`) + +--- +**Affected lints:** +* [`module_inception`](https://rust-lang.github.io/rust-clippy/master/index.html#module_inception) + + +## `allowed-idents-below-min-chars` +Allowed names below the minimum allowed characters. 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 Value:** `{"j", "z", "i", "y", "n", "x", "w"}` (`rustc_data_structures::fx::FxHashSet`) + +--- +**Affected lints:** +* [`min_ident_chars`](https://rust-lang.github.io/rust-clippy/master/index.html#min_ident_chars) + + +## `min-ident-chars-threshold` +Minimum chars an ident can have, anything below or equal to this will be linted. + +**Default Value:** `1` (`u64`) + +--- +**Affected lints:** +* [`min_ident_chars`](https://rust-lang.github.io/rust-clippy/master/index.html#min_ident_chars) + + From 29c1c6e104340b04505572220b29e5e76d7053b9 Mon Sep 17 00:00:00 2001 From: Centri3 <114838443+Centri3@users.noreply.github.com> Date: Sun, 11 Jun 2023 14:51:50 -0500 Subject: [PATCH 145/310] refactor and add link to issue --- clippy_lints/src/min_ident_chars.rs | 33 ++++++++++++++--------------- 1 file changed, 16 insertions(+), 17 deletions(-) diff --git a/clippy_lints/src/min_ident_chars.rs b/clippy_lints/src/min_ident_chars.rs index 316c2bf122c..d49bb0ca6e2 100644 --- a/clippy_lints/src/min_ident_chars.rs +++ b/clippy_lints/src/min_ident_chars.rs @@ -34,7 +34,6 @@ declare_clippy_lint! { /// let title = movie.title; /// } /// ``` - /// ``` #[clippy::version = "1.72.0"] pub MIN_IDENT_CHARS, restriction, @@ -48,6 +47,17 @@ pub struct MinIdentChars { pub min_ident_chars_threshold: u64, } +impl MinIdentChars { + #[expect(clippy::cast_possible_truncation)] + fn is_ident_too_short(&self, cx: &LateContext<'_>, str: &str, span: Span) -> bool { + !in_external_macro(cx.sess(), span) + && str.len() <= self.min_ident_chars_threshold as usize + && !str.starts_with('_') + && !str.is_empty() + && self.allowed_idents_below_min_chars.get(&str.to_owned()).is_none() + } +} + impl LateLintPass<'_> for MinIdentChars { fn check_item(&mut self, cx: &LateContext<'_>, item: &Item<'_>) { if self.min_ident_chars_threshold == 0 { @@ -58,15 +68,10 @@ impl LateLintPass<'_> for MinIdentChars { } // This is necessary as `Node::Pat`s are not visited in `visit_id`. :/ - #[expect(clippy::cast_possible_truncation)] fn check_pat(&mut self, cx: &LateContext<'_>, pat: &Pat<'_>) { if let PatKind::Binding(_, _, ident, ..) = pat.kind && let str = ident.as_str() - && !in_external_macro(cx.sess(), ident.span) - && str.len() <= self.min_ident_chars_threshold as usize - && !str.starts_with('_') - && !str.is_empty() - && self.allowed_idents_below_min_chars.get(&str.to_owned()).is_none() + && self.is_ident_too_short(cx, str, ident.span) { emit_min_ident_chars(self, cx, str, ident.span); } @@ -79,12 +84,11 @@ struct IdentVisitor<'cx, 'tcx> { } impl Visitor<'_> for IdentVisitor<'_, '_> { - #[expect(clippy::cast_possible_truncation)] fn visit_id(&mut self, hir_id: HirId) { let Self { conf, cx } = *self; - // Reimplementation of `find`, as it uses indexing, which can (and will in async functions) panic. - // This should probably be fixed on the rustc side, this is just a temporary workaround. - // FIXME: Remove me if/when this is fixed in rustc + // FIXME(#112534) Reimplementation of `find`, as it uses indexing, which can (and will in + // async functions, or really anything async) panic. This should probably be fixed on the + // rustc side, this is just a temporary workaround. let node = if hir_id.local_id == ItemLocalId::from_u32(0) { // In this case, we can just use `find`, `Owner`'s `node` field is private anyway so we can't // reimplement it even if we wanted to @@ -103,12 +107,7 @@ impl Visitor<'_> for IdentVisitor<'_, '_> { }; let str = ident.as_str(); - if !in_external_macro(cx.sess(), ident.span) - && str.len() <= conf.min_ident_chars_threshold as usize - && !str.starts_with('_') - && !str.is_empty() - && conf.allowed_idents_below_min_chars.get(&str.to_owned()).is_none() - { + if conf.is_ident_too_short(cx, str, ident.span) { if let Node::Item(item) = node && let ItemKind::Use(..) = item.kind { return; } From 7312a93a069f93b8d82cee08100444540e51ffcb Mon Sep 17 00:00:00 2001 From: y21 <30553356+y21@users.noreply.github.com> Date: Thu, 25 May 2023 19:46:05 +0200 Subject: [PATCH 146/310] new lint: `large_stack_frames` --- CHANGELOG.md | 1 + book/src/lint_configuration.md | 10 +- clippy_lints/src/declared_lints.rs | 1 + clippy_lints/src/large_stack_frames.rs | 162 ++++++++++++++++++ clippy_lints/src/lib.rs | 3 + clippy_lints/src/utils/conf.rs | 4 + .../toml_unknown_key/conf_unknown_key.stderr | 1 + tests/ui/large_stack_frames.rs | 44 +++++ tests/ui/large_stack_frames.stderr | 37 ++++ 9 files changed, 262 insertions(+), 1 deletion(-) create mode 100644 clippy_lints/src/large_stack_frames.rs create mode 100644 tests/ui/large_stack_frames.rs create mode 100644 tests/ui/large_stack_frames.stderr diff --git a/CHANGELOG.md b/CHANGELOG.md index 2d62bfd4f99..8624fa136e7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4815,6 +4815,7 @@ Released 2018-09-13 [`get_last_with_len`]: https://rust-lang.github.io/rust-clippy/master/index.html#get_last_with_len [`get_unwrap`]: https://rust-lang.github.io/rust-clippy/master/index.html#get_unwrap [`host_endian_bytes`]: https://rust-lang.github.io/rust-clippy/master/index.html#host_endian_bytes +[`large_stack_frames`]: https://rust-lang.github.io/rust-clippy/master/index.html#large_stack_frames [`identity_conversion`]: https://rust-lang.github.io/rust-clippy/master/index.html#identity_conversion [`identity_op`]: https://rust-lang.github.io/rust-clippy/master/index.html#identity_op [`if_let_mutex`]: https://rust-lang.github.io/rust-clippy/master/index.html#if_let_mutex diff --git a/book/src/lint_configuration.md b/book/src/lint_configuration.md index b2e11d8de67..9e8729a1afe 100644 --- a/book/src/lint_configuration.md +++ b/book/src/lint_configuration.md @@ -338,7 +338,15 @@ The maximum allowed size for arrays on the stack * [`large_const_arrays`](https://rust-lang.github.io/rust-clippy/master/index.html#large_const_arrays) -## `vec-box-size-threshold` +### stack-size-threshold +The maximum allowed stack size for functions in bytes + +**Default Value:** `512000` (`u64`) + +* [large_stack_frames](https://rust-lang.github.io/rust-clippy/master/index.html#large_stack_frames) + + +### vec-box-size-threshold The size of the boxed type in bytes, where boxing in a `Vec` is allowed **Default Value:** `4096` (`u64`) diff --git a/clippy_lints/src/declared_lints.rs b/clippy_lints/src/declared_lints.rs index 769774b27c4..8fd8705b445 100644 --- a/clippy_lints/src/declared_lints.rs +++ b/clippy_lints/src/declared_lints.rs @@ -198,6 +198,7 @@ pub(crate) static LINTS: &[&crate::LintInfo] = &[ crate::functions::TOO_MANY_ARGUMENTS_INFO, crate::functions::TOO_MANY_LINES_INFO, crate::future_not_send::FUTURE_NOT_SEND_INFO, + crate::large_stack_frames::LARGE_STACK_FRAMES_INFO, crate::if_let_mutex::IF_LET_MUTEX_INFO, crate::if_not_else::IF_NOT_ELSE_INFO, crate::if_then_some_else_none::IF_THEN_SOME_ELSE_NONE_INFO, diff --git a/clippy_lints/src/large_stack_frames.rs b/clippy_lints/src/large_stack_frames.rs new file mode 100644 index 00000000000..2ab1f669460 --- /dev/null +++ b/clippy_lints/src/large_stack_frames.rs @@ -0,0 +1,162 @@ +use std::ops::AddAssign; + +use clippy_utils::diagnostics::span_lint_and_then; +use rustc_hir::def_id::LocalDefId; +use rustc_hir::intravisit::FnKind; +use rustc_hir::Body; +use rustc_hir::FnDecl; +use rustc_lint::{LateContext, LateLintPass}; +use rustc_session::declare_tool_lint; +use rustc_session::impl_lint_pass; +use rustc_span::Span; + +declare_clippy_lint! { + /// ### What it does + /// Checks for functions that use a lot of stack space. + /// + /// This often happens when constructing a large type, such as an array with a lot of elements, + /// or constructing *many* smaller-but-still-large structs, or copying around a lot of large types. + /// + /// This lint is a more general version of [`large_stack_arrays`](https://rust-lang.github.io/rust-clippy/master/#large_stack_arrays) + /// that is intended to look at functions as a whole instead of only individual array expressions inside of a function. + /// + /// ### Why is this bad? + /// The stack region of memory is very limited in size (usually *much* smaller than the heap) and attempting to + /// use too much will result in a stack overflow and crash the program. + /// To avoid this, you should consider allocating large types on the heap instead (e.g. by boxing them). + /// + /// Keep in mind that the code path to construction of large types does not even need to be reachable; + /// it purely needs to *exist* inside of the function to contribute to the stack size. + /// For example, this causes a stack overflow even though the branch is unreachable (with `-Zmir-opt-level=0`): + /// ```rust,ignore + /// fn main() { + /// if false { + /// let x = [0u8; 10000000]; // 10 MB stack array + /// black_box(&x); + /// } + /// } + /// ``` + /// + /// ### Drawbacks + /// False positives. The stack size that clippy sees is an estimated value and can be vastly different + /// from the actual stack usage after optimizations passes have run (especially true in release mode). + /// Modern compilers are very smart and are able to optimize away a lot of unnecessary stack allocations. + /// In debug mode however, it is usually more accurate. + /// + /// This lint works by summing up the size of all locals and comparing them against a (configurable, but high-by-default) + /// threshold. + /// Note that "locals" in this context refers to [MIR locals](https://rustc-dev-guide.rust-lang.org/mir/index.html#key-mir-vocabulary), + /// i.e. real local variables that the user typed, storage for temporary values, function arguments + /// and the return value. + /// + /// ### Example + /// This function creates four 500 KB arrays on the stack. Quite big but just small enough to not trigger `large_stack_arrays`. + /// However, looking at the function as a whole, it's clear that this uses a lot of stack space. + /// ```rust + /// struct QuiteLargeType([u8; 500_000]); + /// fn foo() { + /// // ... some function that uses a lot of stack space ... + /// let _x1 = QuiteLargeType([0; 500_000]); + /// let _x2 = QuiteLargeType([0; 500_000]); + /// let _x3 = QuiteLargeType([0; 500_000]); + /// let _x4 = QuiteLargeType([0; 500_000]); + /// } + /// ``` + /// + /// Instead of doing this, allocate the arrays on the heap. + /// This currently requires going through a `Vec` first and then converting it to a `Box`: + /// ```rust + /// struct NotSoLargeType(Box<[u8]>); + /// + /// fn foo() { + /// let _x1 = NotSoLargeType(vec![0; 500_000].into_boxed_slice()); + /// // ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Now heap allocated. + /// // The size of `NotSoLargeType` is 16 bytes. + /// // ... + /// } + /// ``` + #[clippy::version = "1.71.0"] + pub LARGE_STACK_FRAMES, + nursery, + "checks for functions that allocate a lot of stack space" +} + +pub struct LargeStackFrames { + maximum_allowed_size: u64, +} + +impl LargeStackFrames { + #[must_use] + pub fn new(size: u64) -> Self { + Self { + maximum_allowed_size: size, + } + } +} + +impl_lint_pass!(LargeStackFrames => [LARGE_STACK_FRAMES]); + +#[derive(Copy, Clone)] +enum Space { + Used(u64), + Overflow, +} + +impl Space { + pub fn exceeds_limit(self, limit: u64) -> bool { + match self { + Self::Used(used) => used > limit, + Self::Overflow => true, + } + } +} + +impl AddAssign for Space { + fn add_assign(&mut self, rhs: u64) { + if let Self::Used(lhs) = self { + match lhs.checked_add(rhs) { + Some(sum) => *self = Self::Used(sum), + None => { + *self = Self::Overflow; + }, + } + } + } +} + +impl<'tcx> LateLintPass<'tcx> for LargeStackFrames { + fn check_fn( + &mut self, + cx: &LateContext<'tcx>, + _: FnKind<'tcx>, + _: &'tcx FnDecl<'tcx>, + _: &'tcx Body<'tcx>, + span: Span, + local_def_id: LocalDefId, + ) { + let def_id = local_def_id.to_def_id(); + + let mir = cx.tcx.optimized_mir(def_id); + let param_env = cx.tcx.param_env(def_id); + + let mut frame_size = Space::Used(0); + + for local in &mir.local_decls { + if let Ok(layout) = cx.tcx.layout_of(param_env.and(local.ty)) { + frame_size += layout.size.bytes(); + } + } + + if frame_size.exceeds_limit(self.maximum_allowed_size) { + span_lint_and_then( + cx, + LARGE_STACK_FRAMES, + span, + "this function allocates a large amount of stack space", + |diag| { + diag.note("allocating large amounts of stack space can overflow the stack"); + }, + ); + } + } +} diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index dcf1c6f64a4..2fa95e2b447 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -142,6 +142,7 @@ mod from_raw_with_void_ptr; mod from_str_radix_10; mod functions; mod future_not_send; +mod large_stack_frames; mod if_let_mutex; mod if_not_else; mod if_then_some_else_none; @@ -1042,6 +1043,8 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: min_ident_chars_threshold, }) }); + let stack_size_threshold = conf.stack_size_threshold; + store.register_late_pass(move |_| Box::new(large_stack_frames::LargeStackFrames::new(stack_size_threshold))); // add lints here, do not remove this comment, it's used in `new_lint` } diff --git a/clippy_lints/src/utils/conf.rs b/clippy_lints/src/utils/conf.rs index 0a581e0ab9b..f6c7c1fa065 100644 --- a/clippy_lints/src/utils/conf.rs +++ b/clippy_lints/src/utils/conf.rs @@ -387,6 +387,10 @@ define_Conf! { /// /// The maximum allowed size for arrays on the stack (array_size_threshold: u64 = 512_000), + /// Lint: LARGE_STACK_FRAMES. + /// + /// The maximum allowed stack size for functions in bytes + (stack_size_threshold: u64 = 512_000), /// Lint: VEC_BOX. /// /// The size of the boxed type in bytes, where boxing in a `Vec` is allowed 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 c546d95eb46..79af9cc9ac0 100644 --- a/tests/ui-toml/toml_unknown_key/conf_unknown_key.stderr +++ b/tests/ui-toml/toml_unknown_key/conf_unknown_key.stderr @@ -44,6 +44,7 @@ error: error reading Clippy's configuration file: unknown field `foobar`, expect semicolon-inside-block-ignore-singleline semicolon-outside-block-ignore-multiline single-char-binding-names-threshold + stack-size-threshold standard-macro-braces suppress-restriction-lint-in-const third-party diff --git a/tests/ui/large_stack_frames.rs b/tests/ui/large_stack_frames.rs new file mode 100644 index 00000000000..cd9d0c8a67a --- /dev/null +++ b/tests/ui/large_stack_frames.rs @@ -0,0 +1,44 @@ +#![allow(unused, incomplete_features)] +#![warn(clippy::large_stack_frames)] +#![feature(unsized_locals)] + +use std::hint::black_box; + +fn generic() { + let x = T::default(); + black_box(&x); +} + +fn unsized_local() { + let x: dyn std::fmt::Display = *(Box::new(1) as Box); + black_box(&x); +} + +struct ArrayDefault([u8; N]); + +impl Default for ArrayDefault { + fn default() -> Self { + Self([0; N]) + } +} + +fn many_small_arrays() { + let x = [0u8; 500_000]; + let x2 = [0u8; 500_000]; + let x3 = [0u8; 500_000]; + let x4 = [0u8; 500_000]; + let x5 = [0u8; 500_000]; + black_box((&x, &x2, &x3, &x4, &x5)); +} + +fn large_return_value() -> ArrayDefault<1_000_000> { + Default::default() +} + +fn large_fn_arg(x: ArrayDefault<1_000_000>) { + black_box(&x); +} + +fn main() { + generic::>(); +} diff --git a/tests/ui/large_stack_frames.stderr b/tests/ui/large_stack_frames.stderr new file mode 100644 index 00000000000..d57df8596fe --- /dev/null +++ b/tests/ui/large_stack_frames.stderr @@ -0,0 +1,37 @@ +error: this function allocates a large amount of stack space + --> $DIR/large_stack_frames.rs:25:1 + | +LL | / fn many_small_arrays() { +LL | | let x = [0u8; 500_000]; +LL | | let x2 = [0u8; 500_000]; +LL | | let x3 = [0u8; 500_000]; +... | +LL | | black_box((&x, &x2, &x3, &x4, &x5)); +LL | | } + | |_^ + | + = note: allocating large amounts of stack space can overflow the stack + = note: `-D clippy::large-stack-frames` implied by `-D warnings` + +error: this function allocates a large amount of stack space + --> $DIR/large_stack_frames.rs:34:1 + | +LL | / fn large_return_value() -> ArrayDefault<1_000_000> { +LL | | Default::default() +LL | | } + | |_^ + | + = note: allocating large amounts of stack space can overflow the stack + +error: this function allocates a large amount of stack space + --> $DIR/large_stack_frames.rs:38:1 + | +LL | / fn large_fn_arg(x: ArrayDefault<1_000_000>) { +LL | | black_box(&x); +LL | | } + | |_^ + | + = note: allocating large amounts of stack space can overflow the stack + +error: aborting due to 3 previous errors + From 760f91f895fb1da89a4999c7de35564a18f903aa Mon Sep 17 00:00:00 2001 From: y21 <30553356+y21@users.noreply.github.com> Date: Thu, 25 May 2023 19:52:08 +0200 Subject: [PATCH 147/310] `cargo dev update_lints` --- CHANGELOG.md | 1 + clippy_lints/src/declared_lints.rs | 2 +- clippy_lints/src/lib.rs | 2 +- 3 files changed, 3 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 8624fa136e7..e8337c3b6d0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4884,6 +4884,7 @@ Released 2018-09-13 [`large_futures`]: https://rust-lang.github.io/rust-clippy/master/index.html#large_futures [`large_include_file`]: https://rust-lang.github.io/rust-clippy/master/index.html#large_include_file [`large_stack_arrays`]: https://rust-lang.github.io/rust-clippy/master/index.html#large_stack_arrays +[`large_stack_frames`]: https://rust-lang.github.io/rust-clippy/master/index.html#large_stack_frames [`large_types_passed_by_value`]: https://rust-lang.github.io/rust-clippy/master/index.html#large_types_passed_by_value [`len_without_is_empty`]: https://rust-lang.github.io/rust-clippy/master/index.html#len_without_is_empty [`len_zero`]: https://rust-lang.github.io/rust-clippy/master/index.html#len_zero diff --git a/clippy_lints/src/declared_lints.rs b/clippy_lints/src/declared_lints.rs index 8fd8705b445..523faa302dc 100644 --- a/clippy_lints/src/declared_lints.rs +++ b/clippy_lints/src/declared_lints.rs @@ -198,7 +198,6 @@ pub(crate) static LINTS: &[&crate::LintInfo] = &[ crate::functions::TOO_MANY_ARGUMENTS_INFO, crate::functions::TOO_MANY_LINES_INFO, crate::future_not_send::FUTURE_NOT_SEND_INFO, - crate::large_stack_frames::LARGE_STACK_FRAMES_INFO, crate::if_let_mutex::IF_LET_MUTEX_INFO, crate::if_not_else::IF_NOT_ELSE_INFO, crate::if_then_some_else_none::IF_THEN_SOME_ELSE_NONE_INFO, @@ -229,6 +228,7 @@ pub(crate) static LINTS: &[&crate::LintInfo] = &[ crate::large_futures::LARGE_FUTURES_INFO, crate::large_include_file::LARGE_INCLUDE_FILE_INFO, crate::large_stack_arrays::LARGE_STACK_ARRAYS_INFO, + crate::large_stack_frames::LARGE_STACK_FRAMES_INFO, crate::len_zero::COMPARISON_TO_EMPTY_INFO, crate::len_zero::LEN_WITHOUT_IS_EMPTY_INFO, crate::len_zero::LEN_ZERO_INFO, diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index 2fa95e2b447..71447724790 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -142,7 +142,6 @@ mod from_raw_with_void_ptr; mod from_str_radix_10; mod functions; mod future_not_send; -mod large_stack_frames; mod if_let_mutex; mod if_not_else; mod if_then_some_else_none; @@ -169,6 +168,7 @@ mod large_enum_variant; mod large_futures; mod large_include_file; mod large_stack_arrays; +mod large_stack_frames; mod len_zero; mod let_if_seq; mod let_underscore; From 52c6ef77fd620f9efc486280fd237adaddd9fc29 Mon Sep 17 00:00:00 2001 From: y21 <30553356+y21@users.noreply.github.com> Date: Thu, 25 May 2023 20:07:20 +0200 Subject: [PATCH 148/310] fmt --- clippy_lints/src/large_stack_frames.rs | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/clippy_lints/src/large_stack_frames.rs b/clippy_lints/src/large_stack_frames.rs index 2ab1f669460..0da953e6917 100644 --- a/clippy_lints/src/large_stack_frames.rs +++ b/clippy_lints/src/large_stack_frames.rs @@ -116,9 +116,7 @@ impl AddAssign for Space { if let Self::Used(lhs) = self { match lhs.checked_add(rhs) { Some(sum) => *self = Self::Used(sum), - None => { - *self = Self::Overflow; - }, + None => *self = Self::Overflow, } } } From 6b232fdee9c8d65ca40ce112a83e92a8c395c398 Mon Sep 17 00:00:00 2001 From: y21 <30553356+y21@users.noreply.github.com> Date: Thu, 25 May 2023 20:30:38 +0200 Subject: [PATCH 149/310] use span_lint_and_note --- clippy_lints/src/large_stack_frames.rs | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/clippy_lints/src/large_stack_frames.rs b/clippy_lints/src/large_stack_frames.rs index 0da953e6917..87daa2e7da0 100644 --- a/clippy_lints/src/large_stack_frames.rs +++ b/clippy_lints/src/large_stack_frames.rs @@ -1,6 +1,6 @@ use std::ops::AddAssign; -use clippy_utils::diagnostics::span_lint_and_then; +use clippy_utils::diagnostics::span_lint_and_note; use rustc_hir::def_id::LocalDefId; use rustc_hir::intravisit::FnKind; use rustc_hir::Body; @@ -146,14 +146,13 @@ impl<'tcx> LateLintPass<'tcx> for LargeStackFrames { } if frame_size.exceeds_limit(self.maximum_allowed_size) { - span_lint_and_then( + span_lint_and_note( cx, LARGE_STACK_FRAMES, span, "this function allocates a large amount of stack space", - |diag| { - diag.note("allocating large amounts of stack space can overflow the stack"); - }, + None, + "allocating large amounts of stack space can overflow the stack", ); } } From 7aa4babb5ce26208d49be1c1fc404962d87a721e Mon Sep 17 00:00:00 2001 From: y21 <30553356+y21@users.noreply.github.com> Date: Wed, 7 Jun 2023 21:08:05 +0200 Subject: [PATCH 150/310] rename "drawbacks" to "known issues" --- clippy_lints/src/large_stack_frames.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clippy_lints/src/large_stack_frames.rs b/clippy_lints/src/large_stack_frames.rs index 87daa2e7da0..d638279b5d1 100644 --- a/clippy_lints/src/large_stack_frames.rs +++ b/clippy_lints/src/large_stack_frames.rs @@ -37,7 +37,7 @@ declare_clippy_lint! { /// } /// ``` /// - /// ### Drawbacks + /// ### Known issues /// False positives. The stack size that clippy sees is an estimated value and can be vastly different /// from the actual stack usage after optimizations passes have run (especially true in release mode). /// Modern compilers are very smart and are able to optimize away a lot of unnecessary stack allocations. From de7d43bc610f5f2ac107d947de1c2438401f7a2b Mon Sep 17 00:00:00 2001 From: y21 <30553356+y21@users.noreply.github.com> Date: Thu, 8 Jun 2023 12:42:12 +0200 Subject: [PATCH 151/310] make lint description easier to read, prevent ICE --- clippy_lints/src/large_stack_frames.rs | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/clippy_lints/src/large_stack_frames.rs b/clippy_lints/src/large_stack_frames.rs index d638279b5d1..9c0cc978a39 100644 --- a/clippy_lints/src/large_stack_frames.rs +++ b/clippy_lints/src/large_stack_frames.rs @@ -1,6 +1,7 @@ use std::ops::AddAssign; use clippy_utils::diagnostics::span_lint_and_note; +use clippy_utils::fn_has_unsatisfiable_preds; use rustc_hir::def_id::LocalDefId; use rustc_hir::intravisit::FnKind; use rustc_hir::Body; @@ -27,7 +28,7 @@ declare_clippy_lint! { /// /// Keep in mind that the code path to construction of large types does not even need to be reachable; /// it purely needs to *exist* inside of the function to contribute to the stack size. - /// For example, this causes a stack overflow even though the branch is unreachable (with `-Zmir-opt-level=0`): + /// For example, this causes a stack overflow even though the branch is unreachable: /// ```rust,ignore /// fn main() { /// if false { @@ -43,11 +44,9 @@ declare_clippy_lint! { /// Modern compilers are very smart and are able to optimize away a lot of unnecessary stack allocations. /// In debug mode however, it is usually more accurate. /// - /// This lint works by summing up the size of all locals and comparing them against a (configurable, but high-by-default) - /// threshold. - /// Note that "locals" in this context refers to [MIR locals](https://rustc-dev-guide.rust-lang.org/mir/index.html#key-mir-vocabulary), - /// i.e. real local variables that the user typed, storage for temporary values, function arguments - /// and the return value. + /// This lint works by summing up the size of all variables that the user typed, variables that were + /// implicitly introduced by the compiler for temporaries, function arguments and the return value, + /// and comparing them against a (configurable, but high-by-default). /// /// ### Example /// This function creates four 500 KB arrays on the stack. Quite big but just small enough to not trigger `large_stack_arrays`. @@ -133,6 +132,10 @@ impl<'tcx> LateLintPass<'tcx> for LargeStackFrames { local_def_id: LocalDefId, ) { let def_id = local_def_id.to_def_id(); + // Building MIR for `fn`s with unsatisfiable preds results in ICE. + if fn_has_unsatisfiable_preds(cx, def_id) { + return; + } let mir = cx.tcx.optimized_mir(def_id); let param_env = cx.tcx.param_env(def_id); From c8c7a3c79ccee50a852ea94386d0ed630f0d8540 Mon Sep 17 00:00:00 2001 From: y21 <30553356+y21@users.noreply.github.com> Date: Thu, 8 Jun 2023 12:54:13 +0200 Subject: [PATCH 152/310] fix rebase weirdness --- CHANGELOG.md | 1 - book/src/lint_configuration.md | 4 ++-- tests/ui-toml/toml_unknown_key/conf_unknown_key.stderr | 1 + 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index e8337c3b6d0..85fddc97047 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4815,7 +4815,6 @@ Released 2018-09-13 [`get_last_with_len`]: https://rust-lang.github.io/rust-clippy/master/index.html#get_last_with_len [`get_unwrap`]: https://rust-lang.github.io/rust-clippy/master/index.html#get_unwrap [`host_endian_bytes`]: https://rust-lang.github.io/rust-clippy/master/index.html#host_endian_bytes -[`large_stack_frames`]: https://rust-lang.github.io/rust-clippy/master/index.html#large_stack_frames [`identity_conversion`]: https://rust-lang.github.io/rust-clippy/master/index.html#identity_conversion [`identity_op`]: https://rust-lang.github.io/rust-clippy/master/index.html#identity_op [`if_let_mutex`]: https://rust-lang.github.io/rust-clippy/master/index.html#if_let_mutex diff --git a/book/src/lint_configuration.md b/book/src/lint_configuration.md index 9e8729a1afe..d8793881218 100644 --- a/book/src/lint_configuration.md +++ b/book/src/lint_configuration.md @@ -338,7 +338,7 @@ The maximum allowed size for arrays on the stack * [`large_const_arrays`](https://rust-lang.github.io/rust-clippy/master/index.html#large_const_arrays) -### stack-size-threshold +## `stack-size-threshold` The maximum allowed stack size for functions in bytes **Default Value:** `512000` (`u64`) @@ -346,7 +346,7 @@ The maximum allowed stack size for functions in bytes * [large_stack_frames](https://rust-lang.github.io/rust-clippy/master/index.html#large_stack_frames) -### vec-box-size-threshold +## `vec-box-size-threshold` The size of the boxed type in bytes, where boxing in a `Vec` is allowed **Default Value:** `4096` (`u64`) 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 79af9cc9ac0..d8ce0e2f55d 100644 --- a/tests/ui-toml/toml_unknown_key/conf_unknown_key.stderr +++ b/tests/ui-toml/toml_unknown_key/conf_unknown_key.stderr @@ -110,6 +110,7 @@ error: error reading Clippy's configuration file: unknown field `barfoo`, expect semicolon-inside-block-ignore-singleline semicolon-outside-block-ignore-multiline single-char-binding-names-threshold + stack-size-threshold standard-macro-braces suppress-restriction-lint-in-const third-party From 6ad7c6f4e67cd975db7993242f34d27ad893cc93 Mon Sep 17 00:00:00 2001 From: y21 <30553356+y21@users.noreply.github.com> Date: Sun, 11 Jun 2023 12:07:34 +0200 Subject: [PATCH 153/310] update lint_configuration.md --- book/src/lint_configuration.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/book/src/lint_configuration.md b/book/src/lint_configuration.md index d8793881218..085dff8e63b 100644 --- a/book/src/lint_configuration.md +++ b/book/src/lint_configuration.md @@ -343,7 +343,9 @@ The maximum allowed stack size for functions in bytes **Default Value:** `512000` (`u64`) -* [large_stack_frames](https://rust-lang.github.io/rust-clippy/master/index.html#large_stack_frames) +--- +**Affected lints:** +* [`large_stack_frames`](https://rust-lang.github.io/rust-clippy/master/index.html#large_stack_frames) ## `vec-box-size-threshold` From b309875fd8e64c2c33d4a4d0576cc40891ad18be Mon Sep 17 00:00:00 2001 From: y21 <30553356+y21@users.noreply.github.com> Date: Mon, 12 Jun 2023 15:48:04 +0200 Subject: [PATCH 154/310] [`useless_vec`]: detect unnecessary `vec![_]` --- clippy_lints/src/vec.rs | 97 ++++++++++++++++++----------------------- 1 file changed, 42 insertions(+), 55 deletions(-) diff --git a/clippy_lints/src/vec.rs b/clippy_lints/src/vec.rs index 25b6f40762d..2a594e750b9 100644 --- a/clippy_lints/src/vec.rs +++ b/clippy_lints/src/vec.rs @@ -8,7 +8,6 @@ use clippy_utils::ty::is_copy; use clippy_utils::visitors::for_each_local_use_after_expr; use clippy_utils::{get_parent_expr, higher, is_trait_method}; use if_chain::if_chain; -use rustc_ast::BindingAnnotation; use rustc_errors::Applicability; use rustc_hir::{BorrowKind, Expr, ExprKind, Mutability, Node, PatKind}; use rustc_lint::{LateContext, LateLintPass}; @@ -54,11 +53,7 @@ declare_clippy_lint! { impl_lint_pass!(UselessVec => [USELESS_VEC]); fn adjusts_to_slice(cx: &LateContext<'_>, e: &Expr<'_>) -> bool { - if let ty::Ref(_, ty, _) = cx.typeck_results().expr_ty_adjusted(e).kind() { - ty.is_slice() - } else { - false - } + matches!(cx.typeck_results().expr_ty_adjusted(e).kind(), ty::Ref(_, ty, _) if ty.is_slice()) } /// Checks if the given expression is a method call to a `Vec` method @@ -76,13 +71,21 @@ fn is_allowed_vec_method(cx: &LateContext<'_>, e: &Expr<'_>) -> bool { impl<'tcx> LateLintPass<'tcx> for UselessVec { fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) { - // search for `&vec![_]` expressions where the adjusted type is `&[_]` + // search for `&vec![_]` or `vec![_]` expressions where the adjusted type is `&[_]` if_chain! { if adjusts_to_slice(cx, expr); - if let ExprKind::AddrOf(BorrowKind::Ref, mutability, addressee) = expr.kind; - if let Some(vec_args) = higher::VecArgs::hir(cx, addressee); + if let Some(vec_args) = higher::VecArgs::hir(cx, expr.peel_borrows()); then { - self.check_vec_macro(cx, &vec_args, mutability, expr.span, SuggestSlice::Yes); + let (suggest_slice, span) = if let ExprKind::AddrOf(BorrowKind::Ref, mutability, _) = expr.kind { + // `expr` is `&vec![_]`, so suggest `&[_]` (or `&mut[_]` resp.) + (SuggestedType::SliceRef(mutability), expr.span) + } else { + // `expr` is the `vec![_]` expansion, so suggest `[_]` + // and also use the span of the actual `vec![_]` expression + (SuggestedType::Array, expr.span.ctxt().outer_expn_data().call_site) + }; + + self.check_vec_macro(cx, &vec_args, span, suggest_slice); } } @@ -93,7 +96,7 @@ impl<'tcx> LateLintPass<'tcx> for UselessVec { // for now ignore locals with type annotations. // this is to avoid compile errors when doing the suggestion here: let _: Vec<_> = vec![..]; && local.ty.is_none() - && let PatKind::Binding(BindingAnnotation(_, mutbl), id, ..) = local.pat.kind + && let PatKind::Binding(_, id, ..) = local.pat.kind && is_copy(cx, vec_type(cx.typeck_results().expr_ty_adjusted(expr))) { let only_slice_uses = for_each_local_use_after_expr(cx, id, expr.hir_id, |expr| { @@ -113,9 +116,8 @@ impl<'tcx> LateLintPass<'tcx> for UselessVec { self.check_vec_macro( cx, &vec_args, - mutbl, expr.span.ctxt().outer_expn_data().call_site, - SuggestSlice::No + SuggestedType::Array ); } } @@ -128,7 +130,7 @@ impl<'tcx> LateLintPass<'tcx> for UselessVec { then { // report the error around the `vec!` not inside `:` let span = arg.span.ctxt().outer_expn_data().call_site; - self.check_vec_macro(cx, &vec_args, Mutability::Not, span, SuggestSlice::No); + self.check_vec_macro(cx, &vec_args, span, SuggestedType::Array); } } } @@ -137,11 +139,11 @@ impl<'tcx> LateLintPass<'tcx> for UselessVec { } #[derive(Copy, Clone)] -enum SuggestSlice { +enum SuggestedType { /// Suggest using a slice `&[..]` / `&mut [..]` - Yes, + SliceRef(Mutability), /// Suggest using an array: `[..]` - No, + Array, } impl UselessVec { @@ -149,17 +151,11 @@ impl UselessVec { &mut self, cx: &LateContext<'tcx>, vec_args: &higher::VecArgs<'tcx>, - mutability: Mutability, span: Span, - suggest_slice: SuggestSlice, + suggest_slice: SuggestedType, ) { let mut applicability = Applicability::MachineApplicable; - let (borrow_prefix_mut, borrow_prefix) = match suggest_slice { - SuggestSlice::Yes => ("&mut ", "&"), - SuggestSlice::No => ("", ""), - }; - let snippet = match *vec_args { higher::VecArgs::Repeat(elem, len) => { if let Some(Constant::Int(len_constant)) = constant(cx, cx.typeck_results(), len) { @@ -168,21 +164,13 @@ impl UselessVec { return; } - match mutability { - Mutability::Mut => { - format!( - "{borrow_prefix_mut}[{}; {}]", - snippet_with_applicability(cx, elem.span, "elem", &mut applicability), - snippet_with_applicability(cx, len.span, "len", &mut applicability) - ) - }, - Mutability::Not => { - format!( - "{borrow_prefix}[{}; {}]", - snippet_with_applicability(cx, elem.span, "elem", &mut applicability), - snippet_with_applicability(cx, len.span, "len", &mut applicability) - ) - }, + let elem = snippet_with_applicability(cx, elem.span, "elem", &mut applicability); + let len = snippet_with_applicability(cx, len.span, "len", &mut applicability); + + match suggest_slice { + SuggestedType::SliceRef(Mutability::Mut) => format!("&mut [{elem}; {len}]"), + SuggestedType::SliceRef(Mutability::Not) => format!("&[{elem}; {len}]"), + SuggestedType::Array => format!("[{elem}; {len}]"), } } else { return; @@ -194,25 +182,24 @@ impl UselessVec { return; } let span = args[0].span.to(last.span); + let args = snippet_with_applicability(cx, span, "..", &mut applicability); - match mutability { - Mutability::Mut => { - format!( - "{borrow_prefix_mut}[{}]", - snippet_with_applicability(cx, span, "..", &mut applicability) - ) + match suggest_slice { + SuggestedType::SliceRef(Mutability::Mut) => { + format!("&mut [{args}]") }, - Mutability::Not => { - format!( - "{borrow_prefix}[{}]", - snippet_with_applicability(cx, span, "..", &mut applicability) - ) + SuggestedType::SliceRef(Mutability::Not) => { + format!("&[{args}]") + }, + SuggestedType::Array => { + format!("[{args}]") }, } } else { - match mutability { - Mutability::Mut => format!("{borrow_prefix_mut}[]"), - Mutability::Not => format!("{borrow_prefix}[]"), + match suggest_slice { + SuggestedType::SliceRef(Mutability::Mut) => "&mut []".to_owned(), + SuggestedType::SliceRef(Mutability::Not) => "&[]".to_owned(), + SuggestedType::Array => "[]".to_owned(), } } }, @@ -226,8 +213,8 @@ impl UselessVec { &format!( "you can use {} directly", match suggest_slice { - SuggestSlice::Yes => "a slice", - SuggestSlice::No => "an array", + SuggestedType::SliceRef(_) => "a slice", + SuggestedType::Array => "an array", } ), snippet, From 50ba459987a9b73a2db99e19b774531070a9f5fa Mon Sep 17 00:00:00 2001 From: y21 <30553356+y21@users.noreply.github.com> Date: Mon, 12 Jun 2023 16:04:34 +0200 Subject: [PATCH 155/310] add- and fix existing tests --- tests/ui/cloned_instead_of_copied.fixed | 1 + tests/ui/cloned_instead_of_copied.rs | 1 + tests/ui/cloned_instead_of_copied.stderr | 16 +++--- tests/ui/eta.fixed | 3 +- tests/ui/eta.rs | 3 +- tests/ui/eta.stderr | 52 ++++++++++---------- tests/ui/from_iter_instead_of_collect.fixed | 1 + tests/ui/from_iter_instead_of_collect.rs | 1 + tests/ui/from_iter_instead_of_collect.stderr | 30 +++++------ tests/ui/iter_cloned_collect.fixed | 1 + tests/ui/iter_cloned_collect.rs | 1 + tests/ui/iter_cloned_collect.stderr | 10 ++-- tests/ui/vec.fixed | 3 ++ tests/ui/vec.rs | 3 ++ tests/ui/vec.stderr | 18 ++++--- 15 files changed, 82 insertions(+), 62 deletions(-) diff --git a/tests/ui/cloned_instead_of_copied.fixed b/tests/ui/cloned_instead_of_copied.fixed index b6e09ab3190..34bd2233440 100644 --- a/tests/ui/cloned_instead_of_copied.fixed +++ b/tests/ui/cloned_instead_of_copied.fixed @@ -2,6 +2,7 @@ #![warn(clippy::cloned_instead_of_copied)] #![allow(unused)] +#![allow(clippy::useless_vec)] fn main() { // yay diff --git a/tests/ui/cloned_instead_of_copied.rs b/tests/ui/cloned_instead_of_copied.rs index fa9e1a99613..fa8444937b6 100644 --- a/tests/ui/cloned_instead_of_copied.rs +++ b/tests/ui/cloned_instead_of_copied.rs @@ -2,6 +2,7 @@ #![warn(clippy::cloned_instead_of_copied)] #![allow(unused)] +#![allow(clippy::useless_vec)] fn main() { // yay diff --git a/tests/ui/cloned_instead_of_copied.stderr b/tests/ui/cloned_instead_of_copied.stderr index e0361acd956..3ce482006e9 100644 --- a/tests/ui/cloned_instead_of_copied.stderr +++ b/tests/ui/cloned_instead_of_copied.stderr @@ -1,5 +1,5 @@ error: used `cloned` where `copied` could be used instead - --> $DIR/cloned_instead_of_copied.rs:8:24 + --> $DIR/cloned_instead_of_copied.rs:9:24 | LL | let _ = [1].iter().cloned(); | ^^^^^^ help: try: `copied` @@ -7,43 +7,43 @@ LL | let _ = [1].iter().cloned(); = note: `-D clippy::cloned-instead-of-copied` implied by `-D warnings` error: used `cloned` where `copied` could be used instead - --> $DIR/cloned_instead_of_copied.rs:9:31 + --> $DIR/cloned_instead_of_copied.rs:10:31 | LL | let _ = vec!["hi"].iter().cloned(); | ^^^^^^ help: try: `copied` error: used `cloned` where `copied` could be used instead - --> $DIR/cloned_instead_of_copied.rs:10:22 + --> $DIR/cloned_instead_of_copied.rs:11:22 | LL | let _ = Some(&1).cloned(); | ^^^^^^ help: try: `copied` error: used `cloned` where `copied` could be used instead - --> $DIR/cloned_instead_of_copied.rs:11:34 + --> $DIR/cloned_instead_of_copied.rs:12:34 | LL | let _ = Box::new([1].iter()).cloned(); | ^^^^^^ help: try: `copied` error: used `cloned` where `copied` could be used instead - --> $DIR/cloned_instead_of_copied.rs:12:32 + --> $DIR/cloned_instead_of_copied.rs:13:32 | LL | let _ = Box::new(Some(&1)).cloned(); | ^^^^^^ help: try: `copied` error: used `cloned` where `copied` could be used instead - --> $DIR/cloned_instead_of_copied.rs:28:22 + --> $DIR/cloned_instead_of_copied.rs:29:22 | LL | let _ = Some(&1).cloned(); // Option::copied needs 1.35 | ^^^^^^ help: try: `copied` error: used `cloned` where `copied` could be used instead - --> $DIR/cloned_instead_of_copied.rs:33:24 + --> $DIR/cloned_instead_of_copied.rs:34:24 | LL | let _ = [1].iter().cloned(); // Iterator::copied needs 1.36 | ^^^^^^ help: try: `copied` error: used `cloned` where `copied` could be used instead - --> $DIR/cloned_instead_of_copied.rs:34:22 + --> $DIR/cloned_instead_of_copied.rs:35:22 | LL | let _ = Some(&1).cloned(); | ^^^^^^ help: try: `copied` diff --git a/tests/ui/eta.fixed b/tests/ui/eta.fixed index 31a94cb10e8..bf44bcb564e 100644 --- a/tests/ui/eta.fixed +++ b/tests/ui/eta.fixed @@ -7,7 +7,8 @@ clippy::no_effect, clippy::option_map_unit_fn, clippy::redundant_closure_call, - clippy::uninlined_format_args + clippy::uninlined_format_args, + clippy::useless_vec )] use std::path::{Path, PathBuf}; diff --git a/tests/ui/eta.rs b/tests/ui/eta.rs index 978aecd24b3..b2af4bf0953 100644 --- a/tests/ui/eta.rs +++ b/tests/ui/eta.rs @@ -7,7 +7,8 @@ clippy::no_effect, clippy::option_map_unit_fn, clippy::redundant_closure_call, - clippy::uninlined_format_args + clippy::uninlined_format_args, + clippy::useless_vec )] use std::path::{Path, PathBuf}; diff --git a/tests/ui/eta.stderr b/tests/ui/eta.stderr index 19be5fc7389..0ac0b901df4 100644 --- a/tests/ui/eta.stderr +++ b/tests/ui/eta.stderr @@ -1,5 +1,5 @@ error: redundant closure - --> $DIR/eta.rs:28:27 + --> $DIR/eta.rs:29:27 | LL | let a = Some(1u8).map(|a| foo(a)); | ^^^^^^^^^^ help: replace the closure with the function itself: `foo` @@ -7,31 +7,31 @@ LL | let a = Some(1u8).map(|a| foo(a)); = note: `-D clippy::redundant-closure` implied by `-D warnings` error: redundant closure - --> $DIR/eta.rs:32:40 + --> $DIR/eta.rs:33:40 | LL | let _: Option> = true.then(|| vec![]); // special case vec! | ^^^^^^^^^ help: replace the closure with `Vec::new`: `std::vec::Vec::new` error: redundant closure - --> $DIR/eta.rs:33:35 + --> $DIR/eta.rs:34:35 | LL | let d = Some(1u8).map(|a| foo((|b| foo2(b))(a))); //is adjusted? | ^^^^^^^^^^^^^ help: replace the closure with the function itself: `foo2` error: redundant closure - --> $DIR/eta.rs:34:26 + --> $DIR/eta.rs:35:26 | LL | all(&[1, 2, 3], &&2, |x, y| below(x, y)); //is adjusted | ^^^^^^^^^^^^^^^^^^ help: replace the closure with the function itself: `below` error: redundant closure - --> $DIR/eta.rs:41:27 + --> $DIR/eta.rs:42:27 | LL | let e = Some(1u8).map(|a| generic(a)); | ^^^^^^^^^^^^^^ help: replace the closure with the function itself: `generic` error: redundant closure - --> $DIR/eta.rs:93:51 + --> $DIR/eta.rs:94:51 | LL | let e = Some(TestStruct { some_ref: &i }).map(|a| a.foo()); | ^^^^^^^^^^^ help: replace the closure with the method itself: `TestStruct::foo` @@ -39,121 +39,121 @@ LL | let e = Some(TestStruct { some_ref: &i }).map(|a| a.foo()); = note: `-D clippy::redundant-closure-for-method-calls` implied by `-D warnings` error: redundant closure - --> $DIR/eta.rs:94:51 + --> $DIR/eta.rs:95:51 | LL | let e = Some(TestStruct { some_ref: &i }).map(|a| a.trait_foo()); | ^^^^^^^^^^^^^^^^^ help: replace the closure with the method itself: `TestTrait::trait_foo` error: redundant closure - --> $DIR/eta.rs:96:42 + --> $DIR/eta.rs:97:42 | LL | let e = Some(&mut vec![1, 2, 3]).map(|v| v.clear()); | ^^^^^^^^^^^^^ help: replace the closure with the method itself: `std::vec::Vec::clear` error: redundant closure - --> $DIR/eta.rs:100:29 + --> $DIR/eta.rs:101:29 | LL | let e = Some("str").map(|s| s.to_string()); | ^^^^^^^^^^^^^^^^^ help: replace the closure with the method itself: `std::string::ToString::to_string` error: redundant closure - --> $DIR/eta.rs:101:27 + --> $DIR/eta.rs:102:27 | LL | let e = Some('a').map(|s| s.to_uppercase()); | ^^^^^^^^^^^^^^^^^^^^ help: replace the closure with the method itself: `char::to_uppercase` error: redundant closure - --> $DIR/eta.rs:103:65 + --> $DIR/eta.rs:104:65 | LL | let e: std::vec::Vec = vec!['a', 'b', 'c'].iter().map(|c| c.to_ascii_uppercase()).collect(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace the closure with the method itself: `char::to_ascii_uppercase` error: redundant closure - --> $DIR/eta.rs:166:22 + --> $DIR/eta.rs:167:22 | LL | requires_fn_once(|| x()); | ^^^^^^ help: replace the closure with the function itself: `x` error: redundant closure - --> $DIR/eta.rs:173:27 + --> $DIR/eta.rs:174:27 | LL | let a = Some(1u8).map(|a| foo_ptr(a)); | ^^^^^^^^^^^^^^ help: replace the closure with the function itself: `foo_ptr` error: redundant closure - --> $DIR/eta.rs:178:27 + --> $DIR/eta.rs:179:27 | LL | let a = Some(1u8).map(|a| closure(a)); | ^^^^^^^^^^^^^^ help: replace the closure with the function itself: `closure` error: redundant closure - --> $DIR/eta.rs:210:28 + --> $DIR/eta.rs:211:28 | LL | x.into_iter().for_each(|x| add_to_res(x)); | ^^^^^^^^^^^^^^^^^ help: replace the closure with the function itself: `&mut add_to_res` error: redundant closure - --> $DIR/eta.rs:211:28 + --> $DIR/eta.rs:212:28 | LL | y.into_iter().for_each(|x| add_to_res(x)); | ^^^^^^^^^^^^^^^^^ help: replace the closure with the function itself: `&mut add_to_res` error: redundant closure - --> $DIR/eta.rs:212:28 + --> $DIR/eta.rs:213:28 | LL | z.into_iter().for_each(|x| add_to_res(x)); | ^^^^^^^^^^^^^^^^^ help: replace the closure with the function itself: `add_to_res` error: redundant closure - --> $DIR/eta.rs:219:21 + --> $DIR/eta.rs:220:21 | LL | Some(1).map(|n| closure(n)); | ^^^^^^^^^^^^^^ help: replace the closure with the function itself: `&mut closure` error: redundant closure - --> $DIR/eta.rs:223:21 + --> $DIR/eta.rs:224:21 | LL | Some(1).map(|n| in_loop(n)); | ^^^^^^^^^^^^^^ help: replace the closure with the function itself: `in_loop` error: redundant closure - --> $DIR/eta.rs:316:18 + --> $DIR/eta.rs:317:18 | LL | takes_fn_mut(|| f()); | ^^^^^^ help: replace the closure with the function itself: `&mut f` error: redundant closure - --> $DIR/eta.rs:319:19 + --> $DIR/eta.rs:320:19 | LL | takes_fn_once(|| f()); | ^^^^^^ help: replace the closure with the function itself: `&mut f` error: redundant closure - --> $DIR/eta.rs:323:26 + --> $DIR/eta.rs:324:26 | LL | move || takes_fn_mut(|| f_used_once()) | ^^^^^^^^^^^^^^^^ help: replace the closure with the function itself: `&mut f_used_once` error: redundant closure - --> $DIR/eta.rs:335:19 + --> $DIR/eta.rs:336:19 | LL | array_opt.map(|a| a.as_slice()); | ^^^^^^^^^^^^^^^^ help: replace the closure with the method itself: `<[u8; 3]>::as_slice` error: redundant closure - --> $DIR/eta.rs:338:19 + --> $DIR/eta.rs:339:19 | LL | slice_opt.map(|s| s.len()); | ^^^^^^^^^^^ help: replace the closure with the method itself: `<[u8]>::len` error: redundant closure - --> $DIR/eta.rs:341:17 + --> $DIR/eta.rs:342:17 | LL | ptr_opt.map(|p| p.is_null()); | ^^^^^^^^^^^^^^^ help: replace the closure with the method itself: `<*const usize>::is_null` error: redundant closure - --> $DIR/eta.rs:345:17 + --> $DIR/eta.rs:346:17 | LL | dyn_opt.map(|d| d.method_on_dyn()); | ^^^^^^^^^^^^^^^^^^^^^ help: replace the closure with the method itself: `::method_on_dyn` diff --git a/tests/ui/from_iter_instead_of_collect.fixed b/tests/ui/from_iter_instead_of_collect.fixed index 915ff4fb079..1671987cb67 100644 --- a/tests/ui/from_iter_instead_of_collect.fixed +++ b/tests/ui/from_iter_instead_of_collect.fixed @@ -2,6 +2,7 @@ #![warn(clippy::from_iter_instead_of_collect)] #![allow(unused_imports, unused_tuple_struct_fields)] +#![allow(clippy::useless_vec)] use std::collections::{BTreeMap, BTreeSet, HashMap, VecDeque}; diff --git a/tests/ui/from_iter_instead_of_collect.rs b/tests/ui/from_iter_instead_of_collect.rs index e926f8c529d..48509b32f10 100644 --- a/tests/ui/from_iter_instead_of_collect.rs +++ b/tests/ui/from_iter_instead_of_collect.rs @@ -2,6 +2,7 @@ #![warn(clippy::from_iter_instead_of_collect)] #![allow(unused_imports, unused_tuple_struct_fields)] +#![allow(clippy::useless_vec)] use std::collections::{BTreeMap, BTreeSet, HashMap, VecDeque}; diff --git a/tests/ui/from_iter_instead_of_collect.stderr b/tests/ui/from_iter_instead_of_collect.stderr index 8aa3c3c01f8..8f08ac8c3ff 100644 --- a/tests/ui/from_iter_instead_of_collect.stderr +++ b/tests/ui/from_iter_instead_of_collect.stderr @@ -1,5 +1,5 @@ error: usage of `FromIterator::from_iter` - --> $DIR/from_iter_instead_of_collect.rs:18:9 + --> $DIR/from_iter_instead_of_collect.rs:19:9 | LL | >::from_iter(iter.into_iter().copied()) | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `.collect()` instead of `::from_iter()`: `iter.into_iter().copied().collect::()` @@ -7,85 +7,85 @@ LL | >::from_iter(iter.into_iter().copied()) = note: `-D clippy::from-iter-instead-of-collect` implied by `-D warnings` error: usage of `FromIterator::from_iter` - --> $DIR/from_iter_instead_of_collect.rs:24:13 + --> $DIR/from_iter_instead_of_collect.rs:25:13 | LL | let _ = Vec::from_iter(iter_expr); | ^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `.collect()` instead of `::from_iter()`: `iter_expr.collect::>()` error: usage of `FromIterator::from_iter` - --> $DIR/from_iter_instead_of_collect.rs:26:13 + --> $DIR/from_iter_instead_of_collect.rs:27:13 | LL | let _ = HashMap::::from_iter(vec![5, 5, 5, 5].iter().enumerate()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `.collect()` instead of `::from_iter()`: `vec![5, 5, 5, 5].iter().enumerate().collect::>()` error: usage of `FromIterator::from_iter` - --> $DIR/from_iter_instead_of_collect.rs:31:19 + --> $DIR/from_iter_instead_of_collect.rs:32:19 | LL | assert_eq!(a, Vec::from_iter(0..3)); | ^^^^^^^^^^^^^^^^^^^^ help: use `.collect()` instead of `::from_iter()`: `(0..3).collect::>()` error: usage of `FromIterator::from_iter` - --> $DIR/from_iter_instead_of_collect.rs:32:19 + --> $DIR/from_iter_instead_of_collect.rs:33:19 | LL | assert_eq!(a, Vec::::from_iter(0..3)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `.collect()` instead of `::from_iter()`: `(0..3).collect::>()` error: usage of `FromIterator::from_iter` - --> $DIR/from_iter_instead_of_collect.rs:34:17 + --> $DIR/from_iter_instead_of_collect.rs:35:17 | LL | let mut b = VecDeque::from_iter(0..3); | ^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `.collect()` instead of `::from_iter()`: `(0..3).collect::>()` error: usage of `FromIterator::from_iter` - --> $DIR/from_iter_instead_of_collect.rs:37:17 + --> $DIR/from_iter_instead_of_collect.rs:38:17 | LL | let mut b = VecDeque::::from_iter(0..3); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `.collect()` instead of `::from_iter()`: `(0..3).collect::>()` error: usage of `FromIterator::from_iter` - --> $DIR/from_iter_instead_of_collect.rs:42:21 + --> $DIR/from_iter_instead_of_collect.rs:43:21 | LL | let mut b = collections::VecDeque::::from_iter(0..3); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `.collect()` instead of `::from_iter()`: `(0..3).collect::>()` error: usage of `FromIterator::from_iter` - --> $DIR/from_iter_instead_of_collect.rs:47:14 + --> $DIR/from_iter_instead_of_collect.rs:48:14 | LL | let bm = BTreeMap::from_iter(values.iter().cloned()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `.collect()` instead of `::from_iter()`: `values.iter().cloned().collect::>()` error: usage of `FromIterator::from_iter` - --> $DIR/from_iter_instead_of_collect.rs:48:19 + --> $DIR/from_iter_instead_of_collect.rs:49:19 | LL | let mut bar = BTreeMap::from_iter(bm.range(0..2)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `.collect()` instead of `::from_iter()`: `bm.range(0..2).collect::>()` error: usage of `FromIterator::from_iter` - --> $DIR/from_iter_instead_of_collect.rs:51:19 + --> $DIR/from_iter_instead_of_collect.rs:52:19 | LL | let mut bts = BTreeSet::from_iter(0..3); | ^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `.collect()` instead of `::from_iter()`: `(0..3).collect::>()` error: usage of `FromIterator::from_iter` - --> $DIR/from_iter_instead_of_collect.rs:55:17 + --> $DIR/from_iter_instead_of_collect.rs:56:17 | LL | let _ = collections::BTreeSet::from_iter(0..3); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `.collect()` instead of `::from_iter()`: `(0..3).collect::>()` error: usage of `FromIterator::from_iter` - --> $DIR/from_iter_instead_of_collect.rs:56:17 + --> $DIR/from_iter_instead_of_collect.rs:57:17 | LL | let _ = collections::BTreeSet::::from_iter(0..3); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `.collect()` instead of `::from_iter()`: `(0..3).collect::>()` error: usage of `FromIterator::from_iter` - --> $DIR/from_iter_instead_of_collect.rs:59:15 + --> $DIR/from_iter_instead_of_collect.rs:60:15 | LL | for _i in Vec::from_iter([1, 2, 3].iter()) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `.collect()` instead of `::from_iter()`: `[1, 2, 3].iter().collect::>()` error: usage of `FromIterator::from_iter` - --> $DIR/from_iter_instead_of_collect.rs:60:15 + --> $DIR/from_iter_instead_of_collect.rs:61:15 | LL | for _i in Vec::<&i32>::from_iter([1, 2, 3].iter()) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `.collect()` instead of `::from_iter()`: `[1, 2, 3].iter().collect::>()` diff --git a/tests/ui/iter_cloned_collect.fixed b/tests/ui/iter_cloned_collect.fixed index 88f08bb991b..2baea06f84b 100644 --- a/tests/ui/iter_cloned_collect.fixed +++ b/tests/ui/iter_cloned_collect.fixed @@ -1,6 +1,7 @@ //@run-rustfix #![allow(unused)] +#![allow(clippy::useless_vec)] use std::collections::HashSet; use std::collections::VecDeque; diff --git a/tests/ui/iter_cloned_collect.rs b/tests/ui/iter_cloned_collect.rs index d3438b7f51a..9eac94eb8d9 100644 --- a/tests/ui/iter_cloned_collect.rs +++ b/tests/ui/iter_cloned_collect.rs @@ -1,6 +1,7 @@ //@run-rustfix #![allow(unused)] +#![allow(clippy::useless_vec)] use std::collections::HashSet; use std::collections::VecDeque; diff --git a/tests/ui/iter_cloned_collect.stderr b/tests/ui/iter_cloned_collect.stderr index b2cc497bf43..b38cf547dc5 100644 --- a/tests/ui/iter_cloned_collect.stderr +++ b/tests/ui/iter_cloned_collect.stderr @@ -1,5 +1,5 @@ error: called `iter().cloned().collect()` on a slice to create a `Vec`. Calling `to_vec()` is both faster and more readable - --> $DIR/iter_cloned_collect.rs:10:27 + --> $DIR/iter_cloned_collect.rs:11:27 | LL | let v2: Vec = v.iter().cloned().collect(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `.to_vec()` @@ -7,13 +7,13 @@ LL | let v2: Vec = v.iter().cloned().collect(); = note: `-D clippy::iter-cloned-collect` implied by `-D warnings` error: called `iter().cloned().collect()` on a slice to create a `Vec`. Calling `to_vec()` is both faster and more readable - --> $DIR/iter_cloned_collect.rs:15:38 + --> $DIR/iter_cloned_collect.rs:16:38 | LL | let _: Vec = vec![1, 2, 3].iter().cloned().collect(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `.to_vec()` error: called `iter().cloned().collect()` on a slice to create a `Vec`. Calling `to_vec()` is both faster and more readable - --> $DIR/iter_cloned_collect.rs:20:24 + --> $DIR/iter_cloned_collect.rs:21:24 | LL | .to_bytes() | ________________________^ @@ -23,13 +23,13 @@ LL | | .collect(); | |______________________^ help: try: `.to_vec()` error: called `iter().cloned().collect()` on a slice to create a `Vec`. Calling `to_vec()` is both faster and more readable - --> $DIR/iter_cloned_collect.rs:28:24 + --> $DIR/iter_cloned_collect.rs:29:24 | LL | let _: Vec<_> = arr.iter().cloned().collect(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `.to_vec()` error: called `iter().copied().collect()` on a slice to create a `Vec`. Calling `to_vec()` is both faster and more readable - --> $DIR/iter_cloned_collect.rs:31:26 + --> $DIR/iter_cloned_collect.rs:32:26 | LL | let _: Vec = v.iter().copied().collect(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `.to_vec()` diff --git a/tests/ui/vec.fixed b/tests/ui/vec.fixed index 55329ee843d..fcdc917c1b1 100644 --- a/tests/ui/vec.fixed +++ b/tests/ui/vec.fixed @@ -71,6 +71,9 @@ fn main() { println!("{:?}", a); } + // https://github.com/rust-lang/rust-clippy/issues/2262#issuecomment-783979246 + let _x: i32 = [1, 2, 3].iter().sum(); + // Do lint let mut x = [1, 2, 3]; x.fill(123); diff --git a/tests/ui/vec.rs b/tests/ui/vec.rs index bab316fa620..0404d8cdb84 100644 --- a/tests/ui/vec.rs +++ b/tests/ui/vec.rs @@ -71,6 +71,9 @@ fn main() { println!("{:?}", a); } + // https://github.com/rust-lang/rust-clippy/issues/2262#issuecomment-783979246 + let _x: i32 = vec![1, 2, 3].iter().sum(); + // Do lint let mut x = vec![1, 2, 3]; x.fill(123); diff --git a/tests/ui/vec.stderr b/tests/ui/vec.stderr index f3a4bf925dd..33d565b2d52 100644 --- a/tests/ui/vec.stderr +++ b/tests/ui/vec.stderr @@ -61,34 +61,40 @@ LL | on_mut_slice(&mut vec![1; 2]); | ^^^^^^^^^^^^^^^ help: you can use a slice directly: `&mut [1; 2]` error: useless use of `vec!` - --> $DIR/vec.rs:75:17 + --> $DIR/vec.rs:75:19 + | +LL | let _x: i32 = vec![1, 2, 3].iter().sum(); + | ^^^^^^^^^^^^^ help: you can use an array directly: `[1, 2, 3]` + +error: useless use of `vec!` + --> $DIR/vec.rs:78:17 | LL | let mut x = vec![1, 2, 3]; | ^^^^^^^^^^^^^ help: you can use an array directly: `[1, 2, 3]` error: useless use of `vec!` - --> $DIR/vec.rs:81:22 + --> $DIR/vec.rs:84:22 | LL | let _x: &[i32] = &vec![1, 2, 3]; | ^^^^^^^^^^^^^^ help: you can use a slice directly: `&[1, 2, 3]` error: useless use of `vec!` - --> $DIR/vec.rs:83:14 + --> $DIR/vec.rs:86:14 | LL | for _ in vec![1, 2, 3] {} | ^^^^^^^^^^^^^ help: you can use an array directly: `[1, 2, 3]` error: useless use of `vec!` - --> $DIR/vec.rs:117:14 + --> $DIR/vec.rs:120:14 | LL | for a in vec![1, 2, 3] { | ^^^^^^^^^^^^^ help: you can use an array directly: `[1, 2, 3]` error: useless use of `vec!` - --> $DIR/vec.rs:121:14 + --> $DIR/vec.rs:124:14 | LL | for a in vec![String::new(), String::new()] { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: you can use an array directly: `[String::new(), String::new()]` -error: aborting due to 15 previous errors +error: aborting due to 16 previous errors From 5e20a572ee6ee956fa74bb63ff9d9ccd45611c8d Mon Sep 17 00:00:00 2001 From: Alex Macleod Date: Mon, 12 Jun 2023 15:05:14 +0000 Subject: [PATCH 156/310] Don't lint non-statement/faux empty `needless_if`s --- clippy_lints/src/needless_if.rs | 78 +++++++++++---------------------- tests/ui/needless_if.fixed | 65 ++++++++++++++++++++------- tests/ui/needless_if.rs | 56 ++++++++++++++++++----- tests/ui/needless_if.stderr | 56 +++++++++++++++++------ 4 files changed, 161 insertions(+), 94 deletions(-) diff --git a/clippy_lints/src/needless_if.rs b/clippy_lints/src/needless_if.rs index dbffbd6f0d3..ad5c3e1dc82 100644 --- a/clippy_lints/src/needless_if.rs +++ b/clippy_lints/src/needless_if.rs @@ -1,9 +1,6 @@ -use clippy_utils::{diagnostics::span_lint_and_sugg, is_from_proc_macro, source::snippet_with_applicability}; +use clippy_utils::{diagnostics::span_lint_and_sugg, higher::If, is_from_proc_macro, source::snippet_opt}; use rustc_errors::Applicability; -use rustc_hir::{ - intravisit::{walk_expr, Visitor}, - Expr, ExprKind, Node, -}; +use rustc_hir::{ExprKind, Stmt, StmtKind}; use rustc_lint::{LateContext, LateLintPass, LintContext}; use rustc_middle::lint::in_external_macro; use rustc_session::{declare_lint_pass, declare_tool_lint}; @@ -37,67 +34,42 @@ declare_clippy_lint! { declare_lint_pass!(NeedlessIf => [NEEDLESS_IF]); impl LateLintPass<'_> for NeedlessIf { - fn check_expr<'tcx>(&mut self, cx: &LateContext<'tcx>, expr: &Expr<'tcx>) { - if let ExprKind::If(if_expr, block, else_expr) = &expr.kind - && let ExprKind::Block(block, ..) = block.kind + fn check_stmt<'tcx>(&mut self, cx: &LateContext<'tcx>, stmt: &Stmt<'tcx>) { + if let StmtKind::Expr(expr) = stmt.kind + && let Some(If {cond, then, r#else: None }) = If::hir(expr) + && let ExprKind::Block(block, ..) = then.kind && block.stmts.is_empty() && block.expr.is_none() - && else_expr.is_none() && !in_external_macro(cx.sess(), expr.span) + && !is_from_proc_macro(cx, expr) + && let Some(then_snippet) = snippet_opt(cx, then.span) + // Ignore + // - empty macro expansions + // - empty reptitions in macro expansions + // - comments + // - #[cfg]'d out code + && then_snippet.chars().all(|ch| matches!(ch, '{' | '}') || ch.is_ascii_whitespace()) + && let Some(cond_snippet) = snippet_opt(cx, cond.span) { - // Ignore `else if` - if let Some(parent_id) = cx.tcx.hir().opt_parent_id(expr.hir_id) - && let Some(Node::Expr(Expr { - kind: ExprKind::If(_, _, Some(else_expr)), - .. - })) = cx.tcx.hir().find(parent_id) - && else_expr.hir_id == expr.hir_id - { - return; - } - - if is_any_if_let(if_expr) || is_from_proc_macro(cx, expr) { - return; - } - - let mut app = Applicability::MachineApplicable; - let snippet = snippet_with_applicability(cx, if_expr.span, "{ ... }", &mut app); - span_lint_and_sugg( cx, NEEDLESS_IF, - expr.span, + stmt.span, "this `if` branch is empty", "you can remove it", - if if_expr.can_have_side_effects() { - format!("{snippet};") + if cond.can_have_side_effects() || !cx.tcx.hir().attrs(stmt.hir_id).is_empty() { + // `{ foo }` or `{ foo } && bar` placed into a statement position would be + // interpreted as a block statement, force it to be an expression + if cond_snippet.starts_with('{') { + format!("({cond_snippet});") + } else { + format!("{cond_snippet};") + } } else { String::new() }, - app, + Applicability::MachineApplicable, ); } } } - -/// Returns true if any `Expr` contained within this `Expr` is a `Let`, else false. -/// -/// Really wish `Expr` had a `walk` method... -fn is_any_if_let(expr: &Expr<'_>) -> bool { - let mut v = IsAnyLetVisitor(false); - - v.visit_expr(expr); - v.0 -} - -struct IsAnyLetVisitor(bool); - -impl Visitor<'_> for IsAnyLetVisitor { - fn visit_expr(&mut self, expr: &Expr<'_>) { - if matches!(expr.kind, ExprKind::Let(..)) { - self.0 = true; - } else { - walk_expr(self, expr); - } - } -} diff --git a/tests/ui/needless_if.fixed b/tests/ui/needless_if.fixed index bee579be1bf..8fd945f1a54 100644 --- a/tests/ui/needless_if.fixed +++ b/tests/ui/needless_if.fixed @@ -5,9 +5,12 @@ clippy::blocks_in_if_conditions, clippy::if_same_then_else, clippy::ifs_same_cond, + clippy::let_unit_value, clippy::needless_else, clippy::no_effect, clippy::nonminimal_bool, + clippy::short_circuit_statement, + clippy::unnecessary_operation, unused )] #![warn(clippy::needless_if)] @@ -16,12 +19,7 @@ extern crate proc_macros; use proc_macros::external; use proc_macros::with_span; -fn no_side_effects() -> bool { - true -} - -fn has_side_effects(a: &mut u32) -> bool { - *a = 1; +fn maybe_side_effect() -> bool { true } @@ -29,32 +27,67 @@ fn main() { // Lint // Do not remove the condition - no_side_effects(); - let mut x = 0; - has_side_effects(&mut x); - assert_eq!(x, 1); + maybe_side_effect(); // Do not lint if (true) { } else { } - { + ({ return; - }; + }); // Do not lint if `else if` is present if (true) { } else if (true) { } - // Do not lint if any `let` is present + // Do not lint `if let` or let chains if let true = true {} if let true = true && true {} if true && let true = true {} - if { + // Can lint nested `if let`s + ({ if let true = true && true { true } else { false } - } && true - {} + } && true); external! { if (true) {} } with_span! { span if (true) {} } + + if true { + // comment + } + + if true { + #[cfg(any())] + foo; + } + + macro_rules! empty_expansion { + () => {}; + } + + if true { + empty_expansion!(); + } + + macro_rules! empty_repetition { + ($($t:tt)*) => { + if true { + $($t)* + } + } + } + + empty_repetition!(); + + // Must be placed into an expression context to not be interpreted as a block + ({ maybe_side_effect() }); + // Would be a block followed by `&&true` - a double reference to `true` + ({ maybe_side_effect() } && true); + + // Don't leave trailing attributes + #[allow(unused)] + true; + + let () = if maybe_side_effect() {}; } diff --git a/tests/ui/needless_if.rs b/tests/ui/needless_if.rs index 1608d261a36..04868299a54 100644 --- a/tests/ui/needless_if.rs +++ b/tests/ui/needless_if.rs @@ -5,9 +5,12 @@ clippy::blocks_in_if_conditions, clippy::if_same_then_else, clippy::ifs_same_cond, + clippy::let_unit_value, clippy::needless_else, clippy::no_effect, clippy::nonminimal_bool, + clippy::short_circuit_statement, + clippy::unnecessary_operation, unused )] #![warn(clippy::needless_if)] @@ -16,12 +19,7 @@ extern crate proc_macros; use proc_macros::external; use proc_macros::with_span; -fn no_side_effects() -> bool { - true -} - -fn has_side_effects(a: &mut u32) -> bool { - *a = 1; +fn maybe_side_effect() -> bool { true } @@ -29,10 +27,7 @@ fn main() { // Lint if (true) {} // Do not remove the condition - if no_side_effects() {} - let mut x = 0; - if has_side_effects(&mut x) {} - assert_eq!(x, 1); + if maybe_side_effect() {} // Do not lint if (true) { } else { @@ -44,10 +39,11 @@ fn main() { if (true) { } else if (true) { } - // Do not lint if any `let` is present + // Do not lint `if let` or let chains if let true = true {} if let true = true && true {} if true && let true = true {} + // Can lint nested `if let`s if { if let true = true && true { true } else { false } } && true @@ -57,4 +53,42 @@ fn main() { span if (true) {} } + + if true { + // comment + } + + if true { + #[cfg(any())] + foo; + } + + macro_rules! empty_expansion { + () => {}; + } + + if true { + empty_expansion!(); + } + + macro_rules! empty_repetition { + ($($t:tt)*) => { + if true { + $($t)* + } + } + } + + empty_repetition!(); + + // Must be placed into an expression context to not be interpreted as a block + if { maybe_side_effect() } {} + // Would be a block followed by `&&true` - a double reference to `true` + if { maybe_side_effect() } && true {} + + // Don't leave trailing attributes + #[allow(unused)] + if true {} + + let () = if maybe_side_effect() {}; } diff --git a/tests/ui/needless_if.stderr b/tests/ui/needless_if.stderr index 4236b0053eb..5cb42c36921 100644 --- a/tests/ui/needless_if.stderr +++ b/tests/ui/needless_if.stderr @@ -1,5 +1,5 @@ error: this `if` branch is empty - --> $DIR/needless_if.rs:30:5 + --> $DIR/needless_if.rs:28:5 | LL | if (true) {} | ^^^^^^^^^^^^ help: you can remove it @@ -7,19 +7,13 @@ LL | if (true) {} = note: `-D clippy::needless-if` implied by `-D warnings` error: this `if` branch is empty - --> $DIR/needless_if.rs:32:5 + --> $DIR/needless_if.rs:30:5 | -LL | if no_side_effects() {} - | ^^^^^^^^^^^^^^^^^^^^^^^ help: you can remove it: `no_side_effects();` +LL | if maybe_side_effect() {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^ help: you can remove it: `maybe_side_effect();` error: this `if` branch is empty - --> $DIR/needless_if.rs:34:5 - | -LL | if has_side_effects(&mut x) {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: you can remove it: `has_side_effects(&mut x);` - -error: this `if` branch is empty - --> $DIR/needless_if.rs:40:5 + --> $DIR/needless_if.rs:35:5 | LL | / if { LL | | return; @@ -28,10 +22,44 @@ LL | | } {} | help: you can remove it | -LL ~ { +LL ~ ({ LL + return; -LL + }; +LL + }); | -error: aborting due to 4 previous errors +error: this `if` branch is empty + --> $DIR/needless_if.rs:47:5 + | +LL | / if { +LL | | if let true = true && true { true } else { false } +LL | | } && true +LL | | {} + | |______^ + | +help: you can remove it + | +LL ~ ({ +LL + if let true = true && true { true } else { false } +LL + } && true); + | + +error: this `if` branch is empty + --> $DIR/needless_if.rs:85:5 + | +LL | if { maybe_side_effect() } {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: you can remove it: `({ maybe_side_effect() });` + +error: this `if` branch is empty + --> $DIR/needless_if.rs:87:5 + | +LL | if { maybe_side_effect() } && true {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: you can remove it: `({ maybe_side_effect() } && true);` + +error: this `if` branch is empty + --> $DIR/needless_if.rs:91:5 + | +LL | if true {} + | ^^^^^^^^^^ help: you can remove it: `true;` + +error: aborting due to 7 previous errors From 1af23d246362451faa2ff6fd3e5de5a6e5dd549a Mon Sep 17 00:00:00 2001 From: rsdy Date: Thu, 16 Feb 2023 10:47:12 +0000 Subject: [PATCH 157/310] Add test code --- tests/ui/unwrap_literal.rs | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) create mode 100644 tests/ui/unwrap_literal.rs diff --git a/tests/ui/unwrap_literal.rs b/tests/ui/unwrap_literal.rs new file mode 100644 index 00000000000..917ef2126f5 --- /dev/null +++ b/tests/ui/unwrap_literal.rs @@ -0,0 +1,17 @@ +#![warn(clippy::unnecessary_unwrap)] + +fn unwrap_option() { + let val = Some(1).unwrap(); + let val = Some(1).expect("this never happens"); +} + +fn unwrap_result() { + let val = Ok(1).unwrap(); + let val = Err(1).unwrap_err(); + let val = Ok(1).expect("this never happens"); +} + +fn main() { + unwrap_option(); + unwrap_result(); +} From e707447a861739fa3e12e9c05c039c8c9c6b0544 Mon Sep 17 00:00:00 2001 From: Pavan Kumar Sunkara Date: Thu, 16 Feb 2023 11:32:12 +0000 Subject: [PATCH 158/310] Boilerplate for the new lint --- clippy_lints/src/methods/mod.rs | 52 +++++++++++++++++++ .../src/methods/unnecessary_literal_unwrap.rs | 30 +++++++++++ tests/ui/unnecessary_literal_unwrap.rs | 10 ++++ tests/ui/unwrap_literal.rs | 17 ------ 4 files changed, 92 insertions(+), 17 deletions(-) create mode 100644 clippy_lints/src/methods/unnecessary_literal_unwrap.rs create mode 100644 tests/ui/unnecessary_literal_unwrap.rs delete mode 100644 tests/ui/unwrap_literal.rs diff --git a/clippy_lints/src/methods/mod.rs b/clippy_lints/src/methods/mod.rs index 88cbefbb5d3..f24f00ef6a7 100644 --- a/clippy_lints/src/methods/mod.rs +++ b/clippy_lints/src/methods/mod.rs @@ -93,6 +93,7 @@ mod unnecessary_fold; mod unnecessary_iter_cloned; mod unnecessary_join; mod unnecessary_lazy_eval; +mod unnecessary_literal_unwrap; mod unnecessary_sort_by; mod unnecessary_to_owned; mod unwrap_or_else_default; @@ -273,6 +274,56 @@ declare_clippy_lint! { "using `.unwrap()` on `Result` or `Option`, which should at least get a better message using `expect()`" } +declare_clippy_lint! { + /// ### What it does + /// Checks for `.unwrap()` or `.unwrap_err()` calls on `Result`s and `.unwrap()` call on `Option`s. + /// + /// ### Why is this bad? + /// It is better to handle the `None` or `Err` case, + /// or at least call `.expect(_)` with a more helpful message. Still, for a lot of + /// quick-and-dirty code, `unwrap` is a good choice, which is why this lint is + /// `Allow` by default. + /// + /// `result.unwrap()` will let the thread panic on `Err` values. + /// Normally, you want to implement more sophisticated error handling, + /// and propagate errors upwards with `?` operator. + /// + /// Even if you want to panic on errors, not all `Error`s implement good + /// messages on display. Therefore, it may be beneficial to look at the places + /// where they may get displayed. Activate this lint to do just that. + /// + /// ### Examples + /// ```rust + /// # let option = Some(1); + /// # let result: Result = Ok(1); + /// option.unwrap(); + /// result.unwrap(); + /// ``` + /// + /// Use instead: + /// ```rust + /// # let option = Some(1); + /// # let result: Result = Ok(1); + /// option.expect("more helpful message"); + /// result.expect("more helpful message"); + /// ``` + /// + /// If [expect_used](#expect_used) is enabled, instead: + /// ```rust,ignore + /// # let option = Some(1); + /// # let result: Result = Ok(1); + /// option?; + /// + /// // or + /// + /// result?; + /// ``` + #[clippy::version = "1.69.0"] + pub UNNECESSARY_LITERAL_UNWRAP, + complexity, + "checks for calls of `unwrap()` or `expect()` on `Some()` that cannot fail" +} + declare_clippy_lint! { /// ### What it does /// Checks for `.expect()` or `.expect_err()` calls on `Result`s and `.expect()` call on `Option`s. @@ -3814,6 +3865,7 @@ impl Methods { Some(("or", recv, [or_arg], or_span, _)) => { or_then_unwrap::check(cx, expr, recv, or_arg, or_span); }, + // unnecessary_literal_unwrap::check(cx, expr, recv); _ => {}, } unwrap_used::check(cx, expr, recv, false, self.allow_unwrap_in_tests); diff --git a/clippy_lints/src/methods/unnecessary_literal_unwrap.rs b/clippy_lints/src/methods/unnecessary_literal_unwrap.rs new file mode 100644 index 00000000000..39b30b7769d --- /dev/null +++ b/clippy_lints/src/methods/unnecessary_literal_unwrap.rs @@ -0,0 +1,30 @@ +use clippy_utils::diagnostics::span_lint_and_help; +use clippy_utils::ty::is_type_diagnostic_item; +use rustc_hir as hir; +use rustc_lint::LateContext; +use rustc_span::sym; + +use super::UNNECESSARY_LITERAL_UNWRAP; + +pub(super) fn check(cx: &LateContext<'_>, expr: &hir::Expr<'_>, recv: &hir::Expr<'_>) { + let obj_ty = cx.typeck_results().expr_ty(recv).peel_refs(); + + let mess = if is_type_diagnostic_item(cx, obj_ty, sym::Option) { + Some((UNNECESSARY_LITERAL_UNWRAP, "an `Option`", "None", "")) + } else { + None + }; + + if let Some((lint, kind, none_value, none_prefix)) = mess { + let help = format!("if this value is {none_prefix}`{none_value}`, it will panic"); + + span_lint_and_help( + cx, + lint, + expr.span, + &format!("used `unwrap()` on {kind} value"), + None, + &help, + ); + } +} diff --git a/tests/ui/unnecessary_literal_unwrap.rs b/tests/ui/unnecessary_literal_unwrap.rs new file mode 100644 index 00000000000..9ae50517a3e --- /dev/null +++ b/tests/ui/unnecessary_literal_unwrap.rs @@ -0,0 +1,10 @@ +#![warn(clippy::unnecessary_literal_unwrap)] + +fn unwrap_option() { + let val = Some(1).unwrap(); + let val = Some(1).expect("this never happens"); +} + +fn main() { + unwrap_option(); +} diff --git a/tests/ui/unwrap_literal.rs b/tests/ui/unwrap_literal.rs deleted file mode 100644 index 917ef2126f5..00000000000 --- a/tests/ui/unwrap_literal.rs +++ /dev/null @@ -1,17 +0,0 @@ -#![warn(clippy::unnecessary_unwrap)] - -fn unwrap_option() { - let val = Some(1).unwrap(); - let val = Some(1).expect("this never happens"); -} - -fn unwrap_result() { - let val = Ok(1).unwrap(); - let val = Err(1).unwrap_err(); - let val = Ok(1).expect("this never happens"); -} - -fn main() { - unwrap_option(); - unwrap_result(); -} From 5bb768177ee83065191b1f47111ecf63de347cff Mon Sep 17 00:00:00 2001 From: rsdy Date: Thu, 16 Feb 2023 11:49:19 +0000 Subject: [PATCH 159/310] Add hook --- clippy_lints/src/methods/mod.rs | 4 +++- clippy_lints/src/methods/unnecessary_literal_unwrap.rs | 2 +- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/clippy_lints/src/methods/mod.rs b/clippy_lints/src/methods/mod.rs index f24f00ef6a7..9d7b607ec7b 100644 --- a/clippy_lints/src/methods/mod.rs +++ b/clippy_lints/src/methods/mod.rs @@ -3865,7 +3865,9 @@ impl Methods { Some(("or", recv, [or_arg], or_span, _)) => { or_then_unwrap::check(cx, expr, recv, or_arg, or_span); }, - // unnecessary_literal_unwrap::check(cx, expr, recv); + Some((constructor @ "Some", _, _, _, _)) => { + unnecessary_literal_unwrap::check(cx, expr, recv, constructor); + } _ => {}, } unwrap_used::check(cx, expr, recv, false, self.allow_unwrap_in_tests); diff --git a/clippy_lints/src/methods/unnecessary_literal_unwrap.rs b/clippy_lints/src/methods/unnecessary_literal_unwrap.rs index 39b30b7769d..3572f4965ef 100644 --- a/clippy_lints/src/methods/unnecessary_literal_unwrap.rs +++ b/clippy_lints/src/methods/unnecessary_literal_unwrap.rs @@ -6,7 +6,7 @@ use rustc_span::sym; use super::UNNECESSARY_LITERAL_UNWRAP; -pub(super) fn check(cx: &LateContext<'_>, expr: &hir::Expr<'_>, recv: &hir::Expr<'_>) { +pub(super) fn check(cx: &LateContext<'_>, expr: &hir::Expr<'_>, recv: &hir::Expr<'_>, constructor: &str) { let obj_ty = cx.typeck_results().expr_ty(recv).peel_refs(); let mess = if is_type_diagnostic_item(cx, obj_ty, sym::Option) { From 2902359b3c922910b5b5bc1c2fa73c3e8bf2fcfb Mon Sep 17 00:00:00 2001 From: Pavan Kumar Sunkara Date: Thu, 16 Feb 2023 11:32:12 +0000 Subject: [PATCH 160/310] Add the lint to the lib --- clippy_lints/src/declared_lints.rs | 1 + clippy_lints/src/methods/mod.rs | 1 + 2 files changed, 2 insertions(+) diff --git a/clippy_lints/src/declared_lints.rs b/clippy_lints/src/declared_lints.rs index 523faa302dc..62317dc60eb 100644 --- a/clippy_lints/src/declared_lints.rs +++ b/clippy_lints/src/declared_lints.rs @@ -408,6 +408,7 @@ pub(crate) static LINTS: &[&crate::LintInfo] = &[ crate::methods::UNNECESSARY_FOLD_INFO, crate::methods::UNNECESSARY_JOIN_INFO, crate::methods::UNNECESSARY_LAZY_EVALUATIONS_INFO, + crate::methods::UNNECESSARY_LITERAL_UNWRAP_INFO, crate::methods::UNNECESSARY_SORT_BY_INFO, crate::methods::UNNECESSARY_TO_OWNED_INFO, crate::methods::UNWRAP_OR_ELSE_DEFAULT_INFO, diff --git a/clippy_lints/src/methods/mod.rs b/clippy_lints/src/methods/mod.rs index 9d7b607ec7b..6eb97227e0a 100644 --- a/clippy_lints/src/methods/mod.rs +++ b/clippy_lints/src/methods/mod.rs @@ -3400,6 +3400,7 @@ impl_lint_pass!(Methods => [ SUSPICIOUS_COMMAND_ARG_SPACE, CLEAR_WITH_DRAIN, MANUAL_NEXT_BACK, + UNNECESSARY_LITERAL_UNWRAP, ]); /// Extracts a method call name, args, and `Span` of the method name. From 0b1bb5fbf3a4d3e73192f95490ce7246f9fd1914 Mon Sep 17 00:00:00 2001 From: Pavan Kumar Sunkara Date: Thu, 16 Feb 2023 13:36:51 +0000 Subject: [PATCH 161/310] Implement the lint --- clippy_lints/src/methods/mod.rs | 6 +++--- .../src/methods/unnecessary_literal_unwrap.rs | 19 +++++++------------ tests/ui/unnecessary_literal_unwrap.stderr | 11 +++++++++++ 3 files changed, 21 insertions(+), 15 deletions(-) create mode 100644 tests/ui/unnecessary_literal_unwrap.stderr diff --git a/clippy_lints/src/methods/mod.rs b/clippy_lints/src/methods/mod.rs index 6eb97227e0a..7a7d5a588b0 100644 --- a/clippy_lints/src/methods/mod.rs +++ b/clippy_lints/src/methods/mod.rs @@ -3866,11 +3866,11 @@ impl Methods { Some(("or", recv, [or_arg], or_span, _)) => { or_then_unwrap::check(cx, expr, recv, or_arg, or_span); }, - Some((constructor @ "Some", _, _, _, _)) => { - unnecessary_literal_unwrap::check(cx, expr, recv, constructor); - } _ => {}, } + if let ExprKind::Call(recv, _) = recv.kind { + unnecessary_literal_unwrap::check(cx, expr, recv, name); + } unwrap_used::check(cx, expr, recv, false, self.allow_unwrap_in_tests); }, ("unwrap_err", []) => unwrap_used::check(cx, expr, recv, true, self.allow_unwrap_in_tests), diff --git a/clippy_lints/src/methods/unnecessary_literal_unwrap.rs b/clippy_lints/src/methods/unnecessary_literal_unwrap.rs index 3572f4965ef..181e4a06664 100644 --- a/clippy_lints/src/methods/unnecessary_literal_unwrap.rs +++ b/clippy_lints/src/methods/unnecessary_literal_unwrap.rs @@ -1,28 +1,23 @@ -use clippy_utils::diagnostics::span_lint_and_help; -use clippy_utils::ty::is_type_diagnostic_item; +use clippy_utils::{diagnostics::span_lint_and_help, is_res_lang_ctor, path_res}; use rustc_hir as hir; use rustc_lint::LateContext; -use rustc_span::sym; use super::UNNECESSARY_LITERAL_UNWRAP; -pub(super) fn check(cx: &LateContext<'_>, expr: &hir::Expr<'_>, recv: &hir::Expr<'_>, constructor: &str) { - let obj_ty = cx.typeck_results().expr_ty(recv).peel_refs(); - - let mess = if is_type_diagnostic_item(cx, obj_ty, sym::Option) { - Some((UNNECESSARY_LITERAL_UNWRAP, "an `Option`", "None", "")) +pub(super) fn check(cx: &LateContext<'_>, expr: &hir::Expr<'_>, recv: &hir::Expr<'_>, name: &str) { + let mess = if is_res_lang_ctor(cx, path_res(cx, recv), hir::LangItem::OptionSome) { + Some((UNNECESSARY_LITERAL_UNWRAP, "Some")) } else { None }; - if let Some((lint, kind, none_value, none_prefix)) = mess { - let help = format!("if this value is {none_prefix}`{none_value}`, it will panic"); - + if let Some((lint, constructor)) = mess { + let help = String::new(); span_lint_and_help( cx, lint, expr.span, - &format!("used `unwrap()` on {kind} value"), + &format!("used `{name}()` on `{constructor}` value"), None, &help, ); diff --git a/tests/ui/unnecessary_literal_unwrap.stderr b/tests/ui/unnecessary_literal_unwrap.stderr new file mode 100644 index 00000000000..5f9881b2ae3 --- /dev/null +++ b/tests/ui/unnecessary_literal_unwrap.stderr @@ -0,0 +1,11 @@ +error: used `unwrap()` on `Some` value + --> $DIR/unnecessary_literal_unwrap.rs:4:15 + | +LL | let val = Some(1).unwrap(); + | ^^^^^^^^^^^^^^^^ + | + = help: + = note: `-D clippy::unnecessary-literal-unwrap` implied by `-D warnings` + +error: aborting due to previous error + From 21b88ce290ee90259fdd35b33923ee330acb0991 Mon Sep 17 00:00:00 2001 From: Pavan Kumar Sunkara Date: Thu, 16 Feb 2023 13:44:11 +0000 Subject: [PATCH 162/310] Implement the lint for expect --- clippy_lints/src/methods/mod.rs | 13 +++++++++---- tests/ui/unnecessary_literal_unwrap.stderr | 10 +++++++++- 2 files changed, 18 insertions(+), 5 deletions(-) diff --git a/clippy_lints/src/methods/mod.rs b/clippy_lints/src/methods/mod.rs index 7a7d5a588b0..cb82aef1ef0 100644 --- a/clippy_lints/src/methods/mod.rs +++ b/clippy_lints/src/methods/mod.rs @@ -3658,10 +3658,15 @@ impl Methods { case_sensitive_file_extension_comparisons::check(cx, expr, span, recv, arg); } }, - ("expect", [_]) => match method_call(recv) { - Some(("ok", recv, [], _, _)) => ok_expect::check(cx, expr, recv), - Some(("err", recv, [], err_span, _)) => err_expect::check(cx, expr, recv, span, err_span, &self.msrv), - _ => expect_used::check(cx, expr, recv, false, self.allow_expect_in_tests), + ("expect", [_]) => { + match method_call(recv) { + Some(("ok", recv, [], _, _)) => ok_expect::check(cx, expr, recv), + Some(("err", recv, [], err_span, _)) => err_expect::check(cx, expr, recv, span, err_span, &self.msrv), + _ => expect_used::check(cx, expr, recv, false, self.allow_expect_in_tests), + } + if let ExprKind::Call(recv, _) = recv.kind { + unnecessary_literal_unwrap::check(cx, expr, recv, name); + } }, ("expect_err", [_]) => expect_used::check(cx, expr, recv, true, self.allow_expect_in_tests), ("extend", [arg]) => { diff --git a/tests/ui/unnecessary_literal_unwrap.stderr b/tests/ui/unnecessary_literal_unwrap.stderr index 5f9881b2ae3..414d4445cae 100644 --- a/tests/ui/unnecessary_literal_unwrap.stderr +++ b/tests/ui/unnecessary_literal_unwrap.stderr @@ -7,5 +7,13 @@ LL | let val = Some(1).unwrap(); = help: = note: `-D clippy::unnecessary-literal-unwrap` implied by `-D warnings` -error: aborting due to previous error +error: used `expect()` on `Some` value + --> $DIR/unnecessary_literal_unwrap.rs:5:15 + | +LL | let val = Some(1).expect("this never happens"); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: + +error: aborting due to 2 previous errors From daf61974813ba6f9e7513068bc8cce2839fb8939 Mon Sep 17 00:00:00 2001 From: Pavan Kumar Sunkara Date: Thu, 16 Feb 2023 14:21:43 +0000 Subject: [PATCH 163/310] Implement the suggestion --- clippy_lints/src/methods/mod.rs | 8 +++---- .../src/methods/unnecessary_literal_unwrap.rs | 22 ++++++++++++++----- tests/ui/unnecessary_literal_unwrap.fixed | 11 ++++++++++ tests/ui/unnecessary_literal_unwrap.rs | 1 + tests/ui/unnecessary_literal_unwrap.stderr | 16 ++++++++++---- 5 files changed, 44 insertions(+), 14 deletions(-) create mode 100644 tests/ui/unnecessary_literal_unwrap.fixed diff --git a/clippy_lints/src/methods/mod.rs b/clippy_lints/src/methods/mod.rs index cb82aef1ef0..a5c55a42ea5 100644 --- a/clippy_lints/src/methods/mod.rs +++ b/clippy_lints/src/methods/mod.rs @@ -3664,8 +3664,8 @@ impl Methods { Some(("err", recv, [], err_span, _)) => err_expect::check(cx, expr, recv, span, err_span, &self.msrv), _ => expect_used::check(cx, expr, recv, false, self.allow_expect_in_tests), } - if let ExprKind::Call(recv, _) = recv.kind { - unnecessary_literal_unwrap::check(cx, expr, recv, name); + if let ExprKind::Call(recv, [arg]) = recv.kind { + unnecessary_literal_unwrap::check(cx, expr, recv, arg, name); } }, ("expect_err", [_]) => expect_used::check(cx, expr, recv, true, self.allow_expect_in_tests), @@ -3873,8 +3873,8 @@ impl Methods { }, _ => {}, } - if let ExprKind::Call(recv, _) = recv.kind { - unnecessary_literal_unwrap::check(cx, expr, recv, name); + if let ExprKind::Call(recv, [arg]) = recv.kind { + unnecessary_literal_unwrap::check(cx, expr, recv, arg, name); } unwrap_used::check(cx, expr, recv, false, self.allow_unwrap_in_tests); }, diff --git a/clippy_lints/src/methods/unnecessary_literal_unwrap.rs b/clippy_lints/src/methods/unnecessary_literal_unwrap.rs index 181e4a06664..9a82d7e58ea 100644 --- a/clippy_lints/src/methods/unnecessary_literal_unwrap.rs +++ b/clippy_lints/src/methods/unnecessary_literal_unwrap.rs @@ -1,10 +1,11 @@ -use clippy_utils::{diagnostics::span_lint_and_help, is_res_lang_ctor, path_res}; +use clippy_utils::{diagnostics::span_lint_and_then, is_res_lang_ctor, path_res}; +use rustc_errors::Applicability; use rustc_hir as hir; use rustc_lint::LateContext; use super::UNNECESSARY_LITERAL_UNWRAP; -pub(super) fn check(cx: &LateContext<'_>, expr: &hir::Expr<'_>, recv: &hir::Expr<'_>, name: &str) { +pub(super) fn check(cx: &LateContext<'_>, expr: &hir::Expr<'_>, recv: &hir::Expr<'_>, arg: &hir::Expr<'_>, name: &str) { let mess = if is_res_lang_ctor(cx, path_res(cx, recv), hir::LangItem::OptionSome) { Some((UNNECESSARY_LITERAL_UNWRAP, "Some")) } else { @@ -12,14 +13,23 @@ pub(super) fn check(cx: &LateContext<'_>, expr: &hir::Expr<'_>, recv: &hir::Expr }; if let Some((lint, constructor)) = mess { - let help = String::new(); - span_lint_and_help( + span_lint_and_then( cx, lint, expr.span, &format!("used `{name}()` on `{constructor}` value"), - None, - &help, + |diag| { + let suggestions = vec![ + (recv.span.with_hi(arg.span.lo()), String::new()), + (expr.span.with_lo(arg.span.hi()), String::new()), + ]; + + diag.multipart_suggestion( + format!("remove the `{constructor}` and `{name}()`"), + suggestions, + Applicability::MachineApplicable, + ); + }, ); } } diff --git a/tests/ui/unnecessary_literal_unwrap.fixed b/tests/ui/unnecessary_literal_unwrap.fixed new file mode 100644 index 00000000000..8696048d332 --- /dev/null +++ b/tests/ui/unnecessary_literal_unwrap.fixed @@ -0,0 +1,11 @@ +//run-rustfix +#![warn(clippy::unnecessary_literal_unwrap)] + +fn unwrap_option() { + let val = 1; + let val = 1; +} + +fn main() { + unwrap_option(); +} diff --git a/tests/ui/unnecessary_literal_unwrap.rs b/tests/ui/unnecessary_literal_unwrap.rs index 9ae50517a3e..ae41634495b 100644 --- a/tests/ui/unnecessary_literal_unwrap.rs +++ b/tests/ui/unnecessary_literal_unwrap.rs @@ -1,3 +1,4 @@ +//run-rustfix #![warn(clippy::unnecessary_literal_unwrap)] fn unwrap_option() { diff --git a/tests/ui/unnecessary_literal_unwrap.stderr b/tests/ui/unnecessary_literal_unwrap.stderr index 414d4445cae..00d7f186fc4 100644 --- a/tests/ui/unnecessary_literal_unwrap.stderr +++ b/tests/ui/unnecessary_literal_unwrap.stderr @@ -1,19 +1,27 @@ error: used `unwrap()` on `Some` value - --> $DIR/unnecessary_literal_unwrap.rs:4:15 + --> $DIR/unnecessary_literal_unwrap.rs:5:15 | LL | let val = Some(1).unwrap(); | ^^^^^^^^^^^^^^^^ | - = help: = note: `-D clippy::unnecessary-literal-unwrap` implied by `-D warnings` +help: remove the `Some` and `unwrap()` + | +LL - let val = Some(1).unwrap(); +LL + let val = 1; + | error: used `expect()` on `Some` value - --> $DIR/unnecessary_literal_unwrap.rs:5:15 + --> $DIR/unnecessary_literal_unwrap.rs:6:15 | LL | let val = Some(1).expect("this never happens"); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | - = help: +help: remove the `Some` and `expect()` + | +LL - let val = Some(1).expect("this never happens"); +LL + let val = 1; + | error: aborting due to 2 previous errors From 1d159e7d11d86d030c030ec0ec23a88871289d1b Mon Sep 17 00:00:00 2001 From: rsdy Date: Thu, 16 Feb 2023 14:37:18 +0000 Subject: [PATCH 164/310] Recognize `Ok` --- .../src/methods/unnecessary_literal_unwrap.rs | 8 ++-- tests/ui/unnecessary_literal_unwrap.fixed | 11 ++++- tests/ui/unnecessary_literal_unwrap.rs | 11 ++++- tests/ui/unnecessary_literal_unwrap.stderr | 46 ++++++++++++++----- 4 files changed, 58 insertions(+), 18 deletions(-) diff --git a/clippy_lints/src/methods/unnecessary_literal_unwrap.rs b/clippy_lints/src/methods/unnecessary_literal_unwrap.rs index 9a82d7e58ea..0c8a70fedb9 100644 --- a/clippy_lints/src/methods/unnecessary_literal_unwrap.rs +++ b/clippy_lints/src/methods/unnecessary_literal_unwrap.rs @@ -7,15 +7,17 @@ use super::UNNECESSARY_LITERAL_UNWRAP; pub(super) fn check(cx: &LateContext<'_>, expr: &hir::Expr<'_>, recv: &hir::Expr<'_>, arg: &hir::Expr<'_>, name: &str) { let mess = if is_res_lang_ctor(cx, path_res(cx, recv), hir::LangItem::OptionSome) { - Some((UNNECESSARY_LITERAL_UNWRAP, "Some")) + Some("Some") + } else if is_res_lang_ctor(cx, path_res(cx, recv), hir::LangItem::ResultOk) { + Some("Ok") } else { None }; - if let Some((lint, constructor)) = mess { + if let Some(constructor) = mess { span_lint_and_then( cx, - lint, + UNNECESSARY_LITERAL_UNWRAP, expr.span, &format!("used `{name}()` on `{constructor}` value"), |diag| { diff --git a/tests/ui/unnecessary_literal_unwrap.fixed b/tests/ui/unnecessary_literal_unwrap.fixed index 8696048d332..b59dec7d48a 100644 --- a/tests/ui/unnecessary_literal_unwrap.fixed +++ b/tests/ui/unnecessary_literal_unwrap.fixed @@ -2,10 +2,17 @@ #![warn(clippy::unnecessary_literal_unwrap)] fn unwrap_option() { - let val = 1; - let val = 1; + let _val = 1; + let _val = 1; +} + +fn unwrap_result() { + let _val = 1; + let _val = 1; + // let val = Err(1).unwrap_err(); } fn main() { unwrap_option(); + unwrap_result(); } diff --git a/tests/ui/unnecessary_literal_unwrap.rs b/tests/ui/unnecessary_literal_unwrap.rs index ae41634495b..c46204f7a99 100644 --- a/tests/ui/unnecessary_literal_unwrap.rs +++ b/tests/ui/unnecessary_literal_unwrap.rs @@ -2,10 +2,17 @@ #![warn(clippy::unnecessary_literal_unwrap)] fn unwrap_option() { - let val = Some(1).unwrap(); - let val = Some(1).expect("this never happens"); + let _val = Some(1).unwrap(); + let _val = Some(1).expect("this never happens"); +} + +fn unwrap_result() { + let _val = Ok::(1).unwrap(); + let _val = Ok::(1).expect("this never happens"); + // let val = Err(1).unwrap_err(); } fn main() { unwrap_option(); + unwrap_result(); } diff --git a/tests/ui/unnecessary_literal_unwrap.stderr b/tests/ui/unnecessary_literal_unwrap.stderr index 00d7f186fc4..c5e3cd1657b 100644 --- a/tests/ui/unnecessary_literal_unwrap.stderr +++ b/tests/ui/unnecessary_literal_unwrap.stderr @@ -1,27 +1,51 @@ error: used `unwrap()` on `Some` value - --> $DIR/unnecessary_literal_unwrap.rs:5:15 + --> $DIR/unnecessary_literal_unwrap.rs:5:16 | -LL | let val = Some(1).unwrap(); - | ^^^^^^^^^^^^^^^^ +LL | let _val = Some(1).unwrap(); + | ^^^^^^^^^^^^^^^^ | = note: `-D clippy::unnecessary-literal-unwrap` implied by `-D warnings` help: remove the `Some` and `unwrap()` | -LL - let val = Some(1).unwrap(); -LL + let val = 1; +LL - let _val = Some(1).unwrap(); +LL + let _val = 1; | error: used `expect()` on `Some` value - --> $DIR/unnecessary_literal_unwrap.rs:6:15 + --> $DIR/unnecessary_literal_unwrap.rs:6:16 | -LL | let val = Some(1).expect("this never happens"); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | let _val = Some(1).expect("this never happens"); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | help: remove the `Some` and `expect()` | -LL - let val = Some(1).expect("this never happens"); -LL + let val = 1; +LL - let _val = Some(1).expect("this never happens"); +LL + let _val = 1; | -error: aborting due to 2 previous errors +error: used `unwrap()` on `Ok` value + --> $DIR/unnecessary_literal_unwrap.rs:10:16 + | +LL | let _val = Ok::(1).unwrap(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: remove the `Ok` and `unwrap()` + | +LL - let _val = Ok::(1).unwrap(); +LL + let _val = 1; + | + +error: used `expect()` on `Ok` value + --> $DIR/unnecessary_literal_unwrap.rs:11:16 + | +LL | let _val = Ok::(1).expect("this never happens"); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: remove the `Ok` and `expect()` + | +LL - let _val = Ok::(1).expect("this never happens"); +LL + let _val = 1; + | + +error: aborting due to 4 previous errors From 8f83502989f8723377082c52c3aa5c086d5fd3f2 Mon Sep 17 00:00:00 2001 From: Pavan Kumar Sunkara Date: Thu, 16 Feb 2023 14:43:41 +0000 Subject: [PATCH 165/310] Recognize `unwrap_or` methods --- clippy_lints/src/methods/mod.rs | 36 +++++++------ .../src/methods/unnecessary_literal_unwrap.rs | 54 ++++++++++--------- tests/ui/unnecessary_literal_unwrap.fixed | 12 +++++ tests/ui/unnecessary_literal_unwrap.rs | 12 +++++ tests/ui/unnecessary_literal_unwrap.stderr | 50 ++++++++++++++++- 5 files changed, 120 insertions(+), 44 deletions(-) diff --git a/clippy_lints/src/methods/mod.rs b/clippy_lints/src/methods/mod.rs index a5c55a42ea5..5e42123a8da 100644 --- a/clippy_lints/src/methods/mod.rs +++ b/clippy_lints/src/methods/mod.rs @@ -3664,9 +3664,7 @@ impl Methods { Some(("err", recv, [], err_span, _)) => err_expect::check(cx, expr, recv, span, err_span, &self.msrv), _ => expect_used::check(cx, expr, recv, false, self.allow_expect_in_tests), } - if let ExprKind::Call(recv, [arg]) = recv.kind { - unnecessary_literal_unwrap::check(cx, expr, recv, arg, name); - } + unnecessary_literal_unwrap::check(cx, expr, recv, name); }, ("expect_err", [_]) => expect_used::check(cx, expr, recv, true, self.allow_expect_in_tests), ("extend", [arg]) => { @@ -3873,24 +3871,28 @@ impl Methods { }, _ => {}, } - if let ExprKind::Call(recv, [arg]) = recv.kind { - unnecessary_literal_unwrap::check(cx, expr, recv, arg, name); - } + unnecessary_literal_unwrap::check(cx, expr, recv, name); unwrap_used::check(cx, expr, recv, false, self.allow_unwrap_in_tests); }, ("unwrap_err", []) => unwrap_used::check(cx, expr, recv, true, self.allow_unwrap_in_tests), - ("unwrap_or", [u_arg]) => match method_call(recv) { - Some((arith @ ("checked_add" | "checked_sub" | "checked_mul"), lhs, [rhs], _, _)) => { - manual_saturating_arithmetic::check(cx, expr, lhs, rhs, u_arg, &arith["checked_".len()..]); - }, - Some(("map", m_recv, [m_arg], span, _)) => { - option_map_unwrap_or::check(cx, expr, m_recv, m_arg, recv, u_arg, span); - }, - Some(("then_some", t_recv, [t_arg], _, _)) => { - obfuscated_if_else::check(cx, expr, t_recv, t_arg, u_arg); - }, - _ => {}, + ("unwrap_or", [u_arg]) => { + match method_call(recv) { + Some((arith @ ("checked_add" | "checked_sub" | "checked_mul"), lhs, [rhs], _, _)) => { + manual_saturating_arithmetic::check(cx, expr, lhs, rhs, u_arg, &arith["checked_".len()..]); + }, + Some(("map", m_recv, [m_arg], span, _)) => { + option_map_unwrap_or::check(cx, expr, m_recv, m_arg, recv, u_arg, span); + }, + Some(("then_some", t_recv, [t_arg], _, _)) => { + obfuscated_if_else::check(cx, expr, t_recv, t_arg, u_arg); + }, + _ => {}, + } + unnecessary_literal_unwrap::check(cx, expr, recv, name); }, + ("unwrap_or_default", []) => { + unnecessary_literal_unwrap::check(cx, expr, recv, name); + } ("unwrap_or_else", [u_arg]) => match method_call(recv) { Some(("map", recv, [map_arg], _, _)) if map_unwrap_or::check(cx, expr, recv, map_arg, u_arg, &self.msrv) => {}, diff --git a/clippy_lints/src/methods/unnecessary_literal_unwrap.rs b/clippy_lints/src/methods/unnecessary_literal_unwrap.rs index 0c8a70fedb9..9a9c659b232 100644 --- a/clippy_lints/src/methods/unnecessary_literal_unwrap.rs +++ b/clippy_lints/src/methods/unnecessary_literal_unwrap.rs @@ -5,33 +5,35 @@ use rustc_lint::LateContext; use super::UNNECESSARY_LITERAL_UNWRAP; -pub(super) fn check(cx: &LateContext<'_>, expr: &hir::Expr<'_>, recv: &hir::Expr<'_>, arg: &hir::Expr<'_>, name: &str) { - let mess = if is_res_lang_ctor(cx, path_res(cx, recv), hir::LangItem::OptionSome) { - Some("Some") - } else if is_res_lang_ctor(cx, path_res(cx, recv), hir::LangItem::ResultOk) { - Some("Ok") - } else { - None - }; +pub(super) fn check(cx: &LateContext<'_>, expr: &hir::Expr<'_>, recv: &hir::Expr<'_>, name: &str) { + if let hir::ExprKind::Call(call, [arg]) = recv.kind { + let mess = if is_res_lang_ctor(cx, path_res(cx, call), hir::LangItem::OptionSome) { + Some("Some") + } else if is_res_lang_ctor(cx, path_res(cx, call), hir::LangItem::ResultOk) { + Some("Ok") + } else { + None + }; - if let Some(constructor) = mess { - span_lint_and_then( - cx, - UNNECESSARY_LITERAL_UNWRAP, - expr.span, - &format!("used `{name}()` on `{constructor}` value"), - |diag| { - let suggestions = vec![ - (recv.span.with_hi(arg.span.lo()), String::new()), - (expr.span.with_lo(arg.span.hi()), String::new()), - ]; + if let Some(constructor) = mess { + span_lint_and_then( + cx, + UNNECESSARY_LITERAL_UNWRAP, + expr.span, + &format!("used `{name}()` on `{constructor}` value"), + |diag| { + let suggestions = vec![ + (call.span.with_hi(arg.span.lo()), String::new()), + (expr.span.with_lo(arg.span.hi()), String::new()), + ]; - diag.multipart_suggestion( - format!("remove the `{constructor}` and `{name}()`"), - suggestions, - Applicability::MachineApplicable, - ); - }, - ); + diag.multipart_suggestion( + format!("remove the `{constructor}` and `{name}()`"), + suggestions, + Applicability::MachineApplicable, + ); + }, + ); + } } } diff --git a/tests/ui/unnecessary_literal_unwrap.fixed b/tests/ui/unnecessary_literal_unwrap.fixed index b59dec7d48a..55a210bdb98 100644 --- a/tests/ui/unnecessary_literal_unwrap.fixed +++ b/tests/ui/unnecessary_literal_unwrap.fixed @@ -12,7 +12,19 @@ fn unwrap_result() { // let val = Err(1).unwrap_err(); } +fn unwrap_methods_option() { + let _val = 1; + let _val = 1; +} + +fn unwrap_methods_result() { + let _val = 1; + let _val = 1; +} + fn main() { unwrap_option(); unwrap_result(); + unwrap_methods_option(); + unwrap_methods_result(); } diff --git a/tests/ui/unnecessary_literal_unwrap.rs b/tests/ui/unnecessary_literal_unwrap.rs index c46204f7a99..80f72ce3cf2 100644 --- a/tests/ui/unnecessary_literal_unwrap.rs +++ b/tests/ui/unnecessary_literal_unwrap.rs @@ -12,7 +12,19 @@ fn unwrap_result() { // let val = Err(1).unwrap_err(); } +fn unwrap_methods_option() { + let _val = Some(1).unwrap_or(2); + let _val = Some(1).unwrap_or_default(); +} + +fn unwrap_methods_result() { + let _val = Ok::(1).unwrap_or(2); + let _val = Ok::(1).unwrap_or_default(); +} + fn main() { unwrap_option(); unwrap_result(); + unwrap_methods_option(); + unwrap_methods_result(); } diff --git a/tests/ui/unnecessary_literal_unwrap.stderr b/tests/ui/unnecessary_literal_unwrap.stderr index c5e3cd1657b..b8b5a612da1 100644 --- a/tests/ui/unnecessary_literal_unwrap.stderr +++ b/tests/ui/unnecessary_literal_unwrap.stderr @@ -47,5 +47,53 @@ LL - let _val = Ok::(1).expect("this never happens"); LL + let _val = 1; | -error: aborting due to 4 previous errors +error: used `unwrap_or()` on `Some` value + --> $DIR/unnecessary_literal_unwrap.rs:16:16 + | +LL | let _val = Some(1).unwrap_or(2); + | ^^^^^^^^^^^^^^^^^^^^ + | +help: remove the `Some` and `unwrap_or()` + | +LL - let _val = Some(1).unwrap_or(2); +LL + let _val = 1; + | + +error: used `unwrap_or_default()` on `Some` value + --> $DIR/unnecessary_literal_unwrap.rs:17:16 + | +LL | let _val = Some(1).unwrap_or_default(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: remove the `Some` and `unwrap_or_default()` + | +LL - let _val = Some(1).unwrap_or_default(); +LL + let _val = 1; + | + +error: used `unwrap_or()` on `Ok` value + --> $DIR/unnecessary_literal_unwrap.rs:21:16 + | +LL | let _val = Ok::(1).unwrap_or(2); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: remove the `Ok` and `unwrap_or()` + | +LL - let _val = Ok::(1).unwrap_or(2); +LL + let _val = 1; + | + +error: used `unwrap_or_default()` on `Ok` value + --> $DIR/unnecessary_literal_unwrap.rs:22:16 + | +LL | let _val = Ok::(1).unwrap_or_default(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: remove the `Ok` and `unwrap_or_default()` + | +LL - let _val = Ok::(1).unwrap_or_default(); +LL + let _val = 1; + | + +error: aborting due to 8 previous errors From 7ed7283e0f9de697f8d5c8c2118c4b0b8bc7d6b0 Mon Sep 17 00:00:00 2001 From: Pavan Kumar Sunkara Date: Thu, 16 Feb 2023 15:05:56 +0000 Subject: [PATCH 166/310] Recognize `unwrap_or_else` method --- CHANGELOG.md | 1 + clippy_lints/src/methods/mod.rs | 17 +++++---- tests/ui/unnecessary_literal_unwrap.fixed | 3 ++ tests/ui/unnecessary_literal_unwrap.rs | 3 ++ tests/ui/unnecessary_literal_unwrap.stderr | 42 +++++++++++++++++----- 5 files changed, 50 insertions(+), 16 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 85fddc97047..abc35e8546f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5248,6 +5248,7 @@ Released 2018-09-13 [`unnecessary_fold`]: https://rust-lang.github.io/rust-clippy/master/index.html#unnecessary_fold [`unnecessary_join`]: https://rust-lang.github.io/rust-clippy/master/index.html#unnecessary_join [`unnecessary_lazy_evaluations`]: https://rust-lang.github.io/rust-clippy/master/index.html#unnecessary_lazy_evaluations +[`unnecessary_literal_unwrap`]: https://rust-lang.github.io/rust-clippy/master/index.html#unnecessary_literal_unwrap [`unnecessary_mut_passed`]: https://rust-lang.github.io/rust-clippy/master/index.html#unnecessary_mut_passed [`unnecessary_operation`]: https://rust-lang.github.io/rust-clippy/master/index.html#unnecessary_operation [`unnecessary_owned_empty_strings`]: https://rust-lang.github.io/rust-clippy/master/index.html#unnecessary_owned_empty_strings diff --git a/clippy_lints/src/methods/mod.rs b/clippy_lints/src/methods/mod.rs index 5e42123a8da..4686adda683 100644 --- a/clippy_lints/src/methods/mod.rs +++ b/clippy_lints/src/methods/mod.rs @@ -3893,13 +3893,16 @@ impl Methods { ("unwrap_or_default", []) => { unnecessary_literal_unwrap::check(cx, expr, recv, name); } - ("unwrap_or_else", [u_arg]) => match method_call(recv) { - Some(("map", recv, [map_arg], _, _)) - if map_unwrap_or::check(cx, expr, recv, map_arg, u_arg, &self.msrv) => {}, - _ => { - unwrap_or_else_default::check(cx, expr, recv, u_arg); - unnecessary_lazy_eval::check(cx, expr, recv, u_arg, "unwrap_or"); - }, + ("unwrap_or_else", [u_arg]) => { + match method_call(recv) { + Some(("map", recv, [map_arg], _, _)) + if map_unwrap_or::check(cx, expr, recv, map_arg, u_arg, &self.msrv) => {}, + _ => { + unwrap_or_else_default::check(cx, expr, recv, u_arg); + unnecessary_lazy_eval::check(cx, expr, recv, u_arg, "unwrap_or"); + }, + } + unnecessary_literal_unwrap::check(cx, expr, recv, name); }, ("zip", [arg]) => { if let ExprKind::MethodCall(name, iter_recv, [], _) = recv.kind diff --git a/tests/ui/unnecessary_literal_unwrap.fixed b/tests/ui/unnecessary_literal_unwrap.fixed index 55a210bdb98..a388a7f83d2 100644 --- a/tests/ui/unnecessary_literal_unwrap.fixed +++ b/tests/ui/unnecessary_literal_unwrap.fixed @@ -1,5 +1,6 @@ //run-rustfix #![warn(clippy::unnecessary_literal_unwrap)] +#![allow(clippy::unnecessary_lazy_evaluations)] fn unwrap_option() { let _val = 1; @@ -15,11 +16,13 @@ fn unwrap_result() { fn unwrap_methods_option() { let _val = 1; let _val = 1; + let _val = 1; } fn unwrap_methods_result() { let _val = 1; let _val = 1; + let _val = 1; } fn main() { diff --git a/tests/ui/unnecessary_literal_unwrap.rs b/tests/ui/unnecessary_literal_unwrap.rs index 80f72ce3cf2..fe557957dd9 100644 --- a/tests/ui/unnecessary_literal_unwrap.rs +++ b/tests/ui/unnecessary_literal_unwrap.rs @@ -1,5 +1,6 @@ //run-rustfix #![warn(clippy::unnecessary_literal_unwrap)] +#![allow(clippy::unnecessary_lazy_evaluations)] fn unwrap_option() { let _val = Some(1).unwrap(); @@ -15,11 +16,13 @@ fn unwrap_result() { fn unwrap_methods_option() { let _val = Some(1).unwrap_or(2); let _val = Some(1).unwrap_or_default(); + let _val = Some(1).unwrap_or_else(|| _val); } fn unwrap_methods_result() { let _val = Ok::(1).unwrap_or(2); let _val = Ok::(1).unwrap_or_default(); + let _val = Ok::(1).unwrap_or_else(|()| _val); } fn main() { diff --git a/tests/ui/unnecessary_literal_unwrap.stderr b/tests/ui/unnecessary_literal_unwrap.stderr index b8b5a612da1..60499fe700b 100644 --- a/tests/ui/unnecessary_literal_unwrap.stderr +++ b/tests/ui/unnecessary_literal_unwrap.stderr @@ -1,5 +1,5 @@ error: used `unwrap()` on `Some` value - --> $DIR/unnecessary_literal_unwrap.rs:5:16 + --> $DIR/unnecessary_literal_unwrap.rs:6:16 | LL | let _val = Some(1).unwrap(); | ^^^^^^^^^^^^^^^^ @@ -12,7 +12,7 @@ LL + let _val = 1; | error: used `expect()` on `Some` value - --> $DIR/unnecessary_literal_unwrap.rs:6:16 + --> $DIR/unnecessary_literal_unwrap.rs:7:16 | LL | let _val = Some(1).expect("this never happens"); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -24,7 +24,7 @@ LL + let _val = 1; | error: used `unwrap()` on `Ok` value - --> $DIR/unnecessary_literal_unwrap.rs:10:16 + --> $DIR/unnecessary_literal_unwrap.rs:11:16 | LL | let _val = Ok::(1).unwrap(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -36,7 +36,7 @@ LL + let _val = 1; | error: used `expect()` on `Ok` value - --> $DIR/unnecessary_literal_unwrap.rs:11:16 + --> $DIR/unnecessary_literal_unwrap.rs:12:16 | LL | let _val = Ok::(1).expect("this never happens"); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -48,7 +48,7 @@ LL + let _val = 1; | error: used `unwrap_or()` on `Some` value - --> $DIR/unnecessary_literal_unwrap.rs:16:16 + --> $DIR/unnecessary_literal_unwrap.rs:17:16 | LL | let _val = Some(1).unwrap_or(2); | ^^^^^^^^^^^^^^^^^^^^ @@ -60,7 +60,7 @@ LL + let _val = 1; | error: used `unwrap_or_default()` on `Some` value - --> $DIR/unnecessary_literal_unwrap.rs:17:16 + --> $DIR/unnecessary_literal_unwrap.rs:18:16 | LL | let _val = Some(1).unwrap_or_default(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -71,8 +71,20 @@ LL - let _val = Some(1).unwrap_or_default(); LL + let _val = 1; | +error: used `unwrap_or_else()` on `Some` value + --> $DIR/unnecessary_literal_unwrap.rs:19:16 + | +LL | let _val = Some(1).unwrap_or_else(|| _val); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: remove the `Some` and `unwrap_or_else()` + | +LL - let _val = Some(1).unwrap_or_else(|| _val); +LL + let _val = 1; + | + error: used `unwrap_or()` on `Ok` value - --> $DIR/unnecessary_literal_unwrap.rs:21:16 + --> $DIR/unnecessary_literal_unwrap.rs:23:16 | LL | let _val = Ok::(1).unwrap_or(2); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -84,7 +96,7 @@ LL + let _val = 1; | error: used `unwrap_or_default()` on `Ok` value - --> $DIR/unnecessary_literal_unwrap.rs:22:16 + --> $DIR/unnecessary_literal_unwrap.rs:24:16 | LL | let _val = Ok::(1).unwrap_or_default(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -95,5 +107,17 @@ LL - let _val = Ok::(1).unwrap_or_default(); LL + let _val = 1; | -error: aborting due to 8 previous errors +error: used `unwrap_or_else()` on `Ok` value + --> $DIR/unnecessary_literal_unwrap.rs:25:16 + | +LL | let _val = Ok::(1).unwrap_or_else(|()| _val); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: remove the `Ok` and `unwrap_or_else()` + | +LL - let _val = Ok::(1).unwrap_or_else(|()| _val); +LL + let _val = 1; + | + +error: aborting due to 10 previous errors From 6e0e09c8f7622caa6ea6536f2bbc5c033a9cffa2 Mon Sep 17 00:00:00 2001 From: rsdy Date: Thu, 16 Feb 2023 15:30:09 +0000 Subject: [PATCH 167/310] Track init and unwrap of expr --- .../src/methods/unnecessary_literal_unwrap.rs | 22 ++++++++++++++++--- .../unnecessary_literal_unwrap_unfixable.rs | 6 +++++ ...nnecessary_literal_unwrap_unfixable.stderr | 15 +++++++++++++ 3 files changed, 40 insertions(+), 3 deletions(-) create mode 100644 tests/ui/unnecessary_literal_unwrap_unfixable.rs create mode 100644 tests/ui/unnecessary_literal_unwrap_unfixable.stderr diff --git a/clippy_lints/src/methods/unnecessary_literal_unwrap.rs b/clippy_lints/src/methods/unnecessary_literal_unwrap.rs index 9a9c659b232..54160a27cb2 100644 --- a/clippy_lints/src/methods/unnecessary_literal_unwrap.rs +++ b/clippy_lints/src/methods/unnecessary_literal_unwrap.rs @@ -6,7 +6,9 @@ use rustc_lint::LateContext; use super::UNNECESSARY_LITERAL_UNWRAP; pub(super) fn check(cx: &LateContext<'_>, expr: &hir::Expr<'_>, recv: &hir::Expr<'_>, name: &str) { - if let hir::ExprKind::Call(call, [arg]) = recv.kind { + let init = clippy_utils::expr_or_init(cx, recv); + + if let hir::ExprKind::Call(call, [arg]) = init.kind { let mess = if is_res_lang_ctor(cx, path_res(cx, call), hir::LangItem::OptionSome) { Some("Some") } else if is_res_lang_ctor(cx, path_res(cx, call), hir::LangItem::ResultOk) { @@ -15,7 +17,11 @@ pub(super) fn check(cx: &LateContext<'_>, expr: &hir::Expr<'_>, recv: &hir::Expr None }; - if let Some(constructor) = mess { + let Some(constructor) = mess else { + return; + }; + + if init.span == recv.span { span_lint_and_then( cx, UNNECESSARY_LITERAL_UNWRAP, @@ -23,7 +29,7 @@ pub(super) fn check(cx: &LateContext<'_>, expr: &hir::Expr<'_>, recv: &hir::Expr &format!("used `{name}()` on `{constructor}` value"), |diag| { let suggestions = vec![ - (call.span.with_hi(arg.span.lo()), String::new()), + (recv.span.with_hi(arg.span.lo()), String::new()), (expr.span.with_lo(arg.span.hi()), String::new()), ]; @@ -34,6 +40,16 @@ pub(super) fn check(cx: &LateContext<'_>, expr: &hir::Expr<'_>, recv: &hir::Expr ); }, ); + } else { + span_lint_and_then( + cx, + UNNECESSARY_LITERAL_UNWRAP, + expr.span, + &format!("used `{name}()` on `{constructor}` value"), + |diag| { + diag.span_help(init.span, format!("remove the `{constructor}` and `{name}()`")); + }, + ); } } } diff --git a/tests/ui/unnecessary_literal_unwrap_unfixable.rs b/tests/ui/unnecessary_literal_unwrap_unfixable.rs new file mode 100644 index 00000000000..ac3a84934af --- /dev/null +++ b/tests/ui/unnecessary_literal_unwrap_unfixable.rs @@ -0,0 +1,6 @@ +#![warn(clippy::unnecessary_literal_unwrap)] + +fn main() { + let val = Some(1); + let _val2 = val.unwrap(); +} diff --git a/tests/ui/unnecessary_literal_unwrap_unfixable.stderr b/tests/ui/unnecessary_literal_unwrap_unfixable.stderr new file mode 100644 index 00000000000..abc789ccda4 --- /dev/null +++ b/tests/ui/unnecessary_literal_unwrap_unfixable.stderr @@ -0,0 +1,15 @@ +error: used `unwrap()` on `Some` value + --> $DIR/unnecessary_literal_unwrap_unfixable.rs:5:17 + | +LL | let _val2 = val.unwrap(); + | ^^^^^^^^^^^^ + | +help: remove the `Some` and `unwrap()` + --> $DIR/unnecessary_literal_unwrap_unfixable.rs:4:15 + | +LL | let val = Some(1); + | ^^^^^^^ + = note: `-D clippy::unnecessary-literal-unwrap` implied by `-D warnings` + +error: aborting due to previous error + From 69af0e13b2662807ba51ffc3a9fe4a9576e100e2 Mon Sep 17 00:00:00 2001 From: Pavan Kumar Sunkara Date: Thu, 16 Feb 2023 17:15:19 +0000 Subject: [PATCH 168/310] Recognize `Err` --- clippy_lints/src/methods/mod.rs | 10 ++++- .../src/methods/unnecessary_literal_unwrap.rs | 14 +++---- tests/ui/unnecessary_literal_unwrap.fixed | 11 ++++-- tests/ui/unnecessary_literal_unwrap.rs | 11 ++++-- tests/ui/unnecessary_literal_unwrap.stderr | 38 +++++++++++++++---- 5 files changed, 61 insertions(+), 23 deletions(-) diff --git a/clippy_lints/src/methods/mod.rs b/clippy_lints/src/methods/mod.rs index 4686adda683..66789e6137a 100644 --- a/clippy_lints/src/methods/mod.rs +++ b/clippy_lints/src/methods/mod.rs @@ -3666,7 +3666,10 @@ impl Methods { } unnecessary_literal_unwrap::check(cx, expr, recv, name); }, - ("expect_err", [_]) => expect_used::check(cx, expr, recv, true, self.allow_expect_in_tests), + ("expect_err", [_]) => { + unnecessary_literal_unwrap::check(cx, expr, recv, name); + expect_used::check(cx, expr, recv, true, self.allow_expect_in_tests); + }, ("extend", [arg]) => { string_extend_chars::check(cx, expr, recv, arg); extend_with_drain::check(cx, expr, recv, arg); @@ -3874,7 +3877,10 @@ impl Methods { unnecessary_literal_unwrap::check(cx, expr, recv, name); unwrap_used::check(cx, expr, recv, false, self.allow_unwrap_in_tests); }, - ("unwrap_err", []) => unwrap_used::check(cx, expr, recv, true, self.allow_unwrap_in_tests), + ("unwrap_err", []) => { + unnecessary_literal_unwrap::check(cx, expr, recv, name); + unwrap_used::check(cx, expr, recv, true, self.allow_unwrap_in_tests) + }, ("unwrap_or", [u_arg]) => { match method_call(recv) { Some((arith @ ("checked_add" | "checked_sub" | "checked_mul"), lhs, [rhs], _, _)) => { diff --git a/clippy_lints/src/methods/unnecessary_literal_unwrap.rs b/clippy_lints/src/methods/unnecessary_literal_unwrap.rs index 54160a27cb2..56d3c16a5d2 100644 --- a/clippy_lints/src/methods/unnecessary_literal_unwrap.rs +++ b/clippy_lints/src/methods/unnecessary_literal_unwrap.rs @@ -9,18 +9,16 @@ pub(super) fn check(cx: &LateContext<'_>, expr: &hir::Expr<'_>, recv: &hir::Expr let init = clippy_utils::expr_or_init(cx, recv); if let hir::ExprKind::Call(call, [arg]) = init.kind { - let mess = if is_res_lang_ctor(cx, path_res(cx, call), hir::LangItem::OptionSome) { - Some("Some") + let constructor = if is_res_lang_ctor(cx, path_res(cx, call), hir::LangItem::OptionSome) { + "Some" } else if is_res_lang_ctor(cx, path_res(cx, call), hir::LangItem::ResultOk) { - Some("Ok") + "Ok" + } else if is_res_lang_ctor(cx, path_res(cx, call), hir::LangItem::ResultErr) { + "Err" } else { - None + return; }; - let Some(constructor) = mess else { - return; - }; - if init.span == recv.span { span_lint_and_then( cx, diff --git a/tests/ui/unnecessary_literal_unwrap.fixed b/tests/ui/unnecessary_literal_unwrap.fixed index a388a7f83d2..9733993d619 100644 --- a/tests/ui/unnecessary_literal_unwrap.fixed +++ b/tests/ui/unnecessary_literal_unwrap.fixed @@ -7,10 +7,14 @@ fn unwrap_option() { let _val = 1; } -fn unwrap_result() { +fn unwrap_result_ok() { + let _val = 1; + let _val = 1; +} + +fn unwrap_result_err() { let _val = 1; let _val = 1; - // let val = Err(1).unwrap_err(); } fn unwrap_methods_option() { @@ -27,7 +31,8 @@ fn unwrap_methods_result() { fn main() { unwrap_option(); - unwrap_result(); + unwrap_result_ok(); + unwrap_result_err(); unwrap_methods_option(); unwrap_methods_result(); } diff --git a/tests/ui/unnecessary_literal_unwrap.rs b/tests/ui/unnecessary_literal_unwrap.rs index fe557957dd9..775d744c13e 100644 --- a/tests/ui/unnecessary_literal_unwrap.rs +++ b/tests/ui/unnecessary_literal_unwrap.rs @@ -7,10 +7,14 @@ fn unwrap_option() { let _val = Some(1).expect("this never happens"); } -fn unwrap_result() { +fn unwrap_result_ok() { let _val = Ok::(1).unwrap(); let _val = Ok::(1).expect("this never happens"); - // let val = Err(1).unwrap_err(); +} + +fn unwrap_result_err() { + let _val = Err::<(), usize>(1).unwrap_err(); + let _val = Err::<(), usize>(1).expect_err("this never happens"); } fn unwrap_methods_option() { @@ -27,7 +31,8 @@ fn unwrap_methods_result() { fn main() { unwrap_option(); - unwrap_result(); + unwrap_result_ok(); + unwrap_result_err(); unwrap_methods_option(); unwrap_methods_result(); } diff --git a/tests/ui/unnecessary_literal_unwrap.stderr b/tests/ui/unnecessary_literal_unwrap.stderr index 60499fe700b..622743f8c85 100644 --- a/tests/ui/unnecessary_literal_unwrap.stderr +++ b/tests/ui/unnecessary_literal_unwrap.stderr @@ -47,9 +47,33 @@ LL - let _val = Ok::(1).expect("this never happens"); LL + let _val = 1; | -error: used `unwrap_or()` on `Some` value +error: used `unwrap_err()` on `Err` value + --> $DIR/unnecessary_literal_unwrap.rs:16:16 + | +LL | let _val = Err::<(), usize>(1).unwrap_err(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: remove the `Err` and `unwrap_err()` + | +LL - let _val = Err::<(), usize>(1).unwrap_err(); +LL + let _val = 1; + | + +error: used `expect_err()` on `Err` value --> $DIR/unnecessary_literal_unwrap.rs:17:16 | +LL | let _val = Err::<(), usize>(1).expect_err("this never happens"); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: remove the `Err` and `expect_err()` + | +LL - let _val = Err::<(), usize>(1).expect_err("this never happens"); +LL + let _val = 1; + | + +error: used `unwrap_or()` on `Some` value + --> $DIR/unnecessary_literal_unwrap.rs:21:16 + | LL | let _val = Some(1).unwrap_or(2); | ^^^^^^^^^^^^^^^^^^^^ | @@ -60,7 +84,7 @@ LL + let _val = 1; | error: used `unwrap_or_default()` on `Some` value - --> $DIR/unnecessary_literal_unwrap.rs:18:16 + --> $DIR/unnecessary_literal_unwrap.rs:22:16 | LL | let _val = Some(1).unwrap_or_default(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -72,7 +96,7 @@ LL + let _val = 1; | error: used `unwrap_or_else()` on `Some` value - --> $DIR/unnecessary_literal_unwrap.rs:19:16 + --> $DIR/unnecessary_literal_unwrap.rs:23:16 | LL | let _val = Some(1).unwrap_or_else(|| _val); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -84,7 +108,7 @@ LL + let _val = 1; | error: used `unwrap_or()` on `Ok` value - --> $DIR/unnecessary_literal_unwrap.rs:23:16 + --> $DIR/unnecessary_literal_unwrap.rs:27:16 | LL | let _val = Ok::(1).unwrap_or(2); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -96,7 +120,7 @@ LL + let _val = 1; | error: used `unwrap_or_default()` on `Ok` value - --> $DIR/unnecessary_literal_unwrap.rs:24:16 + --> $DIR/unnecessary_literal_unwrap.rs:28:16 | LL | let _val = Ok::(1).unwrap_or_default(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -108,7 +132,7 @@ LL + let _val = 1; | error: used `unwrap_or_else()` on `Ok` value - --> $DIR/unnecessary_literal_unwrap.rs:25:16 + --> $DIR/unnecessary_literal_unwrap.rs:29:16 | LL | let _val = Ok::(1).unwrap_or_else(|()| _val); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -119,5 +143,5 @@ LL - let _val = Ok::(1).unwrap_or_else(|()| _val); LL + let _val = 1; | -error: aborting due to 10 previous errors +error: aborting due to 12 previous errors From 6e4dc93e24866018f2567a7a0baa1955a4c7d868 Mon Sep 17 00:00:00 2001 From: Pavan Kumar Sunkara Date: Thu, 16 Feb 2023 22:31:52 +0000 Subject: [PATCH 169/310] Support suggesting panics --- clippy_lints/src/methods/mod.rs | 16 ++-- .../src/methods/unnecessary_literal_unwrap.rs | 93 +++++++++++-------- tests/ui/unnecessary_literal_unwrap.fixed | 15 ++- tests/ui/unnecessary_literal_unwrap.rs | 15 ++- tests/ui/unnecessary_literal_unwrap.stderr | 87 ++++++++++++++--- 5 files changed, 164 insertions(+), 62 deletions(-) diff --git a/clippy_lints/src/methods/mod.rs b/clippy_lints/src/methods/mod.rs index 66789e6137a..912cce39e2e 100644 --- a/clippy_lints/src/methods/mod.rs +++ b/clippy_lints/src/methods/mod.rs @@ -3664,10 +3664,10 @@ impl Methods { Some(("err", recv, [], err_span, _)) => err_expect::check(cx, expr, recv, span, err_span, &self.msrv), _ => expect_used::check(cx, expr, recv, false, self.allow_expect_in_tests), } - unnecessary_literal_unwrap::check(cx, expr, recv, name); + unnecessary_literal_unwrap::check(cx, expr, recv, name, args); }, ("expect_err", [_]) => { - unnecessary_literal_unwrap::check(cx, expr, recv, name); + unnecessary_literal_unwrap::check(cx, expr, recv, name, args); expect_used::check(cx, expr, recv, true, self.allow_expect_in_tests); }, ("extend", [arg]) => { @@ -3874,12 +3874,12 @@ impl Methods { }, _ => {}, } - unnecessary_literal_unwrap::check(cx, expr, recv, name); + unnecessary_literal_unwrap::check(cx, expr, recv, name, args); unwrap_used::check(cx, expr, recv, false, self.allow_unwrap_in_tests); }, ("unwrap_err", []) => { - unnecessary_literal_unwrap::check(cx, expr, recv, name); - unwrap_used::check(cx, expr, recv, true, self.allow_unwrap_in_tests) + unnecessary_literal_unwrap::check(cx, expr, recv, name, args); + unwrap_used::check(cx, expr, recv, true, self.allow_unwrap_in_tests); }, ("unwrap_or", [u_arg]) => { match method_call(recv) { @@ -3894,10 +3894,10 @@ impl Methods { }, _ => {}, } - unnecessary_literal_unwrap::check(cx, expr, recv, name); + unnecessary_literal_unwrap::check(cx, expr, recv, name, args); }, ("unwrap_or_default", []) => { - unnecessary_literal_unwrap::check(cx, expr, recv, name); + unnecessary_literal_unwrap::check(cx, expr, recv, name, args); } ("unwrap_or_else", [u_arg]) => { match method_call(recv) { @@ -3908,7 +3908,7 @@ impl Methods { unnecessary_lazy_eval::check(cx, expr, recv, u_arg, "unwrap_or"); }, } - unnecessary_literal_unwrap::check(cx, expr, recv, name); + unnecessary_literal_unwrap::check(cx, expr, recv, name, args); }, ("zip", [arg]) => { if let ExprKind::MethodCall(name, iter_recv, [], _) = recv.kind diff --git a/clippy_lints/src/methods/unnecessary_literal_unwrap.rs b/clippy_lints/src/methods/unnecessary_literal_unwrap.rs index 56d3c16a5d2..fe6b86b34f5 100644 --- a/clippy_lints/src/methods/unnecessary_literal_unwrap.rs +++ b/clippy_lints/src/methods/unnecessary_literal_unwrap.rs @@ -5,49 +5,68 @@ use rustc_lint::LateContext; use super::UNNECESSARY_LITERAL_UNWRAP; -pub(super) fn check(cx: &LateContext<'_>, expr: &hir::Expr<'_>, recv: &hir::Expr<'_>, name: &str) { +pub(super) fn check( + cx: &LateContext<'_>, + expr: &hir::Expr<'_>, + recv: &hir::Expr<'_>, + method: &str, + args: &[hir::Expr<'_>], +) { let init = clippy_utils::expr_or_init(cx, recv); - if let hir::ExprKind::Call(call, [arg]) = init.kind { - let constructor = if is_res_lang_ctor(cx, path_res(cx, call), hir::LangItem::OptionSome) { - "Some" + let (constructor, call_args) = if let hir::ExprKind::Call(call, call_args) = init.kind { + if is_res_lang_ctor(cx, path_res(cx, call), hir::LangItem::OptionSome) { + ("Some", call_args) } else if is_res_lang_ctor(cx, path_res(cx, call), hir::LangItem::ResultOk) { - "Ok" + ("Ok", call_args) } else if is_res_lang_ctor(cx, path_res(cx, call), hir::LangItem::ResultErr) { - "Err" + ("Err", call_args) } else { return; - }; - - if init.span == recv.span { - span_lint_and_then( - cx, - UNNECESSARY_LITERAL_UNWRAP, - expr.span, - &format!("used `{name}()` on `{constructor}` value"), - |diag| { - let suggestions = vec![ - (recv.span.with_hi(arg.span.lo()), String::new()), - (expr.span.with_lo(arg.span.hi()), String::new()), - ]; - - diag.multipart_suggestion( - format!("remove the `{constructor}` and `{name}()`"), - suggestions, - Applicability::MachineApplicable, - ); - }, - ); - } else { - span_lint_and_then( - cx, - UNNECESSARY_LITERAL_UNWRAP, - expr.span, - &format!("used `{name}()` on `{constructor}` value"), - |diag| { - diag.span_help(init.span, format!("remove the `{constructor}` and `{name}()`")); - }, - ); } + } else if is_res_lang_ctor(cx, path_res(cx, init), hir::LangItem::OptionNone) { + let call_args: &[hir::Expr<'_>] = &[]; + ("None", call_args) + } else { + return; + }; + + let help_message = format!("used `{method}()` on `{constructor}` value"); + let suggestion_message = format!("remove the `{constructor}` and `{method}()`"); + + if init.span == recv.span { + span_lint_and_then(cx, UNNECESSARY_LITERAL_UNWRAP, expr.span, &help_message, |diag| { + let suggestions = match (constructor, method) { + ("None", "unwrap") => vec![(expr.span, "panic!()".to_string())], + ("None", "expect") => vec![ + (expr.span.with_hi(args[0].span.lo()), "panic!(".to_string()), + (expr.span.with_lo(args[0].span.hi()), ")".to_string()), + ], + ("Ok", "unwrap_err") | ("Err", "unwrap") => vec![ + ( + recv.span.with_hi(call_args[0].span.lo()), + "panic!(\"{:?}\", ".to_string(), + ), + (expr.span.with_lo(call_args[0].span.hi()), ")".to_string()), + ], + ("Ok", "expect_err") | ("Err", "expect") => vec![ + ( + recv.span.with_hi(call_args[0].span.lo()), + "panic!(\"{1}: {:?}\", ".to_string(), + ), + (call_args[0].span.with_lo(args[0].span.lo()), ", ".to_string()), + ], + _ => vec![ + (recv.span.with_hi(call_args[0].span.lo()), String::new()), + (expr.span.with_lo(call_args[0].span.hi()), String::new()), + ], + }; + + diag.multipart_suggestion(suggestion_message, suggestions, Applicability::MachineApplicable); + }); + } else { + span_lint_and_then(cx, UNNECESSARY_LITERAL_UNWRAP, expr.span, &help_message, |diag| { + diag.span_help(init.span, suggestion_message); + }); } } diff --git a/tests/ui/unnecessary_literal_unwrap.fixed b/tests/ui/unnecessary_literal_unwrap.fixed index 9733993d619..d622c984c52 100644 --- a/tests/ui/unnecessary_literal_unwrap.fixed +++ b/tests/ui/unnecessary_literal_unwrap.fixed @@ -1,20 +1,30 @@ //run-rustfix #![warn(clippy::unnecessary_literal_unwrap)] #![allow(clippy::unnecessary_lazy_evaluations)] +#![allow(unreachable_code)] -fn unwrap_option() { +fn unwrap_option_some() { let _val = 1; let _val = 1; } +fn unwrap_option_none() { + panic!(); + panic!("this always happens"); +} + fn unwrap_result_ok() { let _val = 1; let _val = 1; + panic!("{:?}", 1); + panic!("{1}: {:?}", 1, "this always happens"); } fn unwrap_result_err() { let _val = 1; let _val = 1; + panic!("{:?}", 1); + panic!("{1}: {:?}", 1, "this always happens"); } fn unwrap_methods_option() { @@ -30,7 +40,8 @@ fn unwrap_methods_result() { } fn main() { - unwrap_option(); + unwrap_option_some(); + unwrap_option_none(); unwrap_result_ok(); unwrap_result_err(); unwrap_methods_option(); diff --git a/tests/ui/unnecessary_literal_unwrap.rs b/tests/ui/unnecessary_literal_unwrap.rs index 775d744c13e..926265a3471 100644 --- a/tests/ui/unnecessary_literal_unwrap.rs +++ b/tests/ui/unnecessary_literal_unwrap.rs @@ -1,20 +1,30 @@ //run-rustfix #![warn(clippy::unnecessary_literal_unwrap)] #![allow(clippy::unnecessary_lazy_evaluations)] +#![allow(unreachable_code)] -fn unwrap_option() { +fn unwrap_option_some() { let _val = Some(1).unwrap(); let _val = Some(1).expect("this never happens"); } +fn unwrap_option_none() { + None::.unwrap(); + None::.expect("this always happens"); +} + fn unwrap_result_ok() { let _val = Ok::(1).unwrap(); let _val = Ok::(1).expect("this never happens"); + Ok::(1).unwrap_err(); + Ok::(1).expect_err("this always happens"); } fn unwrap_result_err() { let _val = Err::<(), usize>(1).unwrap_err(); let _val = Err::<(), usize>(1).expect_err("this never happens"); + Err::<(), usize>(1).unwrap(); + Err::<(), usize>(1).expect("this always happens"); } fn unwrap_methods_option() { @@ -30,7 +40,8 @@ fn unwrap_methods_result() { } fn main() { - unwrap_option(); + unwrap_option_some(); + unwrap_option_none(); unwrap_result_ok(); unwrap_result_err(); unwrap_methods_option(); diff --git a/tests/ui/unnecessary_literal_unwrap.stderr b/tests/ui/unnecessary_literal_unwrap.stderr index 622743f8c85..1d23bb22bdd 100644 --- a/tests/ui/unnecessary_literal_unwrap.stderr +++ b/tests/ui/unnecessary_literal_unwrap.stderr @@ -1,5 +1,5 @@ error: used `unwrap()` on `Some` value - --> $DIR/unnecessary_literal_unwrap.rs:6:16 + --> $DIR/unnecessary_literal_unwrap.rs:7:16 | LL | let _val = Some(1).unwrap(); | ^^^^^^^^^^^^^^^^ @@ -12,7 +12,7 @@ LL + let _val = 1; | error: used `expect()` on `Some` value - --> $DIR/unnecessary_literal_unwrap.rs:7:16 + --> $DIR/unnecessary_literal_unwrap.rs:8:16 | LL | let _val = Some(1).expect("this never happens"); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -23,8 +23,25 @@ LL - let _val = Some(1).expect("this never happens"); LL + let _val = 1; | +error: used `unwrap()` on `None` value + --> $DIR/unnecessary_literal_unwrap.rs:12:5 + | +LL | None::.unwrap(); + | ^^^^^^^^^^^^^^^^^^^^^^ help: remove the `None` and `unwrap()`: `panic!()` + +error: used `expect()` on `None` value + --> $DIR/unnecessary_literal_unwrap.rs:13:5 + | +LL | None::.expect("this always happens"); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: remove the `None` and `expect()` + | +LL | panic!("this always happens"); + | ~~~~~~~ ~ + error: used `unwrap()` on `Ok` value - --> $DIR/unnecessary_literal_unwrap.rs:11:16 + --> $DIR/unnecessary_literal_unwrap.rs:17:16 | LL | let _val = Ok::(1).unwrap(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -36,7 +53,7 @@ LL + let _val = 1; | error: used `expect()` on `Ok` value - --> $DIR/unnecessary_literal_unwrap.rs:12:16 + --> $DIR/unnecessary_literal_unwrap.rs:18:16 | LL | let _val = Ok::(1).expect("this never happens"); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -47,8 +64,30 @@ LL - let _val = Ok::(1).expect("this never happens"); LL + let _val = 1; | +error: used `unwrap_err()` on `Ok` value + --> $DIR/unnecessary_literal_unwrap.rs:19:5 + | +LL | Ok::(1).unwrap_err(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: remove the `Ok` and `unwrap_err()` + | +LL | panic!("{:?}", 1); + | ~~~~~~~~~~~~~~ ~ + +error: used `expect_err()` on `Ok` value + --> $DIR/unnecessary_literal_unwrap.rs:20:5 + | +LL | Ok::(1).expect_err("this always happens"); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: remove the `Ok` and `expect_err()` + | +LL | panic!("{1}: {:?}", 1, "this always happens"); + | ~~~~~~~~~~~~~~~~~~~ ~ + error: used `unwrap_err()` on `Err` value - --> $DIR/unnecessary_literal_unwrap.rs:16:16 + --> $DIR/unnecessary_literal_unwrap.rs:24:16 | LL | let _val = Err::<(), usize>(1).unwrap_err(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -60,7 +99,7 @@ LL + let _val = 1; | error: used `expect_err()` on `Err` value - --> $DIR/unnecessary_literal_unwrap.rs:17:16 + --> $DIR/unnecessary_literal_unwrap.rs:25:16 | LL | let _val = Err::<(), usize>(1).expect_err("this never happens"); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -71,8 +110,30 @@ LL - let _val = Err::<(), usize>(1).expect_err("this never happens"); LL + let _val = 1; | +error: used `unwrap()` on `Err` value + --> $DIR/unnecessary_literal_unwrap.rs:26:5 + | +LL | Err::<(), usize>(1).unwrap(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: remove the `Err` and `unwrap()` + | +LL | panic!("{:?}", 1); + | ~~~~~~~~~~~~~~ ~ + +error: used `expect()` on `Err` value + --> $DIR/unnecessary_literal_unwrap.rs:27:5 + | +LL | Err::<(), usize>(1).expect("this always happens"); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: remove the `Err` and `expect()` + | +LL | panic!("{1}: {:?}", 1, "this always happens"); + | ~~~~~~~~~~~~~~~~~~~ ~ + error: used `unwrap_or()` on `Some` value - --> $DIR/unnecessary_literal_unwrap.rs:21:16 + --> $DIR/unnecessary_literal_unwrap.rs:31:16 | LL | let _val = Some(1).unwrap_or(2); | ^^^^^^^^^^^^^^^^^^^^ @@ -84,7 +145,7 @@ LL + let _val = 1; | error: used `unwrap_or_default()` on `Some` value - --> $DIR/unnecessary_literal_unwrap.rs:22:16 + --> $DIR/unnecessary_literal_unwrap.rs:32:16 | LL | let _val = Some(1).unwrap_or_default(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -96,7 +157,7 @@ LL + let _val = 1; | error: used `unwrap_or_else()` on `Some` value - --> $DIR/unnecessary_literal_unwrap.rs:23:16 + --> $DIR/unnecessary_literal_unwrap.rs:33:16 | LL | let _val = Some(1).unwrap_or_else(|| _val); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -108,7 +169,7 @@ LL + let _val = 1; | error: used `unwrap_or()` on `Ok` value - --> $DIR/unnecessary_literal_unwrap.rs:27:16 + --> $DIR/unnecessary_literal_unwrap.rs:37:16 | LL | let _val = Ok::(1).unwrap_or(2); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -120,7 +181,7 @@ LL + let _val = 1; | error: used `unwrap_or_default()` on `Ok` value - --> $DIR/unnecessary_literal_unwrap.rs:28:16 + --> $DIR/unnecessary_literal_unwrap.rs:38:16 | LL | let _val = Ok::(1).unwrap_or_default(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -132,7 +193,7 @@ LL + let _val = 1; | error: used `unwrap_or_else()` on `Ok` value - --> $DIR/unnecessary_literal_unwrap.rs:29:16 + --> $DIR/unnecessary_literal_unwrap.rs:39:16 | LL | let _val = Ok::(1).unwrap_or_else(|()| _val); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -143,5 +204,5 @@ LL - let _val = Ok::(1).unwrap_or_else(|()| _val); LL + let _val = 1; | -error: aborting due to 12 previous errors +error: aborting due to 18 previous errors From 6cf138e9b63e63b913b5b567d9a1cb6870a8738f Mon Sep 17 00:00:00 2001 From: Pavan Kumar Sunkara Date: Thu, 16 Feb 2023 23:14:20 +0000 Subject: [PATCH 170/310] Add more tests --- tests/ui/unnecessary_literal_unwrap.fixed | 4 +- tests/ui/unnecessary_literal_unwrap.rs | 8 +- tests/ui/unnecessary_literal_unwrap.stderr | 12 +- .../unnecessary_literal_unwrap_unfixable.rs | 50 ++++- ...nnecessary_literal_unwrap_unfixable.stderr | 210 +++++++++++++++++- 5 files changed, 268 insertions(+), 16 deletions(-) diff --git a/tests/ui/unnecessary_literal_unwrap.fixed b/tests/ui/unnecessary_literal_unwrap.fixed index d622c984c52..41c4dfda47f 100644 --- a/tests/ui/unnecessary_literal_unwrap.fixed +++ b/tests/ui/unnecessary_literal_unwrap.fixed @@ -1,7 +1,7 @@ -//run-rustfix +//@run-rustfix #![warn(clippy::unnecessary_literal_unwrap)] -#![allow(clippy::unnecessary_lazy_evaluations)] #![allow(unreachable_code)] +#![allow(clippy::unnecessary_lazy_evaluations)] fn unwrap_option_some() { let _val = 1; diff --git a/tests/ui/unnecessary_literal_unwrap.rs b/tests/ui/unnecessary_literal_unwrap.rs index 926265a3471..f15c063fe54 100644 --- a/tests/ui/unnecessary_literal_unwrap.rs +++ b/tests/ui/unnecessary_literal_unwrap.rs @@ -1,7 +1,7 @@ -//run-rustfix +//@run-rustfix #![warn(clippy::unnecessary_literal_unwrap)] -#![allow(clippy::unnecessary_lazy_evaluations)] #![allow(unreachable_code)] +#![allow(clippy::unnecessary_lazy_evaluations)] fn unwrap_option_some() { let _val = Some(1).unwrap(); @@ -30,13 +30,13 @@ fn unwrap_result_err() { fn unwrap_methods_option() { let _val = Some(1).unwrap_or(2); let _val = Some(1).unwrap_or_default(); - let _val = Some(1).unwrap_or_else(|| _val); + let _val = Some(1).unwrap_or_else(|| 2); } fn unwrap_methods_result() { let _val = Ok::(1).unwrap_or(2); let _val = Ok::(1).unwrap_or_default(); - let _val = Ok::(1).unwrap_or_else(|()| _val); + let _val = Ok::(1).unwrap_or_else(|_| 2); } fn main() { diff --git a/tests/ui/unnecessary_literal_unwrap.stderr b/tests/ui/unnecessary_literal_unwrap.stderr index 1d23bb22bdd..cf057d7fe5a 100644 --- a/tests/ui/unnecessary_literal_unwrap.stderr +++ b/tests/ui/unnecessary_literal_unwrap.stderr @@ -159,12 +159,12 @@ LL + let _val = 1; error: used `unwrap_or_else()` on `Some` value --> $DIR/unnecessary_literal_unwrap.rs:33:16 | -LL | let _val = Some(1).unwrap_or_else(|| _val); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | let _val = Some(1).unwrap_or_else(|| 2); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | help: remove the `Some` and `unwrap_or_else()` | -LL - let _val = Some(1).unwrap_or_else(|| _val); +LL - let _val = Some(1).unwrap_or_else(|| 2); LL + let _val = 1; | @@ -195,12 +195,12 @@ LL + let _val = 1; error: used `unwrap_or_else()` on `Ok` value --> $DIR/unnecessary_literal_unwrap.rs:39:16 | -LL | let _val = Ok::(1).unwrap_or_else(|()| _val); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | let _val = Ok::(1).unwrap_or_else(|_| 2); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | help: remove the `Ok` and `unwrap_or_else()` | -LL - let _val = Ok::(1).unwrap_or_else(|()| _val); +LL - let _val = Ok::(1).unwrap_or_else(|_| 2); LL + let _val = 1; | diff --git a/tests/ui/unnecessary_literal_unwrap_unfixable.rs b/tests/ui/unnecessary_literal_unwrap_unfixable.rs index ac3a84934af..9ccf6b21447 100644 --- a/tests/ui/unnecessary_literal_unwrap_unfixable.rs +++ b/tests/ui/unnecessary_literal_unwrap_unfixable.rs @@ -1,6 +1,54 @@ #![warn(clippy::unnecessary_literal_unwrap)] +#![allow(clippy::unnecessary_lazy_evaluations)] +#![allow(unreachable_code)] -fn main() { +fn unwrap_option_some() { let val = Some(1); let _val2 = val.unwrap(); + let _val2 = val.expect("this never happens"); +} + +fn unwrap_option_none() { + let val = None::; + val.unwrap(); + val.expect("this always happens"); +} + +fn unwrap_result_ok() { + let val = Ok::(1); + let _val2 = val.unwrap(); + let _val2 = val.expect("this never happens"); + val.unwrap_err(); + val.expect_err("this always happens"); +} + +fn unwrap_result_err() { + let val = Err::<(), usize>(1); + let _val2 = val.unwrap_err(); + let _val2 = val.expect_err("this never happens"); + val.unwrap(); + val.expect("this always happens"); +} + +fn unwrap_methods_option() { + let val = Some(1); + let _val2 = val.unwrap_or(2); + let _val2 = val.unwrap_or_default(); + let _val2 = val.unwrap_or_else(|| 2); +} + +fn unwrap_methods_result() { + let val = Ok::(1); + let _val2 = val.unwrap_or(2); + let _val2 = val.unwrap_or_default(); + let _val2 = val.unwrap_or_else(|_| 2); +} + +fn main() { + unwrap_option_some(); + unwrap_option_none(); + unwrap_result_ok(); + unwrap_result_err(); + unwrap_methods_option(); + unwrap_methods_result(); } diff --git a/tests/ui/unnecessary_literal_unwrap_unfixable.stderr b/tests/ui/unnecessary_literal_unwrap_unfixable.stderr index abc789ccda4..7931deeca7f 100644 --- a/tests/ui/unnecessary_literal_unwrap_unfixable.stderr +++ b/tests/ui/unnecessary_literal_unwrap_unfixable.stderr @@ -1,15 +1,219 @@ error: used `unwrap()` on `Some` value - --> $DIR/unnecessary_literal_unwrap_unfixable.rs:5:17 + --> $DIR/unnecessary_literal_unwrap_unfixable.rs:7:17 | LL | let _val2 = val.unwrap(); | ^^^^^^^^^^^^ | help: remove the `Some` and `unwrap()` - --> $DIR/unnecessary_literal_unwrap_unfixable.rs:4:15 + --> $DIR/unnecessary_literal_unwrap_unfixable.rs:6:15 | LL | let val = Some(1); | ^^^^^^^ = note: `-D clippy::unnecessary-literal-unwrap` implied by `-D warnings` -error: aborting due to previous error +error: used `expect()` on `Some` value + --> $DIR/unnecessary_literal_unwrap_unfixable.rs:8:17 + | +LL | let _val2 = val.expect("this never happens"); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: remove the `Some` and `expect()` + --> $DIR/unnecessary_literal_unwrap_unfixable.rs:6:15 + | +LL | let val = Some(1); + | ^^^^^^^ + +error: used `unwrap()` on `None` value + --> $DIR/unnecessary_literal_unwrap_unfixable.rs:13:5 + | +LL | val.unwrap(); + | ^^^^^^^^^^^^ + | +help: remove the `None` and `unwrap()` + --> $DIR/unnecessary_literal_unwrap_unfixable.rs:12:15 + | +LL | let val = None::; + | ^^^^^^^^^^^^^ + +error: used `expect()` on `None` value + --> $DIR/unnecessary_literal_unwrap_unfixable.rs:14:5 + | +LL | val.expect("this always happens"); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: remove the `None` and `expect()` + --> $DIR/unnecessary_literal_unwrap_unfixable.rs:12:15 + | +LL | let val = None::; + | ^^^^^^^^^^^^^ + +error: used `unwrap()` on `Ok` value + --> $DIR/unnecessary_literal_unwrap_unfixable.rs:19:17 + | +LL | let _val2 = val.unwrap(); + | ^^^^^^^^^^^^ + | +help: remove the `Ok` and `unwrap()` + --> $DIR/unnecessary_literal_unwrap_unfixable.rs:18:15 + | +LL | let val = Ok::(1); + | ^^^^^^^^^^^^^^^^^^ + +error: used `expect()` on `Ok` value + --> $DIR/unnecessary_literal_unwrap_unfixable.rs:20:17 + | +LL | let _val2 = val.expect("this never happens"); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: remove the `Ok` and `expect()` + --> $DIR/unnecessary_literal_unwrap_unfixable.rs:18:15 + | +LL | let val = Ok::(1); + | ^^^^^^^^^^^^^^^^^^ + +error: used `unwrap_err()` on `Ok` value + --> $DIR/unnecessary_literal_unwrap_unfixable.rs:21:5 + | +LL | val.unwrap_err(); + | ^^^^^^^^^^^^^^^^ + | +help: remove the `Ok` and `unwrap_err()` + --> $DIR/unnecessary_literal_unwrap_unfixable.rs:18:15 + | +LL | let val = Ok::(1); + | ^^^^^^^^^^^^^^^^^^ + +error: used `expect_err()` on `Ok` value + --> $DIR/unnecessary_literal_unwrap_unfixable.rs:22:5 + | +LL | val.expect_err("this always happens"); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: remove the `Ok` and `expect_err()` + --> $DIR/unnecessary_literal_unwrap_unfixable.rs:18:15 + | +LL | let val = Ok::(1); + | ^^^^^^^^^^^^^^^^^^ + +error: used `unwrap_err()` on `Err` value + --> $DIR/unnecessary_literal_unwrap_unfixable.rs:27:17 + | +LL | let _val2 = val.unwrap_err(); + | ^^^^^^^^^^^^^^^^ + | +help: remove the `Err` and `unwrap_err()` + --> $DIR/unnecessary_literal_unwrap_unfixable.rs:26:15 + | +LL | let val = Err::<(), usize>(1); + | ^^^^^^^^^^^^^^^^^^^ + +error: used `expect_err()` on `Err` value + --> $DIR/unnecessary_literal_unwrap_unfixable.rs:28:17 + | +LL | let _val2 = val.expect_err("this never happens"); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: remove the `Err` and `expect_err()` + --> $DIR/unnecessary_literal_unwrap_unfixable.rs:26:15 + | +LL | let val = Err::<(), usize>(1); + | ^^^^^^^^^^^^^^^^^^^ + +error: used `unwrap()` on `Err` value + --> $DIR/unnecessary_literal_unwrap_unfixable.rs:29:5 + | +LL | val.unwrap(); + | ^^^^^^^^^^^^ + | +help: remove the `Err` and `unwrap()` + --> $DIR/unnecessary_literal_unwrap_unfixable.rs:26:15 + | +LL | let val = Err::<(), usize>(1); + | ^^^^^^^^^^^^^^^^^^^ + +error: used `expect()` on `Err` value + --> $DIR/unnecessary_literal_unwrap_unfixable.rs:30:5 + | +LL | val.expect("this always happens"); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: remove the `Err` and `expect()` + --> $DIR/unnecessary_literal_unwrap_unfixable.rs:26:15 + | +LL | let val = Err::<(), usize>(1); + | ^^^^^^^^^^^^^^^^^^^ + +error: used `unwrap_or()` on `Some` value + --> $DIR/unnecessary_literal_unwrap_unfixable.rs:35:17 + | +LL | let _val2 = val.unwrap_or(2); + | ^^^^^^^^^^^^^^^^ + | +help: remove the `Some` and `unwrap_or()` + --> $DIR/unnecessary_literal_unwrap_unfixable.rs:34:15 + | +LL | let val = Some(1); + | ^^^^^^^ + +error: used `unwrap_or_default()` on `Some` value + --> $DIR/unnecessary_literal_unwrap_unfixable.rs:36:17 + | +LL | let _val2 = val.unwrap_or_default(); + | ^^^^^^^^^^^^^^^^^^^^^^^ + | +help: remove the `Some` and `unwrap_or_default()` + --> $DIR/unnecessary_literal_unwrap_unfixable.rs:34:15 + | +LL | let val = Some(1); + | ^^^^^^^ + +error: used `unwrap_or_else()` on `Some` value + --> $DIR/unnecessary_literal_unwrap_unfixable.rs:37:17 + | +LL | let _val2 = val.unwrap_or_else(|| 2); + | ^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: remove the `Some` and `unwrap_or_else()` + --> $DIR/unnecessary_literal_unwrap_unfixable.rs:34:15 + | +LL | let val = Some(1); + | ^^^^^^^ + +error: used `unwrap_or()` on `Ok` value + --> $DIR/unnecessary_literal_unwrap_unfixable.rs:42:17 + | +LL | let _val2 = val.unwrap_or(2); + | ^^^^^^^^^^^^^^^^ + | +help: remove the `Ok` and `unwrap_or()` + --> $DIR/unnecessary_literal_unwrap_unfixable.rs:41:15 + | +LL | let val = Ok::(1); + | ^^^^^^^^^^^^^^^^^^ + +error: used `unwrap_or_default()` on `Ok` value + --> $DIR/unnecessary_literal_unwrap_unfixable.rs:43:17 + | +LL | let _val2 = val.unwrap_or_default(); + | ^^^^^^^^^^^^^^^^^^^^^^^ + | +help: remove the `Ok` and `unwrap_or_default()` + --> $DIR/unnecessary_literal_unwrap_unfixable.rs:41:15 + | +LL | let val = Ok::(1); + | ^^^^^^^^^^^^^^^^^^ + +error: used `unwrap_or_else()` on `Ok` value + --> $DIR/unnecessary_literal_unwrap_unfixable.rs:44:17 + | +LL | let _val2 = val.unwrap_or_else(|_| 2); + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: remove the `Ok` and `unwrap_or_else()` + --> $DIR/unnecessary_literal_unwrap_unfixable.rs:41:15 + | +LL | let val = Ok::(1); + | ^^^^^^^^^^^^^^^^^^ + +error: aborting due to 18 previous errors From 6e4c5561be566c164c7519e6e3c6772f2da17cb4 Mon Sep 17 00:00:00 2001 From: Pavan Kumar Sunkara Date: Wed, 31 May 2023 20:09:12 +0100 Subject: [PATCH 171/310] Preserve type annotations when present --- clippy_lints/src/methods/mod.rs | 42 +- .../src/methods/unnecessary_literal_unwrap.rs | 109 ++-- tests/ui/unnecessary_literal_unwrap.fixed | 31 +- tests/ui/unnecessary_literal_unwrap.rs | 57 +- tests/ui/unnecessary_literal_unwrap.stderr | 311 +++++++++-- .../unnecessary_literal_unwrap_unfixable.rs | 84 ++- ...nnecessary_literal_unwrap_unfixable.stderr | 528 +++++++++++++++--- 7 files changed, 935 insertions(+), 227 deletions(-) diff --git a/clippy_lints/src/methods/mod.rs b/clippy_lints/src/methods/mod.rs index 912cce39e2e..183bd582a48 100644 --- a/clippy_lints/src/methods/mod.rs +++ b/clippy_lints/src/methods/mod.rs @@ -276,52 +276,28 @@ declare_clippy_lint! { declare_clippy_lint! { /// ### What it does - /// Checks for `.unwrap()` or `.unwrap_err()` calls on `Result`s and `.unwrap()` call on `Option`s. + /// Checks for `.unwrap()` related calls on `Result`s and `Option`s that are constructed. /// /// ### Why is this bad? - /// It is better to handle the `None` or `Err` case, - /// or at least call `.expect(_)` with a more helpful message. Still, for a lot of - /// quick-and-dirty code, `unwrap` is a good choice, which is why this lint is - /// `Allow` by default. - /// - /// `result.unwrap()` will let the thread panic on `Err` values. - /// Normally, you want to implement more sophisticated error handling, - /// and propagate errors upwards with `?` operator. - /// - /// Even if you want to panic on errors, not all `Error`s implement good - /// messages on display. Therefore, it may be beneficial to look at the places - /// where they may get displayed. Activate this lint to do just that. + /// It is better to write the value directly without the indirection. /// /// ### Examples /// ```rust - /// # let option = Some(1); - /// # let result: Result = Ok(1); - /// option.unwrap(); - /// result.unwrap(); + /// let val1 = Some(1).unwrap(); + /// let val2 = Ok::<_, ()>(1).unwrap(); + /// let val3 = Err::<(), _>(1).unwrap_err(); /// ``` /// /// Use instead: /// ```rust - /// # let option = Some(1); - /// # let result: Result = Ok(1); - /// option.expect("more helpful message"); - /// result.expect("more helpful message"); - /// ``` - /// - /// If [expect_used](#expect_used) is enabled, instead: - /// ```rust,ignore - /// # let option = Some(1); - /// # let result: Result = Ok(1); - /// option?; - /// - /// // or - /// - /// result?; + /// let val1 = 1; + /// let val2 = 1; + /// let val3 = 1; /// ``` #[clippy::version = "1.69.0"] pub UNNECESSARY_LITERAL_UNWRAP, complexity, - "checks for calls of `unwrap()` or `expect()` on `Some()` that cannot fail" + "using `unwrap()` related calls on `Result` and `Option` constructors" } declare_clippy_lint! { diff --git a/clippy_lints/src/methods/unnecessary_literal_unwrap.rs b/clippy_lints/src/methods/unnecessary_literal_unwrap.rs index fe6b86b34f5..7877f6a386c 100644 --- a/clippy_lints/src/methods/unnecessary_literal_unwrap.rs +++ b/clippy_lints/src/methods/unnecessary_literal_unwrap.rs @@ -1,10 +1,26 @@ -use clippy_utils::{diagnostics::span_lint_and_then, is_res_lang_ctor, path_res}; +use clippy_utils::{diagnostics::span_lint_and_then, is_res_lang_ctor, last_path_segment, path_res, MaybePath}; use rustc_errors::Applicability; use rustc_hir as hir; use rustc_lint::LateContext; use super::UNNECESSARY_LITERAL_UNWRAP; +fn get_ty_from_args<'a>(args: Option<&'a [hir::GenericArg<'a>]>, index: usize) -> Option<&'a hir::Ty<'a>> { + let args = args?; + + if args.len() <= index { + return None; + } + + match args[index] { + hir::GenericArg::Type(ty) => match ty.kind { + hir::TyKind::Infer => None, + _ => Some(ty), + }, + _ => None, + } +} + pub(super) fn check( cx: &LateContext<'_>, expr: &hir::Expr<'_>, @@ -14,19 +30,24 @@ pub(super) fn check( ) { let init = clippy_utils::expr_or_init(cx, recv); - let (constructor, call_args) = if let hir::ExprKind::Call(call, call_args) = init.kind { - if is_res_lang_ctor(cx, path_res(cx, call), hir::LangItem::OptionSome) { - ("Some", call_args) - } else if is_res_lang_ctor(cx, path_res(cx, call), hir::LangItem::ResultOk) { - ("Ok", call_args) - } else if is_res_lang_ctor(cx, path_res(cx, call), hir::LangItem::ResultErr) { - ("Err", call_args) + let (constructor, call_args, ty) = if let hir::ExprKind::Call(call, call_args) = init.kind { + let Some(qpath) = call.qpath_opt() else { return }; + + let args = last_path_segment(qpath).args.map(|args| args.args); + let res = cx.qpath_res(qpath, call.hir_id()); + + if is_res_lang_ctor(cx, res, hir::LangItem::OptionSome) { + ("Some", call_args, get_ty_from_args(args, 0)) + } else if is_res_lang_ctor(cx, res, hir::LangItem::ResultOk) { + ("Ok", call_args, get_ty_from_args(args, 0)) + } else if is_res_lang_ctor(cx, res, hir::LangItem::ResultErr) { + ("Err", call_args, get_ty_from_args(args, 1)) } else { return; } } else if is_res_lang_ctor(cx, path_res(cx, init), hir::LangItem::OptionNone) { let call_args: &[hir::Expr<'_>] = &[]; - ("None", call_args) + ("None", call_args, None) } else { return; }; @@ -34,39 +55,41 @@ pub(super) fn check( let help_message = format!("used `{method}()` on `{constructor}` value"); let suggestion_message = format!("remove the `{constructor}` and `{method}()`"); - if init.span == recv.span { - span_lint_and_then(cx, UNNECESSARY_LITERAL_UNWRAP, expr.span, &help_message, |diag| { - let suggestions = match (constructor, method) { - ("None", "unwrap") => vec![(expr.span, "panic!()".to_string())], - ("None", "expect") => vec![ - (expr.span.with_hi(args[0].span.lo()), "panic!(".to_string()), - (expr.span.with_lo(args[0].span.hi()), ")".to_string()), - ], - ("Ok", "unwrap_err") | ("Err", "unwrap") => vec![ - ( - recv.span.with_hi(call_args[0].span.lo()), - "panic!(\"{:?}\", ".to_string(), - ), - (expr.span.with_lo(call_args[0].span.hi()), ")".to_string()), - ], - ("Ok", "expect_err") | ("Err", "expect") => vec![ - ( - recv.span.with_hi(call_args[0].span.lo()), - "panic!(\"{1}: {:?}\", ".to_string(), - ), - (call_args[0].span.with_lo(args[0].span.lo()), ", ".to_string()), - ], - _ => vec![ - (recv.span.with_hi(call_args[0].span.lo()), String::new()), - (expr.span.with_lo(call_args[0].span.hi()), String::new()), - ], - }; + span_lint_and_then(cx, UNNECESSARY_LITERAL_UNWRAP, expr.span, &help_message, |diag| { + let suggestions = match (constructor, method, ty) { + ("None", "unwrap", _) => Some(vec![(expr.span, "panic!()".to_string())]), + ("None", "expect", _) => Some(vec![ + (expr.span.with_hi(args[0].span.lo()), "panic!(".to_string()), + (expr.span.with_lo(args[0].span.hi()), ")".to_string()), + ]), + (_, _, Some(_)) => None, + ("Ok", "unwrap_err", None) | ("Err", "unwrap", None) => Some(vec![ + ( + recv.span.with_hi(call_args[0].span.lo()), + "panic!(\"{:?}\", ".to_string(), + ), + (expr.span.with_lo(call_args[0].span.hi()), ")".to_string()), + ]), + ("Ok", "expect_err", None) | ("Err", "expect", None) => Some(vec![ + ( + recv.span.with_hi(call_args[0].span.lo()), + "panic!(\"{1}: {:?}\", ".to_string(), + ), + (call_args[0].span.with_lo(args[0].span.lo()), ", ".to_string()), + ]), + (_, _, None) => Some(vec![ + (recv.span.with_hi(call_args[0].span.lo()), String::new()), + (expr.span.with_lo(call_args[0].span.hi()), String::new()), + ]), + }; - diag.multipart_suggestion(suggestion_message, suggestions, Applicability::MachineApplicable); - }); - } else { - span_lint_and_then(cx, UNNECESSARY_LITERAL_UNWRAP, expr.span, &help_message, |diag| { - diag.span_help(init.span, suggestion_message); - }); - } + match (init.span == recv.span, suggestions) { + (true, Some(suggestions)) => { + diag.multipart_suggestion(suggestion_message, suggestions, Applicability::MachineApplicable); + }, + _ => { + diag.span_help(init.span, suggestion_message); + }, + } + }); } diff --git a/tests/ui/unnecessary_literal_unwrap.fixed b/tests/ui/unnecessary_literal_unwrap.fixed index 41c4dfda47f..630a1bea3c8 100644 --- a/tests/ui/unnecessary_literal_unwrap.fixed +++ b/tests/ui/unnecessary_literal_unwrap.fixed @@ -1,14 +1,25 @@ //@run-rustfix #![warn(clippy::unnecessary_literal_unwrap)] #![allow(unreachable_code)] -#![allow(clippy::unnecessary_lazy_evaluations)] +#![allow( + clippy::unnecessary_lazy_evaluations, + clippy::diverging_sub_expression, + clippy::let_unit_value, + clippy::no_effect +)] fn unwrap_option_some() { let _val = 1; let _val = 1; + + 1; + 1; } fn unwrap_option_none() { + let _val = panic!(); + let _val = panic!("this always happens"); + panic!(); panic!("this always happens"); } @@ -16,6 +27,11 @@ fn unwrap_option_none() { fn unwrap_result_ok() { let _val = 1; let _val = 1; + let _val = panic!("{:?}", 1); + let _val = panic!("{1}: {:?}", 1, "this always happens"); + + 1; + 1; panic!("{:?}", 1); panic!("{1}: {:?}", 1, "this always happens"); } @@ -23,6 +39,11 @@ fn unwrap_result_ok() { fn unwrap_result_err() { let _val = 1; let _val = 1; + let _val = panic!("{:?}", 1); + let _val = panic!("{1}: {:?}", 1, "this always happens"); + + 1; + 1; panic!("{:?}", 1); panic!("{1}: {:?}", 1, "this always happens"); } @@ -31,12 +52,20 @@ fn unwrap_methods_option() { let _val = 1; let _val = 1; let _val = 1; + + 1; + 1; + 1; } fn unwrap_methods_result() { let _val = 1; let _val = 1; let _val = 1; + + 1; + 1; + 1; } fn main() { diff --git a/tests/ui/unnecessary_literal_unwrap.rs b/tests/ui/unnecessary_literal_unwrap.rs index f15c063fe54..14f92cb370f 100644 --- a/tests/ui/unnecessary_literal_unwrap.rs +++ b/tests/ui/unnecessary_literal_unwrap.rs @@ -1,42 +1,71 @@ //@run-rustfix #![warn(clippy::unnecessary_literal_unwrap)] #![allow(unreachable_code)] -#![allow(clippy::unnecessary_lazy_evaluations)] +#![allow( + clippy::unnecessary_lazy_evaluations, + clippy::diverging_sub_expression, + clippy::let_unit_value, + clippy::no_effect +)] fn unwrap_option_some() { let _val = Some(1).unwrap(); let _val = Some(1).expect("this never happens"); + + Some(1).unwrap(); + Some(1).expect("this never happens"); } fn unwrap_option_none() { - None::.unwrap(); - None::.expect("this always happens"); + let _val = None::<()>.unwrap(); + let _val = None::<()>.expect("this always happens"); + + None::<()>.unwrap(); + None::<()>.expect("this always happens"); } fn unwrap_result_ok() { - let _val = Ok::(1).unwrap(); - let _val = Ok::(1).expect("this never happens"); - Ok::(1).unwrap_err(); - Ok::(1).expect_err("this always happens"); + let _val = Ok::<_, ()>(1).unwrap(); + let _val = Ok::<_, ()>(1).expect("this never happens"); + let _val = Ok::<_, ()>(1).unwrap_err(); + let _val = Ok::<_, ()>(1).expect_err("this always happens"); + + Ok::<_, ()>(1).unwrap(); + Ok::<_, ()>(1).expect("this never happens"); + Ok::<_, ()>(1).unwrap_err(); + Ok::<_, ()>(1).expect_err("this always happens"); } fn unwrap_result_err() { - let _val = Err::<(), usize>(1).unwrap_err(); - let _val = Err::<(), usize>(1).expect_err("this never happens"); - Err::<(), usize>(1).unwrap(); - Err::<(), usize>(1).expect("this always happens"); + let _val = Err::<(), _>(1).unwrap_err(); + let _val = Err::<(), _>(1).expect_err("this never happens"); + let _val = Err::<(), _>(1).unwrap(); + let _val = Err::<(), _>(1).expect("this always happens"); + + Err::<(), _>(1).unwrap_err(); + Err::<(), _>(1).expect_err("this never happens"); + Err::<(), _>(1).unwrap(); + Err::<(), _>(1).expect("this always happens"); } fn unwrap_methods_option() { let _val = Some(1).unwrap_or(2); let _val = Some(1).unwrap_or_default(); let _val = Some(1).unwrap_or_else(|| 2); + + Some(1).unwrap_or(2); + Some(1).unwrap_or_default(); + Some(1).unwrap_or_else(|| 2); } fn unwrap_methods_result() { - let _val = Ok::(1).unwrap_or(2); - let _val = Ok::(1).unwrap_or_default(); - let _val = Ok::(1).unwrap_or_else(|_| 2); + let _val = Ok::<_, ()>(1).unwrap_or(2); + let _val = Ok::<_, ()>(1).unwrap_or_default(); + let _val = Ok::<_, ()>(1).unwrap_or_else(|_| 2); + + Ok::<_, ()>(1).unwrap_or(2); + Ok::<_, ()>(1).unwrap_or_default(); + Ok::<_, ()>(1).unwrap_or_else(|_| 2); } fn main() { diff --git a/tests/ui/unnecessary_literal_unwrap.stderr b/tests/ui/unnecessary_literal_unwrap.stderr index cf057d7fe5a..0c71ee05323 100644 --- a/tests/ui/unnecessary_literal_unwrap.stderr +++ b/tests/ui/unnecessary_literal_unwrap.stderr @@ -1,5 +1,5 @@ error: used `unwrap()` on `Some` value - --> $DIR/unnecessary_literal_unwrap.rs:7:16 + --> $DIR/unnecessary_literal_unwrap.rs:12:16 | LL | let _val = Some(1).unwrap(); | ^^^^^^^^^^^^^^^^ @@ -12,7 +12,7 @@ LL + let _val = 1; | error: used `expect()` on `Some` value - --> $DIR/unnecessary_literal_unwrap.rs:8:16 + --> $DIR/unnecessary_literal_unwrap.rs:13:16 | LL | let _val = Some(1).expect("this never happens"); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -23,17 +23,58 @@ LL - let _val = Some(1).expect("this never happens"); LL + let _val = 1; | -error: used `unwrap()` on `None` value - --> $DIR/unnecessary_literal_unwrap.rs:12:5 +error: used `unwrap()` on `Some` value + --> $DIR/unnecessary_literal_unwrap.rs:15:5 | -LL | None::.unwrap(); - | ^^^^^^^^^^^^^^^^^^^^^^ help: remove the `None` and `unwrap()`: `panic!()` +LL | Some(1).unwrap(); + | ^^^^^^^^^^^^^^^^ + | +help: remove the `Some` and `unwrap()` + | +LL - Some(1).unwrap(); +LL + 1; + | + +error: used `expect()` on `Some` value + --> $DIR/unnecessary_literal_unwrap.rs:16:5 + | +LL | Some(1).expect("this never happens"); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: remove the `Some` and `expect()` + | +LL - Some(1).expect("this never happens"); +LL + 1; + | + +error: used `unwrap()` on `None` value + --> $DIR/unnecessary_literal_unwrap.rs:20:16 + | +LL | let _val = None::<()>.unwrap(); + | ^^^^^^^^^^^^^^^^^^^ help: remove the `None` and `unwrap()`: `panic!()` error: used `expect()` on `None` value - --> $DIR/unnecessary_literal_unwrap.rs:13:5 + --> $DIR/unnecessary_literal_unwrap.rs:21:16 | -LL | None::.expect("this always happens"); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | let _val = None::<()>.expect("this always happens"); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: remove the `None` and `expect()` + | +LL | let _val = panic!("this always happens"); + | ~~~~~~~ ~ + +error: used `unwrap()` on `None` value + --> $DIR/unnecessary_literal_unwrap.rs:23:5 + | +LL | None::<()>.unwrap(); + | ^^^^^^^^^^^^^^^^^^^ help: remove the `None` and `unwrap()`: `panic!()` + +error: used `expect()` on `None` value + --> $DIR/unnecessary_literal_unwrap.rs:24:5 + | +LL | None::<()>.expect("this always happens"); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | help: remove the `None` and `expect()` | @@ -41,34 +82,80 @@ LL | panic!("this always happens"); | ~~~~~~~ ~ error: used `unwrap()` on `Ok` value - --> $DIR/unnecessary_literal_unwrap.rs:17:16 + --> $DIR/unnecessary_literal_unwrap.rs:28:16 | -LL | let _val = Ok::(1).unwrap(); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | let _val = Ok::<_, ()>(1).unwrap(); + | ^^^^^^^^^^^^^^^^^^^^^^^ | help: remove the `Ok` and `unwrap()` | -LL - let _val = Ok::(1).unwrap(); +LL - let _val = Ok::<_, ()>(1).unwrap(); LL + let _val = 1; | error: used `expect()` on `Ok` value - --> $DIR/unnecessary_literal_unwrap.rs:18:16 + --> $DIR/unnecessary_literal_unwrap.rs:29:16 | -LL | let _val = Ok::(1).expect("this never happens"); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | let _val = Ok::<_, ()>(1).expect("this never happens"); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | help: remove the `Ok` and `expect()` | -LL - let _val = Ok::(1).expect("this never happens"); +LL - let _val = Ok::<_, ()>(1).expect("this never happens"); LL + let _val = 1; | error: used `unwrap_err()` on `Ok` value - --> $DIR/unnecessary_literal_unwrap.rs:19:5 + --> $DIR/unnecessary_literal_unwrap.rs:30:16 | -LL | Ok::(1).unwrap_err(); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | let _val = Ok::<_, ()>(1).unwrap_err(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: remove the `Ok` and `unwrap_err()` + | +LL | let _val = panic!("{:?}", 1); + | ~~~~~~~~~~~~~~ ~ + +error: used `expect_err()` on `Ok` value + --> $DIR/unnecessary_literal_unwrap.rs:31:16 + | +LL | let _val = Ok::<_, ()>(1).expect_err("this always happens"); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: remove the `Ok` and `expect_err()` + | +LL | let _val = panic!("{1}: {:?}", 1, "this always happens"); + | ~~~~~~~~~~~~~~~~~~~ ~ + +error: used `unwrap()` on `Ok` value + --> $DIR/unnecessary_literal_unwrap.rs:33:5 + | +LL | Ok::<_, ()>(1).unwrap(); + | ^^^^^^^^^^^^^^^^^^^^^^^ + | +help: remove the `Ok` and `unwrap()` + | +LL - Ok::<_, ()>(1).unwrap(); +LL + 1; + | + +error: used `expect()` on `Ok` value + --> $DIR/unnecessary_literal_unwrap.rs:34:5 + | +LL | Ok::<_, ()>(1).expect("this never happens"); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: remove the `Ok` and `expect()` + | +LL - Ok::<_, ()>(1).expect("this never happens"); +LL + 1; + | + +error: used `unwrap_err()` on `Ok` value + --> $DIR/unnecessary_literal_unwrap.rs:35:5 + | +LL | Ok::<_, ()>(1).unwrap_err(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ | help: remove the `Ok` and `unwrap_err()` | @@ -76,10 +163,10 @@ LL | panic!("{:?}", 1); | ~~~~~~~~~~~~~~ ~ error: used `expect_err()` on `Ok` value - --> $DIR/unnecessary_literal_unwrap.rs:20:5 + --> $DIR/unnecessary_literal_unwrap.rs:36:5 | -LL | Ok::(1).expect_err("this always happens"); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | Ok::<_, ()>(1).expect_err("this always happens"); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | help: remove the `Ok` and `expect_err()` | @@ -87,45 +174,91 @@ LL | panic!("{1}: {:?}", 1, "this always happens"); | ~~~~~~~~~~~~~~~~~~~ ~ error: used `unwrap_err()` on `Err` value - --> $DIR/unnecessary_literal_unwrap.rs:24:16 + --> $DIR/unnecessary_literal_unwrap.rs:40:16 | -LL | let _val = Err::<(), usize>(1).unwrap_err(); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | let _val = Err::<(), _>(1).unwrap_err(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | help: remove the `Err` and `unwrap_err()` | -LL - let _val = Err::<(), usize>(1).unwrap_err(); +LL - let _val = Err::<(), _>(1).unwrap_err(); LL + let _val = 1; | error: used `expect_err()` on `Err` value - --> $DIR/unnecessary_literal_unwrap.rs:25:16 + --> $DIR/unnecessary_literal_unwrap.rs:41:16 | -LL | let _val = Err::<(), usize>(1).expect_err("this never happens"); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | let _val = Err::<(), _>(1).expect_err("this never happens"); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | help: remove the `Err` and `expect_err()` | -LL - let _val = Err::<(), usize>(1).expect_err("this never happens"); +LL - let _val = Err::<(), _>(1).expect_err("this never happens"); LL + let _val = 1; | error: used `unwrap()` on `Err` value - --> $DIR/unnecessary_literal_unwrap.rs:26:5 + --> $DIR/unnecessary_literal_unwrap.rs:42:16 | -LL | Err::<(), usize>(1).unwrap(); +LL | let _val = Err::<(), _>(1).unwrap(); + | ^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: remove the `Err` and `unwrap()` + | +LL | let _val = panic!("{:?}", 1); + | ~~~~~~~~~~~~~~ ~ + +error: used `expect()` on `Err` value + --> $DIR/unnecessary_literal_unwrap.rs:43:16 + | +LL | let _val = Err::<(), _>(1).expect("this always happens"); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: remove the `Err` and `expect()` + | +LL | let _val = panic!("{1}: {:?}", 1, "this always happens"); + | ~~~~~~~~~~~~~~~~~~~ ~ + +error: used `unwrap_err()` on `Err` value + --> $DIR/unnecessary_literal_unwrap.rs:45:5 + | +LL | Err::<(), _>(1).unwrap_err(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | +help: remove the `Err` and `unwrap_err()` + | +LL - Err::<(), _>(1).unwrap_err(); +LL + 1; + | + +error: used `expect_err()` on `Err` value + --> $DIR/unnecessary_literal_unwrap.rs:46:5 + | +LL | Err::<(), _>(1).expect_err("this never happens"); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: remove the `Err` and `expect_err()` + | +LL - Err::<(), _>(1).expect_err("this never happens"); +LL + 1; + | + +error: used `unwrap()` on `Err` value + --> $DIR/unnecessary_literal_unwrap.rs:47:5 + | +LL | Err::<(), _>(1).unwrap(); + | ^^^^^^^^^^^^^^^^^^^^^^^^ + | help: remove the `Err` and `unwrap()` | LL | panic!("{:?}", 1); | ~~~~~~~~~~~~~~ ~ error: used `expect()` on `Err` value - --> $DIR/unnecessary_literal_unwrap.rs:27:5 + --> $DIR/unnecessary_literal_unwrap.rs:48:5 | -LL | Err::<(), usize>(1).expect("this always happens"); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | Err::<(), _>(1).expect("this always happens"); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | help: remove the `Err` and `expect()` | @@ -133,7 +266,7 @@ LL | panic!("{1}: {:?}", 1, "this always happens"); | ~~~~~~~~~~~~~~~~~~~ ~ error: used `unwrap_or()` on `Some` value - --> $DIR/unnecessary_literal_unwrap.rs:31:16 + --> $DIR/unnecessary_literal_unwrap.rs:52:16 | LL | let _val = Some(1).unwrap_or(2); | ^^^^^^^^^^^^^^^^^^^^ @@ -145,7 +278,7 @@ LL + let _val = 1; | error: used `unwrap_or_default()` on `Some` value - --> $DIR/unnecessary_literal_unwrap.rs:32:16 + --> $DIR/unnecessary_literal_unwrap.rs:53:16 | LL | let _val = Some(1).unwrap_or_default(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -157,7 +290,7 @@ LL + let _val = 1; | error: used `unwrap_or_else()` on `Some` value - --> $DIR/unnecessary_literal_unwrap.rs:33:16 + --> $DIR/unnecessary_literal_unwrap.rs:54:16 | LL | let _val = Some(1).unwrap_or_else(|| 2); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -168,41 +301,113 @@ LL - let _val = Some(1).unwrap_or_else(|| 2); LL + let _val = 1; | -error: used `unwrap_or()` on `Ok` value - --> $DIR/unnecessary_literal_unwrap.rs:37:16 +error: used `unwrap_or()` on `Some` value + --> $DIR/unnecessary_literal_unwrap.rs:56:5 | -LL | let _val = Ok::(1).unwrap_or(2); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | Some(1).unwrap_or(2); + | ^^^^^^^^^^^^^^^^^^^^ + | +help: remove the `Some` and `unwrap_or()` + | +LL - Some(1).unwrap_or(2); +LL + 1; + | + +error: used `unwrap_or_default()` on `Some` value + --> $DIR/unnecessary_literal_unwrap.rs:57:5 + | +LL | Some(1).unwrap_or_default(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: remove the `Some` and `unwrap_or_default()` + | +LL - Some(1).unwrap_or_default(); +LL + 1; + | + +error: used `unwrap_or_else()` on `Some` value + --> $DIR/unnecessary_literal_unwrap.rs:58:5 + | +LL | Some(1).unwrap_or_else(|| 2); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: remove the `Some` and `unwrap_or_else()` + | +LL - Some(1).unwrap_or_else(|| 2); +LL + 1; + | + +error: used `unwrap_or()` on `Ok` value + --> $DIR/unnecessary_literal_unwrap.rs:62:16 + | +LL | let _val = Ok::<_, ()>(1).unwrap_or(2); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ | help: remove the `Ok` and `unwrap_or()` | -LL - let _val = Ok::(1).unwrap_or(2); +LL - let _val = Ok::<_, ()>(1).unwrap_or(2); LL + let _val = 1; | error: used `unwrap_or_default()` on `Ok` value - --> $DIR/unnecessary_literal_unwrap.rs:38:16 + --> $DIR/unnecessary_literal_unwrap.rs:63:16 | -LL | let _val = Ok::(1).unwrap_or_default(); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | let _val = Ok::<_, ()>(1).unwrap_or_default(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | help: remove the `Ok` and `unwrap_or_default()` | -LL - let _val = Ok::(1).unwrap_or_default(); +LL - let _val = Ok::<_, ()>(1).unwrap_or_default(); LL + let _val = 1; | error: used `unwrap_or_else()` on `Ok` value - --> $DIR/unnecessary_literal_unwrap.rs:39:16 + --> $DIR/unnecessary_literal_unwrap.rs:64:16 | -LL | let _val = Ok::(1).unwrap_or_else(|_| 2); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | let _val = Ok::<_, ()>(1).unwrap_or_else(|_| 2); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | help: remove the `Ok` and `unwrap_or_else()` | -LL - let _val = Ok::(1).unwrap_or_else(|_| 2); +LL - let _val = Ok::<_, ()>(1).unwrap_or_else(|_| 2); LL + let _val = 1; | -error: aborting due to 18 previous errors +error: used `unwrap_or()` on `Ok` value + --> $DIR/unnecessary_literal_unwrap.rs:66:5 + | +LL | Ok::<_, ()>(1).unwrap_or(2); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: remove the `Ok` and `unwrap_or()` + | +LL - Ok::<_, ()>(1).unwrap_or(2); +LL + 1; + | + +error: used `unwrap_or_default()` on `Ok` value + --> $DIR/unnecessary_literal_unwrap.rs:67:5 + | +LL | Ok::<_, ()>(1).unwrap_or_default(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: remove the `Ok` and `unwrap_or_default()` + | +LL - Ok::<_, ()>(1).unwrap_or_default(); +LL + 1; + | + +error: used `unwrap_or_else()` on `Ok` value + --> $DIR/unnecessary_literal_unwrap.rs:68:5 + | +LL | Ok::<_, ()>(1).unwrap_or_else(|_| 2); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: remove the `Ok` and `unwrap_or_else()` + | +LL - Ok::<_, ()>(1).unwrap_or_else(|_| 2); +LL + 1; + | + +error: aborting due to 36 previous errors diff --git a/tests/ui/unnecessary_literal_unwrap_unfixable.rs b/tests/ui/unnecessary_literal_unwrap_unfixable.rs index 9ccf6b21447..711fdce3962 100644 --- a/tests/ui/unnecessary_literal_unwrap_unfixable.rs +++ b/tests/ui/unnecessary_literal_unwrap_unfixable.rs @@ -1,6 +1,6 @@ #![warn(clippy::unnecessary_literal_unwrap)] -#![allow(clippy::unnecessary_lazy_evaluations)] #![allow(unreachable_code)] +#![allow(clippy::unnecessary_lazy_evaluations, clippy::let_unit_value)] fn unwrap_option_some() { let val = Some(1); @@ -8,26 +8,61 @@ fn unwrap_option_some() { let _val2 = val.expect("this never happens"); } +fn unwrap_option_some_context() { + let _val = Some::([1, 2, 3].iter().sum()).unwrap(); + let _val = Some::([1, 2, 3].iter().sum()).expect("this never happens"); + + let val = Some::([1, 2, 3].iter().sum()); + let _val2 = val.unwrap(); + let _val2 = val.expect("this never happens"); +} + fn unwrap_option_none() { - let val = None::; - val.unwrap(); - val.expect("this always happens"); + let val = None::<()>; + let _val2 = val.unwrap(); + let _val2 = val.expect("this always happens"); } fn unwrap_result_ok() { - let val = Ok::(1); + let val = Ok::<_, ()>(1); let _val2 = val.unwrap(); let _val2 = val.expect("this never happens"); - val.unwrap_err(); - val.expect_err("this always happens"); + let _val2 = val.unwrap_err(); + let _val2 = val.expect_err("this always happens"); +} + +fn unwrap_result_ok_context() { + let _val = Ok::([1, 2, 3].iter().sum()).unwrap(); + let _val = Ok::([1, 2, 3].iter().sum()).expect("this never happens"); + let _val = Ok::([1, 2, 3].iter().sum()).unwrap_err(); + let _val = Ok::([1, 2, 3].iter().sum()).expect_err("this always happens"); + + let val = Ok::([1, 2, 3].iter().sum()); + let _val2 = val.unwrap(); + let _val2 = val.expect("this never happens"); + let _val2 = val.unwrap_err(); + let _val2 = val.expect_err("this always happens"); } fn unwrap_result_err() { - let val = Err::<(), usize>(1); + let val = Err::<(), _>(1); let _val2 = val.unwrap_err(); let _val2 = val.expect_err("this never happens"); - val.unwrap(); - val.expect("this always happens"); + let _val2 = val.unwrap(); + let _val2 = val.expect("this always happens"); +} + +fn unwrap_result_err_context() { + let _val = Err::<(), usize>([1, 2, 3].iter().sum()).unwrap_err(); + let _val = Err::<(), usize>([1, 2, 3].iter().sum()).expect_err("this never happens"); + let _val = Err::<(), usize>([1, 2, 3].iter().sum()).unwrap(); + let _val = Err::<(), usize>([1, 2, 3].iter().sum()).expect("this always happens"); + + let val = Err::<(), usize>([1, 2, 3].iter().sum()); + let _val2 = val.unwrap_err(); + let _val2 = val.expect_err("this never happens"); + let _val2 = val.unwrap(); + let _val2 = val.expect("this always happens"); } fn unwrap_methods_option() { @@ -37,8 +72,30 @@ fn unwrap_methods_option() { let _val2 = val.unwrap_or_else(|| 2); } +fn unwrap_methods_option_context() { + let _val = Some::([1, 2, 3].iter().sum()).unwrap_or(2); + let _val = Some::([1, 2, 3].iter().sum()).unwrap_or_default(); + let _val = Some::([1, 2, 3].iter().sum()).unwrap_or_else(|| 2); + + let val = Some::([1, 2, 3].iter().sum()); + let _val2 = val.unwrap_or(2); + let _val2 = val.unwrap_or_default(); + let _val2 = val.unwrap_or_else(|| 2); +} + fn unwrap_methods_result() { - let val = Ok::(1); + let val = Ok::<_, ()>(1); + let _val2 = val.unwrap_or(2); + let _val2 = val.unwrap_or_default(); + let _val2 = val.unwrap_or_else(|_| 2); +} + +fn unwrap_methods_result_context() { + let _val = Ok::([1, 2, 3].iter().sum()).unwrap_or(2); + let _val = Ok::([1, 2, 3].iter().sum()).unwrap_or_default(); + let _val = Ok::([1, 2, 3].iter().sum()).unwrap_or_else(|_| 2); + + let val = Ok::([1, 2, 3].iter().sum()); let _val2 = val.unwrap_or(2); let _val2 = val.unwrap_or_default(); let _val2 = val.unwrap_or_else(|_| 2); @@ -46,9 +103,14 @@ fn unwrap_methods_result() { fn main() { unwrap_option_some(); + unwrap_option_some_context(); unwrap_option_none(); unwrap_result_ok(); + unwrap_result_ok_context(); unwrap_result_err(); + unwrap_result_err_context(); unwrap_methods_option(); + unwrap_methods_option_context(); unwrap_methods_result(); + unwrap_methods_result_context(); } diff --git a/tests/ui/unnecessary_literal_unwrap_unfixable.stderr b/tests/ui/unnecessary_literal_unwrap_unfixable.stderr index 7931deeca7f..feb9325b77a 100644 --- a/tests/ui/unnecessary_literal_unwrap_unfixable.stderr +++ b/tests/ui/unnecessary_literal_unwrap_unfixable.stderr @@ -23,197 +23,581 @@ help: remove the `Some` and `expect()` LL | let val = Some(1); | ^^^^^^^ -error: used `unwrap()` on `None` value - --> $DIR/unnecessary_literal_unwrap_unfixable.rs:13:5 +error: used `unwrap()` on `Some` value + --> $DIR/unnecessary_literal_unwrap_unfixable.rs:12:16 | -LL | val.unwrap(); - | ^^^^^^^^^^^^ +LL | let _val = Some::([1, 2, 3].iter().sum()).unwrap(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: remove the `Some` and `unwrap()` + --> $DIR/unnecessary_literal_unwrap_unfixable.rs:12:16 + | +LL | let _val = Some::([1, 2, 3].iter().sum()).unwrap(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: used `expect()` on `Some` value + --> $DIR/unnecessary_literal_unwrap_unfixable.rs:13:16 + | +LL | let _val = Some::([1, 2, 3].iter().sum()).expect("this never happens"); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: remove the `Some` and `expect()` + --> $DIR/unnecessary_literal_unwrap_unfixable.rs:13:16 + | +LL | let _val = Some::([1, 2, 3].iter().sum()).expect("this never happens"); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: used `unwrap()` on `Some` value + --> $DIR/unnecessary_literal_unwrap_unfixable.rs:16:17 + | +LL | let _val2 = val.unwrap(); + | ^^^^^^^^^^^^ + | +help: remove the `Some` and `unwrap()` + --> $DIR/unnecessary_literal_unwrap_unfixable.rs:15:15 + | +LL | let val = Some::([1, 2, 3].iter().sum()); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: used `expect()` on `Some` value + --> $DIR/unnecessary_literal_unwrap_unfixable.rs:17:17 + | +LL | let _val2 = val.expect("this never happens"); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: remove the `Some` and `expect()` + --> $DIR/unnecessary_literal_unwrap_unfixable.rs:15:15 + | +LL | let val = Some::([1, 2, 3].iter().sum()); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: used `unwrap()` on `None` value + --> $DIR/unnecessary_literal_unwrap_unfixable.rs:22:17 + | +LL | let _val2 = val.unwrap(); + | ^^^^^^^^^^^^ | help: remove the `None` and `unwrap()` - --> $DIR/unnecessary_literal_unwrap_unfixable.rs:12:15 + --> $DIR/unnecessary_literal_unwrap_unfixable.rs:21:15 | -LL | let val = None::; - | ^^^^^^^^^^^^^ +LL | let val = None::<()>; + | ^^^^^^^^^^ error: used `expect()` on `None` value - --> $DIR/unnecessary_literal_unwrap_unfixable.rs:14:5 + --> $DIR/unnecessary_literal_unwrap_unfixable.rs:23:17 | -LL | val.expect("this always happens"); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | let _val2 = val.expect("this always happens"); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | help: remove the `None` and `expect()` - --> $DIR/unnecessary_literal_unwrap_unfixable.rs:12:15 + --> $DIR/unnecessary_literal_unwrap_unfixable.rs:21:15 | -LL | let val = None::; - | ^^^^^^^^^^^^^ +LL | let val = None::<()>; + | ^^^^^^^^^^ error: used `unwrap()` on `Ok` value - --> $DIR/unnecessary_literal_unwrap_unfixable.rs:19:17 + --> $DIR/unnecessary_literal_unwrap_unfixable.rs:28:17 | LL | let _val2 = val.unwrap(); | ^^^^^^^^^^^^ | help: remove the `Ok` and `unwrap()` - --> $DIR/unnecessary_literal_unwrap_unfixable.rs:18:15 + --> $DIR/unnecessary_literal_unwrap_unfixable.rs:27:15 | -LL | let val = Ok::(1); - | ^^^^^^^^^^^^^^^^^^ +LL | let val = Ok::<_, ()>(1); + | ^^^^^^^^^^^^^^ error: used `expect()` on `Ok` value - --> $DIR/unnecessary_literal_unwrap_unfixable.rs:20:17 + --> $DIR/unnecessary_literal_unwrap_unfixable.rs:29:17 | LL | let _val2 = val.expect("this never happens"); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | help: remove the `Ok` and `expect()` - --> $DIR/unnecessary_literal_unwrap_unfixable.rs:18:15 + --> $DIR/unnecessary_literal_unwrap_unfixable.rs:27:15 | -LL | let val = Ok::(1); - | ^^^^^^^^^^^^^^^^^^ +LL | let val = Ok::<_, ()>(1); + | ^^^^^^^^^^^^^^ error: used `unwrap_err()` on `Ok` value - --> $DIR/unnecessary_literal_unwrap_unfixable.rs:21:5 + --> $DIR/unnecessary_literal_unwrap_unfixable.rs:30:17 | -LL | val.unwrap_err(); - | ^^^^^^^^^^^^^^^^ +LL | let _val2 = val.unwrap_err(); + | ^^^^^^^^^^^^^^^^ | help: remove the `Ok` and `unwrap_err()` - --> $DIR/unnecessary_literal_unwrap_unfixable.rs:18:15 + --> $DIR/unnecessary_literal_unwrap_unfixable.rs:27:15 | -LL | let val = Ok::(1); - | ^^^^^^^^^^^^^^^^^^ +LL | let val = Ok::<_, ()>(1); + | ^^^^^^^^^^^^^^ error: used `expect_err()` on `Ok` value - --> $DIR/unnecessary_literal_unwrap_unfixable.rs:22:5 + --> $DIR/unnecessary_literal_unwrap_unfixable.rs:31:17 | -LL | val.expect_err("this always happens"); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | let _val2 = val.expect_err("this always happens"); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | help: remove the `Ok` and `expect_err()` - --> $DIR/unnecessary_literal_unwrap_unfixable.rs:18:15 + --> $DIR/unnecessary_literal_unwrap_unfixable.rs:27:15 | -LL | let val = Ok::(1); - | ^^^^^^^^^^^^^^^^^^ +LL | let val = Ok::<_, ()>(1); + | ^^^^^^^^^^^^^^ + +error: used `unwrap()` on `Ok` value + --> $DIR/unnecessary_literal_unwrap_unfixable.rs:35:16 + | +LL | let _val = Ok::([1, 2, 3].iter().sum()).unwrap(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: remove the `Ok` and `unwrap()` + --> $DIR/unnecessary_literal_unwrap_unfixable.rs:35:16 + | +LL | let _val = Ok::([1, 2, 3].iter().sum()).unwrap(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: used `expect()` on `Ok` value + --> $DIR/unnecessary_literal_unwrap_unfixable.rs:36:16 + | +LL | let _val = Ok::([1, 2, 3].iter().sum()).expect("this never happens"); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: remove the `Ok` and `expect()` + --> $DIR/unnecessary_literal_unwrap_unfixable.rs:36:16 + | +LL | let _val = Ok::([1, 2, 3].iter().sum()).expect("this never happens"); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: used `unwrap_err()` on `Ok` value + --> $DIR/unnecessary_literal_unwrap_unfixable.rs:37:16 + | +LL | let _val = Ok::([1, 2, 3].iter().sum()).unwrap_err(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: remove the `Ok` and `unwrap_err()` + --> $DIR/unnecessary_literal_unwrap_unfixable.rs:37:16 + | +LL | let _val = Ok::([1, 2, 3].iter().sum()).unwrap_err(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: used `expect_err()` on `Ok` value + --> $DIR/unnecessary_literal_unwrap_unfixable.rs:38:16 + | +LL | let _val = Ok::([1, 2, 3].iter().sum()).expect_err("this always happens"); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: remove the `Ok` and `expect_err()` + --> $DIR/unnecessary_literal_unwrap_unfixable.rs:38:16 + | +LL | let _val = Ok::([1, 2, 3].iter().sum()).expect_err("this always happens"); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: used `unwrap()` on `Ok` value + --> $DIR/unnecessary_literal_unwrap_unfixable.rs:41:17 + | +LL | let _val2 = val.unwrap(); + | ^^^^^^^^^^^^ + | +help: remove the `Ok` and `unwrap()` + --> $DIR/unnecessary_literal_unwrap_unfixable.rs:40:15 + | +LL | let val = Ok::([1, 2, 3].iter().sum()); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: used `expect()` on `Ok` value + --> $DIR/unnecessary_literal_unwrap_unfixable.rs:42:17 + | +LL | let _val2 = val.expect("this never happens"); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: remove the `Ok` and `expect()` + --> $DIR/unnecessary_literal_unwrap_unfixable.rs:40:15 + | +LL | let val = Ok::([1, 2, 3].iter().sum()); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: used `unwrap_err()` on `Ok` value + --> $DIR/unnecessary_literal_unwrap_unfixable.rs:43:17 + | +LL | let _val2 = val.unwrap_err(); + | ^^^^^^^^^^^^^^^^ + | +help: remove the `Ok` and `unwrap_err()` + --> $DIR/unnecessary_literal_unwrap_unfixable.rs:40:15 + | +LL | let val = Ok::([1, 2, 3].iter().sum()); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: used `expect_err()` on `Ok` value + --> $DIR/unnecessary_literal_unwrap_unfixable.rs:44:17 + | +LL | let _val2 = val.expect_err("this always happens"); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: remove the `Ok` and `expect_err()` + --> $DIR/unnecessary_literal_unwrap_unfixable.rs:40:15 + | +LL | let val = Ok::([1, 2, 3].iter().sum()); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: used `unwrap_err()` on `Err` value - --> $DIR/unnecessary_literal_unwrap_unfixable.rs:27:17 + --> $DIR/unnecessary_literal_unwrap_unfixable.rs:49:17 | LL | let _val2 = val.unwrap_err(); | ^^^^^^^^^^^^^^^^ | help: remove the `Err` and `unwrap_err()` - --> $DIR/unnecessary_literal_unwrap_unfixable.rs:26:15 + --> $DIR/unnecessary_literal_unwrap_unfixable.rs:48:15 | -LL | let val = Err::<(), usize>(1); - | ^^^^^^^^^^^^^^^^^^^ +LL | let val = Err::<(), _>(1); + | ^^^^^^^^^^^^^^^ error: used `expect_err()` on `Err` value - --> $DIR/unnecessary_literal_unwrap_unfixable.rs:28:17 + --> $DIR/unnecessary_literal_unwrap_unfixable.rs:50:17 | LL | let _val2 = val.expect_err("this never happens"); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | help: remove the `Err` and `expect_err()` - --> $DIR/unnecessary_literal_unwrap_unfixable.rs:26:15 + --> $DIR/unnecessary_literal_unwrap_unfixable.rs:48:15 | -LL | let val = Err::<(), usize>(1); - | ^^^^^^^^^^^^^^^^^^^ +LL | let val = Err::<(), _>(1); + | ^^^^^^^^^^^^^^^ error: used `unwrap()` on `Err` value - --> $DIR/unnecessary_literal_unwrap_unfixable.rs:29:5 + --> $DIR/unnecessary_literal_unwrap_unfixable.rs:51:17 | -LL | val.unwrap(); - | ^^^^^^^^^^^^ +LL | let _val2 = val.unwrap(); + | ^^^^^^^^^^^^ | help: remove the `Err` and `unwrap()` - --> $DIR/unnecessary_literal_unwrap_unfixable.rs:26:15 + --> $DIR/unnecessary_literal_unwrap_unfixable.rs:48:15 | -LL | let val = Err::<(), usize>(1); - | ^^^^^^^^^^^^^^^^^^^ +LL | let val = Err::<(), _>(1); + | ^^^^^^^^^^^^^^^ error: used `expect()` on `Err` value - --> $DIR/unnecessary_literal_unwrap_unfixable.rs:30:5 + --> $DIR/unnecessary_literal_unwrap_unfixable.rs:52:17 | -LL | val.expect("this always happens"); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | let _val2 = val.expect("this always happens"); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | help: remove the `Err` and `expect()` - --> $DIR/unnecessary_literal_unwrap_unfixable.rs:26:15 + --> $DIR/unnecessary_literal_unwrap_unfixable.rs:48:15 | -LL | let val = Err::<(), usize>(1); - | ^^^^^^^^^^^^^^^^^^^ +LL | let val = Err::<(), _>(1); + | ^^^^^^^^^^^^^^^ + +error: used `unwrap_err()` on `Err` value + --> $DIR/unnecessary_literal_unwrap_unfixable.rs:56:16 + | +LL | let _val = Err::<(), usize>([1, 2, 3].iter().sum()).unwrap_err(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: remove the `Err` and `unwrap_err()` + --> $DIR/unnecessary_literal_unwrap_unfixable.rs:56:16 + | +LL | let _val = Err::<(), usize>([1, 2, 3].iter().sum()).unwrap_err(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: used `expect_err()` on `Err` value + --> $DIR/unnecessary_literal_unwrap_unfixable.rs:57:16 + | +LL | let _val = Err::<(), usize>([1, 2, 3].iter().sum()).expect_err("this never happens"); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: remove the `Err` and `expect_err()` + --> $DIR/unnecessary_literal_unwrap_unfixable.rs:57:16 + | +LL | let _val = Err::<(), usize>([1, 2, 3].iter().sum()).expect_err("this never happens"); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: used `unwrap()` on `Err` value + --> $DIR/unnecessary_literal_unwrap_unfixable.rs:58:16 + | +LL | let _val = Err::<(), usize>([1, 2, 3].iter().sum()).unwrap(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: remove the `Err` and `unwrap()` + --> $DIR/unnecessary_literal_unwrap_unfixable.rs:58:16 + | +LL | let _val = Err::<(), usize>([1, 2, 3].iter().sum()).unwrap(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: used `expect()` on `Err` value + --> $DIR/unnecessary_literal_unwrap_unfixable.rs:59:16 + | +LL | let _val = Err::<(), usize>([1, 2, 3].iter().sum()).expect("this always happens"); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: remove the `Err` and `expect()` + --> $DIR/unnecessary_literal_unwrap_unfixable.rs:59:16 + | +LL | let _val = Err::<(), usize>([1, 2, 3].iter().sum()).expect("this always happens"); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: used `unwrap_err()` on `Err` value + --> $DIR/unnecessary_literal_unwrap_unfixable.rs:62:17 + | +LL | let _val2 = val.unwrap_err(); + | ^^^^^^^^^^^^^^^^ + | +help: remove the `Err` and `unwrap_err()` + --> $DIR/unnecessary_literal_unwrap_unfixable.rs:61:15 + | +LL | let val = Err::<(), usize>([1, 2, 3].iter().sum()); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: used `expect_err()` on `Err` value + --> $DIR/unnecessary_literal_unwrap_unfixable.rs:63:17 + | +LL | let _val2 = val.expect_err("this never happens"); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: remove the `Err` and `expect_err()` + --> $DIR/unnecessary_literal_unwrap_unfixable.rs:61:15 + | +LL | let val = Err::<(), usize>([1, 2, 3].iter().sum()); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: used `unwrap()` on `Err` value + --> $DIR/unnecessary_literal_unwrap_unfixable.rs:64:17 + | +LL | let _val2 = val.unwrap(); + | ^^^^^^^^^^^^ + | +help: remove the `Err` and `unwrap()` + --> $DIR/unnecessary_literal_unwrap_unfixable.rs:61:15 + | +LL | let val = Err::<(), usize>([1, 2, 3].iter().sum()); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: used `expect()` on `Err` value + --> $DIR/unnecessary_literal_unwrap_unfixable.rs:65:17 + | +LL | let _val2 = val.expect("this always happens"); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: remove the `Err` and `expect()` + --> $DIR/unnecessary_literal_unwrap_unfixable.rs:61:15 + | +LL | let val = Err::<(), usize>([1, 2, 3].iter().sum()); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: used `unwrap_or()` on `Some` value - --> $DIR/unnecessary_literal_unwrap_unfixable.rs:35:17 + --> $DIR/unnecessary_literal_unwrap_unfixable.rs:70:17 | LL | let _val2 = val.unwrap_or(2); | ^^^^^^^^^^^^^^^^ | help: remove the `Some` and `unwrap_or()` - --> $DIR/unnecessary_literal_unwrap_unfixable.rs:34:15 + --> $DIR/unnecessary_literal_unwrap_unfixable.rs:69:15 | LL | let val = Some(1); | ^^^^^^^ error: used `unwrap_or_default()` on `Some` value - --> $DIR/unnecessary_literal_unwrap_unfixable.rs:36:17 + --> $DIR/unnecessary_literal_unwrap_unfixable.rs:71:17 | LL | let _val2 = val.unwrap_or_default(); | ^^^^^^^^^^^^^^^^^^^^^^^ | help: remove the `Some` and `unwrap_or_default()` - --> $DIR/unnecessary_literal_unwrap_unfixable.rs:34:15 + --> $DIR/unnecessary_literal_unwrap_unfixable.rs:69:15 | LL | let val = Some(1); | ^^^^^^^ error: used `unwrap_or_else()` on `Some` value - --> $DIR/unnecessary_literal_unwrap_unfixable.rs:37:17 + --> $DIR/unnecessary_literal_unwrap_unfixable.rs:72:17 | LL | let _val2 = val.unwrap_or_else(|| 2); | ^^^^^^^^^^^^^^^^^^^^^^^^ | help: remove the `Some` and `unwrap_or_else()` - --> $DIR/unnecessary_literal_unwrap_unfixable.rs:34:15 + --> $DIR/unnecessary_literal_unwrap_unfixable.rs:69:15 | LL | let val = Some(1); | ^^^^^^^ +error: used `unwrap_or()` on `Some` value + --> $DIR/unnecessary_literal_unwrap_unfixable.rs:76:16 + | +LL | let _val = Some::([1, 2, 3].iter().sum()).unwrap_or(2); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: remove the `Some` and `unwrap_or()` + --> $DIR/unnecessary_literal_unwrap_unfixable.rs:76:16 + | +LL | let _val = Some::([1, 2, 3].iter().sum()).unwrap_or(2); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: used `unwrap_or_default()` on `Some` value + --> $DIR/unnecessary_literal_unwrap_unfixable.rs:77:16 + | +LL | let _val = Some::([1, 2, 3].iter().sum()).unwrap_or_default(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: remove the `Some` and `unwrap_or_default()` + --> $DIR/unnecessary_literal_unwrap_unfixable.rs:77:16 + | +LL | let _val = Some::([1, 2, 3].iter().sum()).unwrap_or_default(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: used `unwrap_or_else()` on `Some` value + --> $DIR/unnecessary_literal_unwrap_unfixable.rs:78:16 + | +LL | let _val = Some::([1, 2, 3].iter().sum()).unwrap_or_else(|| 2); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: remove the `Some` and `unwrap_or_else()` + --> $DIR/unnecessary_literal_unwrap_unfixable.rs:78:16 + | +LL | let _val = Some::([1, 2, 3].iter().sum()).unwrap_or_else(|| 2); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: used `unwrap_or()` on `Some` value + --> $DIR/unnecessary_literal_unwrap_unfixable.rs:81:17 + | +LL | let _val2 = val.unwrap_or(2); + | ^^^^^^^^^^^^^^^^ + | +help: remove the `Some` and `unwrap_or()` + --> $DIR/unnecessary_literal_unwrap_unfixable.rs:80:15 + | +LL | let val = Some::([1, 2, 3].iter().sum()); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: used `unwrap_or_default()` on `Some` value + --> $DIR/unnecessary_literal_unwrap_unfixable.rs:82:17 + | +LL | let _val2 = val.unwrap_or_default(); + | ^^^^^^^^^^^^^^^^^^^^^^^ + | +help: remove the `Some` and `unwrap_or_default()` + --> $DIR/unnecessary_literal_unwrap_unfixable.rs:80:15 + | +LL | let val = Some::([1, 2, 3].iter().sum()); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: used `unwrap_or_else()` on `Some` value + --> $DIR/unnecessary_literal_unwrap_unfixable.rs:83:17 + | +LL | let _val2 = val.unwrap_or_else(|| 2); + | ^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: remove the `Some` and `unwrap_or_else()` + --> $DIR/unnecessary_literal_unwrap_unfixable.rs:80:15 + | +LL | let val = Some::([1, 2, 3].iter().sum()); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + error: used `unwrap_or()` on `Ok` value - --> $DIR/unnecessary_literal_unwrap_unfixable.rs:42:17 + --> $DIR/unnecessary_literal_unwrap_unfixable.rs:88:17 | LL | let _val2 = val.unwrap_or(2); | ^^^^^^^^^^^^^^^^ | help: remove the `Ok` and `unwrap_or()` - --> $DIR/unnecessary_literal_unwrap_unfixable.rs:41:15 + --> $DIR/unnecessary_literal_unwrap_unfixable.rs:87:15 | -LL | let val = Ok::(1); - | ^^^^^^^^^^^^^^^^^^ +LL | let val = Ok::<_, ()>(1); + | ^^^^^^^^^^^^^^ error: used `unwrap_or_default()` on `Ok` value - --> $DIR/unnecessary_literal_unwrap_unfixable.rs:43:17 + --> $DIR/unnecessary_literal_unwrap_unfixable.rs:89:17 | LL | let _val2 = val.unwrap_or_default(); | ^^^^^^^^^^^^^^^^^^^^^^^ | help: remove the `Ok` and `unwrap_or_default()` - --> $DIR/unnecessary_literal_unwrap_unfixable.rs:41:15 + --> $DIR/unnecessary_literal_unwrap_unfixable.rs:87:15 | -LL | let val = Ok::(1); - | ^^^^^^^^^^^^^^^^^^ +LL | let val = Ok::<_, ()>(1); + | ^^^^^^^^^^^^^^ error: used `unwrap_or_else()` on `Ok` value - --> $DIR/unnecessary_literal_unwrap_unfixable.rs:44:17 + --> $DIR/unnecessary_literal_unwrap_unfixable.rs:90:17 | LL | let _val2 = val.unwrap_or_else(|_| 2); | ^^^^^^^^^^^^^^^^^^^^^^^^^ | help: remove the `Ok` and `unwrap_or_else()` - --> $DIR/unnecessary_literal_unwrap_unfixable.rs:41:15 + --> $DIR/unnecessary_literal_unwrap_unfixable.rs:87:15 | -LL | let val = Ok::(1); - | ^^^^^^^^^^^^^^^^^^ +LL | let val = Ok::<_, ()>(1); + | ^^^^^^^^^^^^^^ -error: aborting due to 18 previous errors +error: used `unwrap_or()` on `Ok` value + --> $DIR/unnecessary_literal_unwrap_unfixable.rs:94:16 + | +LL | let _val = Ok::([1, 2, 3].iter().sum()).unwrap_or(2); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: remove the `Ok` and `unwrap_or()` + --> $DIR/unnecessary_literal_unwrap_unfixable.rs:94:16 + | +LL | let _val = Ok::([1, 2, 3].iter().sum()).unwrap_or(2); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: used `unwrap_or_default()` on `Ok` value + --> $DIR/unnecessary_literal_unwrap_unfixable.rs:95:16 + | +LL | let _val = Ok::([1, 2, 3].iter().sum()).unwrap_or_default(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: remove the `Ok` and `unwrap_or_default()` + --> $DIR/unnecessary_literal_unwrap_unfixable.rs:95:16 + | +LL | let _val = Ok::([1, 2, 3].iter().sum()).unwrap_or_default(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: used `unwrap_or_else()` on `Ok` value + --> $DIR/unnecessary_literal_unwrap_unfixable.rs:96:16 + | +LL | let _val = Ok::([1, 2, 3].iter().sum()).unwrap_or_else(|_| 2); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: remove the `Ok` and `unwrap_or_else()` + --> $DIR/unnecessary_literal_unwrap_unfixable.rs:96:16 + | +LL | let _val = Ok::([1, 2, 3].iter().sum()).unwrap_or_else(|_| 2); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: used `unwrap_or()` on `Ok` value + --> $DIR/unnecessary_literal_unwrap_unfixable.rs:99:17 + | +LL | let _val2 = val.unwrap_or(2); + | ^^^^^^^^^^^^^^^^ + | +help: remove the `Ok` and `unwrap_or()` + --> $DIR/unnecessary_literal_unwrap_unfixable.rs:98:15 + | +LL | let val = Ok::([1, 2, 3].iter().sum()); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: used `unwrap_or_default()` on `Ok` value + --> $DIR/unnecessary_literal_unwrap_unfixable.rs:100:17 + | +LL | let _val2 = val.unwrap_or_default(); + | ^^^^^^^^^^^^^^^^^^^^^^^ + | +help: remove the `Ok` and `unwrap_or_default()` + --> $DIR/unnecessary_literal_unwrap_unfixable.rs:98:15 + | +LL | let val = Ok::([1, 2, 3].iter().sum()); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: used `unwrap_or_else()` on `Ok` value + --> $DIR/unnecessary_literal_unwrap_unfixable.rs:101:17 + | +LL | let _val2 = val.unwrap_or_else(|_| 2); + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: remove the `Ok` and `unwrap_or_else()` + --> $DIR/unnecessary_literal_unwrap_unfixable.rs:98:15 + | +LL | let val = Ok::([1, 2, 3].iter().sum()); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 50 previous errors From bfd5abad4b1b93133796a07a52ece3f7aa053062 Mon Sep 17 00:00:00 2001 From: Pavan Kumar Sunkara Date: Wed, 31 May 2023 18:47:10 +0100 Subject: [PATCH 172/310] Fix all the other tests --- .../uninlined_format_args.fixed | 1 + .../uninlined_format_args.rs | 1 + .../uninlined_format_args.stderr | 12 +- .../arithmetic_side_effects_allowed.rs | 1 + .../arithmetic_side_effects_allowed.stderr | 18 +-- tests/ui-toml/expect_used/expect_used.rs | 1 + tests/ui-toml/expect_used/expect_used.stderr | 4 +- tests/ui/assertions_on_result_states.fixed | 1 + tests/ui/assertions_on_result_states.rs | 1 + tests/ui/assertions_on_result_states.stderr | 14 +- tests/ui/blocks_in_if_conditions_closure.rs | 7 +- .../ui/blocks_in_if_conditions_closure.stderr | 4 +- .../ui/checked_unwrap/complex_conditionals.rs | 6 +- .../complex_conditionals.stderr | 40 ++--- .../complex_conditionals_nested.rs | 6 +- .../complex_conditionals_nested.stderr | 4 +- .../ui/checked_unwrap/simple_conditionals.rs | 6 +- .../checked_unwrap/simple_conditionals.stderr | 34 ++--- tests/ui/crashes/ice-5579.rs | 2 + tests/ui/err_expect.fixed | 2 +- tests/ui/err_expect.rs | 2 +- tests/ui/expect.rs | 1 + tests/ui/expect.stderr | 6 +- tests/ui/expect_fun_call.fixed | 6 +- tests/ui/expect_fun_call.rs | 6 +- tests/ui/expect_fun_call.stderr | 30 ++-- tests/ui/explicit_deref_methods.fixed | 3 +- tests/ui/explicit_deref_methods.rs | 3 +- tests/ui/explicit_deref_methods.stderr | 24 +-- tests/ui/manual_unwrap_or.fixed | 2 +- tests/ui/manual_unwrap_or.rs | 2 +- tests/ui/missing_panics_doc.rs | 2 +- tests/ui/needless_borrow.fixed | 3 +- tests/ui/needless_borrow.rs | 3 +- tests/ui/needless_borrow.stderr | 72 ++++----- tests/ui/needless_range_loop.rs | 6 +- tests/ui/needless_range_loop.stderr | 28 ++-- tests/ui/ok_expect.rs | 2 + tests/ui/ok_expect.stderr | 10 +- tests/ui/or_fun_call.fixed | 1 + tests/ui/or_fun_call.rs | 1 + tests/ui/or_fun_call.stderr | 56 +++---- tests/ui/or_then_unwrap.fixed | 2 +- tests/ui/or_then_unwrap.rs | 2 +- tests/ui/redundant_clone.fixed | 7 +- tests/ui/redundant_clone.rs | 7 +- tests/ui/redundant_clone.stderr | 60 ++++---- tests/ui/uninlined_format_args.fixed | 7 +- tests/ui/uninlined_format_args.rs | 7 +- tests/ui/uninlined_format_args.stderr | 142 +++++++++--------- tests/ui/unnecessary_lazy_eval.fixed | 1 + tests/ui/unnecessary_lazy_eval.rs | 1 + tests/ui/unnecessary_lazy_eval.stderr | 76 +++++----- tests/ui/unnecessary_lazy_eval_unfixable.rs | 1 + .../ui/unnecessary_lazy_eval_unfixable.stderr | 6 +- tests/ui/unwrap.rs | 1 + tests/ui/unwrap.stderr | 6 +- tests/ui/unwrap_expect_used.rs | 1 + tests/ui/unwrap_expect_used.stderr | 12 +- tests/ui/unwrap_or.rs | 1 + tests/ui/unwrap_or.stderr | 4 +- tests/ui/unwrap_or_else_default.fixed | 2 +- tests/ui/unwrap_or_else_default.rs | 2 +- 63 files changed, 427 insertions(+), 355 deletions(-) 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 23e7bc16d23..c9085684528 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,5 +1,6 @@ //@run-rustfix #![warn(clippy::uninlined_format_args)] +#![allow(clippy::unnecessary_literal_unwrap)] fn main() { let local_i32 = 1; 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 d66b2b8ff6a..661350c5c6d 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,5 +1,6 @@ //@run-rustfix #![warn(clippy::uninlined_format_args)] +#![allow(clippy::unnecessary_literal_unwrap)] fn main() { let local_i32 = 1; 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 1be0cda12fc..6ec79a618de 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 @@ -1,5 +1,5 @@ error: variables can be used directly in the `format!` string - --> $DIR/uninlined_format_args.rs:9:5 + --> $DIR/uninlined_format_args.rs:10:5 | LL | println!("val='{}'", local_i32); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -12,7 +12,7 @@ LL + println!("val='{local_i32}'"); | error: variables can be used directly in the `format!` string - --> $DIR/uninlined_format_args.rs:10:5 + --> $DIR/uninlined_format_args.rs:11:5 | LL | println!("Hello {} is {:.*}", "x", local_i32, local_f64); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -24,7 +24,7 @@ LL + println!("Hello {} is {local_f64:.local_i32$}", "x"); | error: literal with an empty format string - --> $DIR/uninlined_format_args.rs:10:35 + --> $DIR/uninlined_format_args.rs:11:35 | LL | println!("Hello {} is {:.*}", "x", local_i32, local_f64); | ^^^ @@ -37,7 +37,7 @@ LL + println!("Hello x is {:.*}", local_i32, local_f64); | error: variables can be used directly in the `format!` string - --> $DIR/uninlined_format_args.rs:11:5 + --> $DIR/uninlined_format_args.rs:12:5 | LL | println!("Hello {} is {:.*}", local_i32, 5, local_f64); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -49,7 +49,7 @@ LL + println!("Hello {local_i32} is {local_f64:.*}", 5); | error: variables can be used directly in the `format!` string - --> $DIR/uninlined_format_args.rs:12:5 + --> $DIR/uninlined_format_args.rs:13:5 | LL | println!("Hello {} is {2:.*}", local_i32, 5, local_f64); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -61,7 +61,7 @@ LL + println!("Hello {local_i32} is {local_f64:.*}", 5); | error: variables can be used directly in the `format!` string - --> $DIR/uninlined_format_args.rs:13:5 + --> $DIR/uninlined_format_args.rs:14:5 | LL | println!("{}, {}", local_i32, local_opt.unwrap()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui-toml/arithmetic_side_effects_allowed/arithmetic_side_effects_allowed.rs b/tests/ui-toml/arithmetic_side_effects_allowed/arithmetic_side_effects_allowed.rs index fb5b1b193f8..33f7c8ba804 100644 --- a/tests/ui-toml/arithmetic_side_effects_allowed/arithmetic_side_effects_allowed.rs +++ b/tests/ui-toml/arithmetic_side_effects_allowed/arithmetic_side_effects_allowed.rs @@ -1,4 +1,5 @@ #![warn(clippy::arithmetic_side_effects)] +#![allow(clippy::unnecessary_literal_unwrap)] use core::ops::{Add, Neg}; diff --git a/tests/ui-toml/arithmetic_side_effects_allowed/arithmetic_side_effects_allowed.stderr b/tests/ui-toml/arithmetic_side_effects_allowed/arithmetic_side_effects_allowed.stderr index ad89534aa1b..4f98ca19231 100644 --- a/tests/ui-toml/arithmetic_side_effects_allowed/arithmetic_side_effects_allowed.stderr +++ b/tests/ui-toml/arithmetic_side_effects_allowed/arithmetic_side_effects_allowed.stderr @@ -1,5 +1,5 @@ error: arithmetic operation that can potentially result in unexpected side-effects - --> $DIR/arithmetic_side_effects_allowed.rs:68:13 + --> $DIR/arithmetic_side_effects_allowed.rs:69:13 | LL | let _ = Baz + Baz; | ^^^^^^^^^ @@ -7,49 +7,49 @@ LL | let _ = Baz + Baz; = note: `-D clippy::arithmetic-side-effects` implied by `-D warnings` error: arithmetic operation that can potentially result in unexpected side-effects - --> $DIR/arithmetic_side_effects_allowed.rs:79:13 + --> $DIR/arithmetic_side_effects_allowed.rs:80:13 | LL | let _ = 1i32 + Baz; | ^^^^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> $DIR/arithmetic_side_effects_allowed.rs:82:13 + --> $DIR/arithmetic_side_effects_allowed.rs:83:13 | LL | let _ = 1i64 + Foo; | ^^^^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> $DIR/arithmetic_side_effects_allowed.rs:86:13 + --> $DIR/arithmetic_side_effects_allowed.rs:87:13 | LL | let _ = 1i64 + Baz; | ^^^^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> $DIR/arithmetic_side_effects_allowed.rs:97:13 + --> $DIR/arithmetic_side_effects_allowed.rs:98:13 | LL | let _ = Baz + 1i32; | ^^^^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> $DIR/arithmetic_side_effects_allowed.rs:100:13 + --> $DIR/arithmetic_side_effects_allowed.rs:101:13 | LL | let _ = Foo + 1i64; | ^^^^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> $DIR/arithmetic_side_effects_allowed.rs:104:13 + --> $DIR/arithmetic_side_effects_allowed.rs:105:13 | LL | let _ = Baz + 1i64; | ^^^^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> $DIR/arithmetic_side_effects_allowed.rs:113:13 + --> $DIR/arithmetic_side_effects_allowed.rs:114:13 | LL | let _ = -Bar; | ^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> $DIR/arithmetic_side_effects_allowed.rs:115:13 + --> $DIR/arithmetic_side_effects_allowed.rs:116:13 | LL | let _ = -Baz; | ^^^^ diff --git a/tests/ui-toml/expect_used/expect_used.rs b/tests/ui-toml/expect_used/expect_used.rs index 9e267c89300..206788e19f0 100644 --- a/tests/ui-toml/expect_used/expect_used.rs +++ b/tests/ui-toml/expect_used/expect_used.rs @@ -1,5 +1,6 @@ //@compile-flags: --test #![warn(clippy::expect_used)] +#![allow(clippy::unnecessary_literal_unwrap)] fn expect_option() { let opt = Some(0); diff --git a/tests/ui-toml/expect_used/expect_used.stderr b/tests/ui-toml/expect_used/expect_used.stderr index 1e9bb48c333..9eef0e1bfaa 100644 --- a/tests/ui-toml/expect_used/expect_used.stderr +++ b/tests/ui-toml/expect_used/expect_used.stderr @@ -1,5 +1,5 @@ error: used `expect()` on an `Option` value - --> $DIR/expect_used.rs:6:13 + --> $DIR/expect_used.rs:7:13 | LL | let _ = opt.expect(""); | ^^^^^^^^^^^^^^ @@ -8,7 +8,7 @@ LL | let _ = opt.expect(""); = note: `-D clippy::expect-used` implied by `-D warnings` error: used `expect()` on a `Result` value - --> $DIR/expect_used.rs:11:13 + --> $DIR/expect_used.rs:12:13 | LL | let _ = res.expect(""); | ^^^^^^^^^^^^^^ diff --git a/tests/ui/assertions_on_result_states.fixed b/tests/ui/assertions_on_result_states.fixed index ea8b895664c..3152bd3cae1 100644 --- a/tests/ui/assertions_on_result_states.fixed +++ b/tests/ui/assertions_on_result_states.fixed @@ -1,5 +1,6 @@ //@run-rustfix #![warn(clippy::assertions_on_result_states)] +#![allow(clippy::unnecessary_literal_unwrap)] use std::result::Result; diff --git a/tests/ui/assertions_on_result_states.rs b/tests/ui/assertions_on_result_states.rs index 6fc20f85988..42755e935aa 100644 --- a/tests/ui/assertions_on_result_states.rs +++ b/tests/ui/assertions_on_result_states.rs @@ -1,5 +1,6 @@ //@run-rustfix #![warn(clippy::assertions_on_result_states)] +#![allow(clippy::unnecessary_literal_unwrap)] use std::result::Result; diff --git a/tests/ui/assertions_on_result_states.stderr b/tests/ui/assertions_on_result_states.stderr index 298d63c9c34..be581030cb6 100644 --- a/tests/ui/assertions_on_result_states.stderr +++ b/tests/ui/assertions_on_result_states.stderr @@ -1,5 +1,5 @@ error: called `assert!` with `Result::is_ok` - --> $DIR/assertions_on_result_states.rs:24:5 + --> $DIR/assertions_on_result_states.rs:25:5 | LL | assert!(r.is_ok()); | ^^^^^^^^^^^^^^^^^^ help: replace with: `r.unwrap()` @@ -7,37 +7,37 @@ LL | assert!(r.is_ok()); = note: `-D clippy::assertions-on-result-states` implied by `-D warnings` error: called `assert!` with `Result::is_ok` - --> $DIR/assertions_on_result_states.rs:42:5 + --> $DIR/assertions_on_result_states.rs:43:5 | LL | assert!(get_ok().is_ok()); | ^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace with: `get_ok().unwrap()` error: called `assert!` with `Result::is_ok` - --> $DIR/assertions_on_result_states.rs:45:5 + --> $DIR/assertions_on_result_states.rs:46:5 | LL | assert!(get_ok_macro!().is_ok()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace with: `get_ok_macro!().unwrap()` error: called `assert!` with `Result::is_ok` - --> $DIR/assertions_on_result_states.rs:58:5 + --> $DIR/assertions_on_result_states.rs:59:5 | LL | assert!(r.is_ok()); | ^^^^^^^^^^^^^^^^^^ help: replace with: `r.unwrap()` error: called `assert!` with `Result::is_ok` - --> $DIR/assertions_on_result_states.rs:64:9 + --> $DIR/assertions_on_result_states.rs:65:9 | LL | assert!(r.is_ok()); | ^^^^^^^^^^^^^^^^^^ help: replace with: `r.unwrap()` error: called `assert!` with `Result::is_err` - --> $DIR/assertions_on_result_states.rs:72:5 + --> $DIR/assertions_on_result_states.rs:73:5 | LL | assert!(r.is_err()); | ^^^^^^^^^^^^^^^^^^^ help: replace with: `r.unwrap_err()` error: called `assert!` with `Result::is_err` - --> $DIR/assertions_on_result_states.rs:82:5 + --> $DIR/assertions_on_result_states.rs:83:5 | LL | assert!(res.is_err()) | ^^^^^^^^^^^^^^^^^^^^^ help: replace with: `res.unwrap_err();` diff --git a/tests/ui/blocks_in_if_conditions_closure.rs b/tests/ui/blocks_in_if_conditions_closure.rs index 7da12d89a61..d6d085d7fd1 100644 --- a/tests/ui/blocks_in_if_conditions_closure.rs +++ b/tests/ui/blocks_in_if_conditions_closure.rs @@ -1,5 +1,10 @@ #![warn(clippy::blocks_in_if_conditions)] -#![allow(unused, clippy::let_and_return, clippy::needless_if)] +#![allow( + unused, + clippy::let_and_return, + clippy::needless_if, + clippy::unnecessary_literal_unwrap +)] fn predicate bool, T>(pfn: F, val: T) -> bool { pfn(val) diff --git a/tests/ui/blocks_in_if_conditions_closure.stderr b/tests/ui/blocks_in_if_conditions_closure.stderr index 941d604dd5f..5ac02e7504e 100644 --- a/tests/ui/blocks_in_if_conditions_closure.stderr +++ b/tests/ui/blocks_in_if_conditions_closure.stderr @@ -1,5 +1,5 @@ error: in an `if` condition, avoid complex blocks or closures with blocks; instead, move the block or closure higher and bind it with a `let` - --> $DIR/blocks_in_if_conditions_closure.rs:18:17 + --> $DIR/blocks_in_if_conditions_closure.rs:23:17 | LL | |x| { | _________________^ @@ -11,7 +11,7 @@ LL | | }, = note: `-D clippy::blocks-in-if-conditions` implied by `-D warnings` error: in an `if` condition, avoid complex blocks or closures with blocks; instead, move the block or closure higher and bind it with a `let` - --> $DIR/blocks_in_if_conditions_closure.rs:27:13 + --> $DIR/blocks_in_if_conditions_closure.rs:32:13 | LL | |x| { | _____________^ diff --git a/tests/ui/checked_unwrap/complex_conditionals.rs b/tests/ui/checked_unwrap/complex_conditionals.rs index ec082c73b44..16e54a7d969 100644 --- a/tests/ui/checked_unwrap/complex_conditionals.rs +++ b/tests/ui/checked_unwrap/complex_conditionals.rs @@ -1,5 +1,9 @@ #![deny(clippy::panicking_unwrap, clippy::unnecessary_unwrap)] -#![allow(clippy::if_same_then_else, clippy::branches_sharing_code)] +#![allow( + clippy::if_same_then_else, + clippy::branches_sharing_code, + clippy::unnecessary_literal_unwrap +)] fn test_complex_conditions() { let x: Result<(), ()> = Ok(()); diff --git a/tests/ui/checked_unwrap/complex_conditionals.stderr b/tests/ui/checked_unwrap/complex_conditionals.stderr index d44d5072e48..c395c5ba06f 100644 --- a/tests/ui/checked_unwrap/complex_conditionals.stderr +++ b/tests/ui/checked_unwrap/complex_conditionals.stderr @@ -1,5 +1,5 @@ error: called `unwrap` on `x` after checking its variant with `is_ok` - --> $DIR/complex_conditionals.rs:8:9 + --> $DIR/complex_conditionals.rs:12:9 | LL | if x.is_ok() && y.is_err() { | --------- the check is happening here @@ -14,7 +14,7 @@ LL | #![deny(clippy::panicking_unwrap, clippy::unnecessary_unwrap)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^ error: this call to `unwrap_err()` will always panic - --> $DIR/complex_conditionals.rs:9:9 + --> $DIR/complex_conditionals.rs:13:9 | LL | if x.is_ok() && y.is_err() { | --------- because of this check @@ -29,7 +29,7 @@ LL | #![deny(clippy::panicking_unwrap, clippy::unnecessary_unwrap)] | ^^^^^^^^^^^^^^^^^^^^^^^^ error: this call to `unwrap()` will always panic - --> $DIR/complex_conditionals.rs:10:9 + --> $DIR/complex_conditionals.rs:14:9 | LL | if x.is_ok() && y.is_err() { | ---------- because of this check @@ -38,7 +38,7 @@ LL | y.unwrap(); // will panic | ^^^^^^^^^^ error: called `unwrap_err` on `y` after checking its variant with `is_err` - --> $DIR/complex_conditionals.rs:11:9 + --> $DIR/complex_conditionals.rs:15:9 | LL | if x.is_ok() && y.is_err() { | ---------- the check is happening here @@ -49,7 +49,7 @@ LL | y.unwrap_err(); // unnecessary = help: try using `if let` or `match` error: this call to `unwrap()` will always panic - --> $DIR/complex_conditionals.rs:25:9 + --> $DIR/complex_conditionals.rs:29:9 | LL | if x.is_ok() || y.is_ok() { | --------- because of this check @@ -58,7 +58,7 @@ LL | x.unwrap(); // will panic | ^^^^^^^^^^ error: called `unwrap_err` on `x` after checking its variant with `is_ok` - --> $DIR/complex_conditionals.rs:26:9 + --> $DIR/complex_conditionals.rs:30:9 | LL | if x.is_ok() || y.is_ok() { | --------- the check is happening here @@ -69,7 +69,7 @@ LL | x.unwrap_err(); // unnecessary = help: try using `if let` or `match` error: this call to `unwrap()` will always panic - --> $DIR/complex_conditionals.rs:27:9 + --> $DIR/complex_conditionals.rs:31:9 | LL | if x.is_ok() || y.is_ok() { | --------- because of this check @@ -78,7 +78,7 @@ LL | y.unwrap(); // will panic | ^^^^^^^^^^ error: called `unwrap_err` on `y` after checking its variant with `is_ok` - --> $DIR/complex_conditionals.rs:28:9 + --> $DIR/complex_conditionals.rs:32:9 | LL | if x.is_ok() || y.is_ok() { | --------- the check is happening here @@ -89,7 +89,7 @@ LL | y.unwrap_err(); // unnecessary = help: try using `if let` or `match` error: called `unwrap` on `x` after checking its variant with `is_ok` - --> $DIR/complex_conditionals.rs:32:9 + --> $DIR/complex_conditionals.rs:36:9 | LL | if x.is_ok() && !(y.is_ok() || z.is_err()) { | --------- the check is happening here @@ -99,7 +99,7 @@ LL | x.unwrap(); // unnecessary = help: try using `if let` or `match` error: this call to `unwrap_err()` will always panic - --> $DIR/complex_conditionals.rs:33:9 + --> $DIR/complex_conditionals.rs:37:9 | LL | if x.is_ok() && !(y.is_ok() || z.is_err()) { | --------- because of this check @@ -108,7 +108,7 @@ LL | x.unwrap_err(); // will panic | ^^^^^^^^^^^^^^ error: this call to `unwrap()` will always panic - --> $DIR/complex_conditionals.rs:34:9 + --> $DIR/complex_conditionals.rs:38:9 | LL | if x.is_ok() && !(y.is_ok() || z.is_err()) { | --------- because of this check @@ -117,7 +117,7 @@ LL | y.unwrap(); // will panic | ^^^^^^^^^^ error: called `unwrap_err` on `y` after checking its variant with `is_ok` - --> $DIR/complex_conditionals.rs:35:9 + --> $DIR/complex_conditionals.rs:39:9 | LL | if x.is_ok() && !(y.is_ok() || z.is_err()) { | --------- the check is happening here @@ -128,7 +128,7 @@ LL | y.unwrap_err(); // unnecessary = help: try using `if let` or `match` error: called `unwrap` on `z` after checking its variant with `is_err` - --> $DIR/complex_conditionals.rs:36:9 + --> $DIR/complex_conditionals.rs:40:9 | LL | if x.is_ok() && !(y.is_ok() || z.is_err()) { | ---------- the check is happening here @@ -139,7 +139,7 @@ LL | z.unwrap(); // unnecessary = help: try using `if let` or `match` error: this call to `unwrap_err()` will always panic - --> $DIR/complex_conditionals.rs:37:9 + --> $DIR/complex_conditionals.rs:41:9 | LL | if x.is_ok() && !(y.is_ok() || z.is_err()) { | ---------- because of this check @@ -148,7 +148,7 @@ LL | z.unwrap_err(); // will panic | ^^^^^^^^^^^^^^ error: this call to `unwrap()` will always panic - --> $DIR/complex_conditionals.rs:45:9 + --> $DIR/complex_conditionals.rs:49:9 | LL | if x.is_ok() || !(y.is_ok() && z.is_err()) { | --------- because of this check @@ -157,7 +157,7 @@ LL | x.unwrap(); // will panic | ^^^^^^^^^^ error: called `unwrap_err` on `x` after checking its variant with `is_ok` - --> $DIR/complex_conditionals.rs:46:9 + --> $DIR/complex_conditionals.rs:50:9 | LL | if x.is_ok() || !(y.is_ok() && z.is_err()) { | --------- the check is happening here @@ -168,7 +168,7 @@ LL | x.unwrap_err(); // unnecessary = help: try using `if let` or `match` error: called `unwrap` on `y` after checking its variant with `is_ok` - --> $DIR/complex_conditionals.rs:47:9 + --> $DIR/complex_conditionals.rs:51:9 | LL | if x.is_ok() || !(y.is_ok() && z.is_err()) { | --------- the check is happening here @@ -179,7 +179,7 @@ LL | y.unwrap(); // unnecessary = help: try using `if let` or `match` error: this call to `unwrap_err()` will always panic - --> $DIR/complex_conditionals.rs:48:9 + --> $DIR/complex_conditionals.rs:52:9 | LL | if x.is_ok() || !(y.is_ok() && z.is_err()) { | --------- because of this check @@ -188,7 +188,7 @@ LL | y.unwrap_err(); // will panic | ^^^^^^^^^^^^^^ error: this call to `unwrap()` will always panic - --> $DIR/complex_conditionals.rs:49:9 + --> $DIR/complex_conditionals.rs:53:9 | LL | if x.is_ok() || !(y.is_ok() && z.is_err()) { | ---------- because of this check @@ -197,7 +197,7 @@ LL | z.unwrap(); // will panic | ^^^^^^^^^^ error: called `unwrap_err` on `z` after checking its variant with `is_err` - --> $DIR/complex_conditionals.rs:50:9 + --> $DIR/complex_conditionals.rs:54:9 | LL | if x.is_ok() || !(y.is_ok() && z.is_err()) { | ---------- the check is happening here diff --git a/tests/ui/checked_unwrap/complex_conditionals_nested.rs b/tests/ui/checked_unwrap/complex_conditionals_nested.rs index 043ea4148dc..e417cf833cb 100644 --- a/tests/ui/checked_unwrap/complex_conditionals_nested.rs +++ b/tests/ui/checked_unwrap/complex_conditionals_nested.rs @@ -1,5 +1,9 @@ #![deny(clippy::panicking_unwrap, clippy::unnecessary_unwrap)] -#![allow(clippy::if_same_then_else, clippy::branches_sharing_code)] +#![allow( + clippy::if_same_then_else, + clippy::branches_sharing_code, + clippy::unnecessary_literal_unwrap +)] fn test_nested() { fn nested() { diff --git a/tests/ui/checked_unwrap/complex_conditionals_nested.stderr b/tests/ui/checked_unwrap/complex_conditionals_nested.stderr index 542ab53300c..049a69d93bf 100644 --- a/tests/ui/checked_unwrap/complex_conditionals_nested.stderr +++ b/tests/ui/checked_unwrap/complex_conditionals_nested.stderr @@ -1,5 +1,5 @@ error: called `unwrap` on `x` after checking its variant with `is_some` - --> $DIR/complex_conditionals_nested.rs:8:13 + --> $DIR/complex_conditionals_nested.rs:12:13 | LL | if x.is_some() { | -------------- help: try: `if let Some(..) = x` @@ -13,7 +13,7 @@ LL | #![deny(clippy::panicking_unwrap, clippy::unnecessary_unwrap)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^ error: this call to `unwrap()` will always panic - --> $DIR/complex_conditionals_nested.rs:10:13 + --> $DIR/complex_conditionals_nested.rs:14:13 | LL | if x.is_some() { | ----------- because of this check diff --git a/tests/ui/checked_unwrap/simple_conditionals.rs b/tests/ui/checked_unwrap/simple_conditionals.rs index 82dce81979f..61042bb90d2 100644 --- a/tests/ui/checked_unwrap/simple_conditionals.rs +++ b/tests/ui/checked_unwrap/simple_conditionals.rs @@ -1,6 +1,10 @@ #![feature(lint_reasons)] #![deny(clippy::panicking_unwrap, clippy::unnecessary_unwrap)] -#![allow(clippy::if_same_then_else, clippy::branches_sharing_code)] +#![allow( + clippy::if_same_then_else, + clippy::branches_sharing_code, + clippy::unnecessary_literal_unwrap +)] macro_rules! m { ($a:expr) => { diff --git a/tests/ui/checked_unwrap/simple_conditionals.stderr b/tests/ui/checked_unwrap/simple_conditionals.stderr index ef688274222..93809f6551a 100644 --- a/tests/ui/checked_unwrap/simple_conditionals.stderr +++ b/tests/ui/checked_unwrap/simple_conditionals.stderr @@ -1,5 +1,5 @@ error: called `unwrap` on `x` after checking its variant with `is_some` - --> $DIR/simple_conditionals.rs:40:9 + --> $DIR/simple_conditionals.rs:44:9 | LL | if x.is_some() { | -------------- help: try: `if let Some(..) = x` @@ -13,7 +13,7 @@ LL | #![deny(clippy::panicking_unwrap, clippy::unnecessary_unwrap)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^ error: called `expect` on `x` after checking its variant with `is_some` - --> $DIR/simple_conditionals.rs:41:9 + --> $DIR/simple_conditionals.rs:45:9 | LL | if x.is_some() { | -------------- help: try: `if let Some(..) = x` @@ -22,7 +22,7 @@ LL | x.expect("an error message"); // unnecessary | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: this call to `unwrap()` will always panic - --> $DIR/simple_conditionals.rs:43:9 + --> $DIR/simple_conditionals.rs:47:9 | LL | if x.is_some() { | ----------- because of this check @@ -37,7 +37,7 @@ LL | #![deny(clippy::panicking_unwrap, clippy::unnecessary_unwrap)] | ^^^^^^^^^^^^^^^^^^^^^^^^ error: this call to `expect()` will always panic - --> $DIR/simple_conditionals.rs:44:9 + --> $DIR/simple_conditionals.rs:48:9 | LL | if x.is_some() { | ----------- because of this check @@ -46,7 +46,7 @@ LL | x.expect("an error message"); // will panic | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: this call to `unwrap()` will always panic - --> $DIR/simple_conditionals.rs:47:9 + --> $DIR/simple_conditionals.rs:51:9 | LL | if x.is_none() { | ----------- because of this check @@ -54,7 +54,7 @@ LL | x.unwrap(); // will panic | ^^^^^^^^^^ error: called `unwrap` on `x` after checking its variant with `is_none` - --> $DIR/simple_conditionals.rs:49:9 + --> $DIR/simple_conditionals.rs:53:9 | LL | if x.is_none() { | -------------- help: try: `if let Some(..) = x` @@ -63,7 +63,7 @@ LL | x.unwrap(); // unnecessary | ^^^^^^^^^^ error: called `unwrap` on `x` after checking its variant with `is_some` - --> $DIR/simple_conditionals.rs:8:13 + --> $DIR/simple_conditionals.rs:12:13 | LL | if $a.is_some() { | --------------- help: try: `if let Some(..) = x` @@ -76,7 +76,7 @@ LL | m!(x); = note: this error originates in the macro `m` (in Nightly builds, run with -Z macro-backtrace for more info) error: called `unwrap` on `x` after checking its variant with `is_ok` - --> $DIR/simple_conditionals.rs:57:9 + --> $DIR/simple_conditionals.rs:61:9 | LL | if x.is_ok() { | ------------ help: try: `if let Ok(..) = x` @@ -84,7 +84,7 @@ LL | x.unwrap(); // unnecessary | ^^^^^^^^^^ error: called `expect` on `x` after checking its variant with `is_ok` - --> $DIR/simple_conditionals.rs:58:9 + --> $DIR/simple_conditionals.rs:62:9 | LL | if x.is_ok() { | ------------ help: try: `if let Ok(..) = x` @@ -93,7 +93,7 @@ LL | x.expect("an error message"); // unnecessary | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: this call to `unwrap_err()` will always panic - --> $DIR/simple_conditionals.rs:59:9 + --> $DIR/simple_conditionals.rs:63:9 | LL | if x.is_ok() { | --------- because of this check @@ -102,7 +102,7 @@ LL | x.unwrap_err(); // will panic | ^^^^^^^^^^^^^^ error: this call to `unwrap()` will always panic - --> $DIR/simple_conditionals.rs:61:9 + --> $DIR/simple_conditionals.rs:65:9 | LL | if x.is_ok() { | --------- because of this check @@ -111,7 +111,7 @@ LL | x.unwrap(); // will panic | ^^^^^^^^^^ error: this call to `expect()` will always panic - --> $DIR/simple_conditionals.rs:62:9 + --> $DIR/simple_conditionals.rs:66:9 | LL | if x.is_ok() { | --------- because of this check @@ -120,7 +120,7 @@ LL | x.expect("an error message"); // will panic | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: called `unwrap_err` on `x` after checking its variant with `is_ok` - --> $DIR/simple_conditionals.rs:63:9 + --> $DIR/simple_conditionals.rs:67:9 | LL | if x.is_ok() { | ------------ help: try: `if let Err(..) = x` @@ -129,7 +129,7 @@ LL | x.unwrap_err(); // unnecessary | ^^^^^^^^^^^^^^ error: this call to `unwrap()` will always panic - --> $DIR/simple_conditionals.rs:66:9 + --> $DIR/simple_conditionals.rs:70:9 | LL | if x.is_err() { | ---------- because of this check @@ -137,7 +137,7 @@ LL | x.unwrap(); // will panic | ^^^^^^^^^^ error: called `unwrap_err` on `x` after checking its variant with `is_err` - --> $DIR/simple_conditionals.rs:67:9 + --> $DIR/simple_conditionals.rs:71:9 | LL | if x.is_err() { | ------------- help: try: `if let Err(..) = x` @@ -146,7 +146,7 @@ LL | x.unwrap_err(); // unnecessary | ^^^^^^^^^^^^^^ error: called `unwrap` on `x` after checking its variant with `is_err` - --> $DIR/simple_conditionals.rs:69:9 + --> $DIR/simple_conditionals.rs:73:9 | LL | if x.is_err() { | ------------- help: try: `if let Ok(..) = x` @@ -155,7 +155,7 @@ LL | x.unwrap(); // unnecessary | ^^^^^^^^^^ error: this call to `unwrap_err()` will always panic - --> $DIR/simple_conditionals.rs:70:9 + --> $DIR/simple_conditionals.rs:74:9 | LL | if x.is_err() { | ---------- because of this check diff --git a/tests/ui/crashes/ice-5579.rs b/tests/ui/crashes/ice-5579.rs index e1842c73f0e..8ab36bbf93c 100644 --- a/tests/ui/crashes/ice-5579.rs +++ b/tests/ui/crashes/ice-5579.rs @@ -1,3 +1,5 @@ +#![allow(clippy::unnecessary_literal_unwrap)] + trait IsErr { fn is_err(&self, err: &str) -> bool; } diff --git a/tests/ui/err_expect.fixed b/tests/ui/err_expect.fixed index 6ade6f54689..46e2816da52 100644 --- a/tests/ui/err_expect.fixed +++ b/tests/ui/err_expect.fixed @@ -1,6 +1,6 @@ //@run-rustfix -#![allow(unused)] +#![allow(unused, clippy::unnecessary_literal_unwrap)] struct MyTypeNonDebug; diff --git a/tests/ui/err_expect.rs b/tests/ui/err_expect.rs index a93fb59493f..b9446034d50 100644 --- a/tests/ui/err_expect.rs +++ b/tests/ui/err_expect.rs @@ -1,6 +1,6 @@ //@run-rustfix -#![allow(unused)] +#![allow(unused, clippy::unnecessary_literal_unwrap)] struct MyTypeNonDebug; diff --git a/tests/ui/expect.rs b/tests/ui/expect.rs index d742595e14d..1588579bb0f 100644 --- a/tests/ui/expect.rs +++ b/tests/ui/expect.rs @@ -1,4 +1,5 @@ #![warn(clippy::expect_used)] +#![allow(clippy::unnecessary_literal_unwrap)] fn expect_option() { let opt = Some(0); diff --git a/tests/ui/expect.stderr b/tests/ui/expect.stderr index c08e0dbbf74..be340340d47 100644 --- a/tests/ui/expect.stderr +++ b/tests/ui/expect.stderr @@ -1,5 +1,5 @@ error: used `expect()` on an `Option` value - --> $DIR/expect.rs:5:13 + --> $DIR/expect.rs:6:13 | LL | let _ = opt.expect(""); | ^^^^^^^^^^^^^^ @@ -8,7 +8,7 @@ LL | let _ = opt.expect(""); = note: `-D clippy::expect-used` implied by `-D warnings` error: used `expect()` on a `Result` value - --> $DIR/expect.rs:10:13 + --> $DIR/expect.rs:11:13 | LL | let _ = res.expect(""); | ^^^^^^^^^^^^^^ @@ -16,7 +16,7 @@ LL | let _ = res.expect(""); = help: if this value is an `Err`, it will panic error: used `expect_err()` on a `Result` value - --> $DIR/expect.rs:11:13 + --> $DIR/expect.rs:12:13 | LL | let _ = res.expect_err(""); | ^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/expect_fun_call.fixed b/tests/ui/expect_fun_call.fixed index 8e97054fb6b..73c6c97de84 100644 --- a/tests/ui/expect_fun_call.fixed +++ b/tests/ui/expect_fun_call.fixed @@ -1,6 +1,10 @@ //@run-rustfix #![warn(clippy::expect_fun_call)] -#![allow(clippy::to_string_in_format_args, clippy::uninlined_format_args)] +#![allow( + clippy::to_string_in_format_args, + clippy::uninlined_format_args, + clippy::unnecessary_literal_unwrap +)] /// Checks implementation of the `EXPECT_FUN_CALL` lint diff --git a/tests/ui/expect_fun_call.rs b/tests/ui/expect_fun_call.rs index 31e6bcc7ff6..a786138631c 100644 --- a/tests/ui/expect_fun_call.rs +++ b/tests/ui/expect_fun_call.rs @@ -1,6 +1,10 @@ //@run-rustfix #![warn(clippy::expect_fun_call)] -#![allow(clippy::to_string_in_format_args, clippy::uninlined_format_args)] +#![allow( + clippy::to_string_in_format_args, + clippy::uninlined_format_args, + clippy::unnecessary_literal_unwrap +)] /// Checks implementation of the `EXPECT_FUN_CALL` lint diff --git a/tests/ui/expect_fun_call.stderr b/tests/ui/expect_fun_call.stderr index cb55e32aee0..36fb0e5de15 100644 --- a/tests/ui/expect_fun_call.stderr +++ b/tests/ui/expect_fun_call.stderr @@ -1,5 +1,5 @@ error: use of `expect` followed by a function call - --> $DIR/expect_fun_call.rs:34:26 + --> $DIR/expect_fun_call.rs:38:26 | LL | with_none_and_format.expect(&format!("Error {}: fake error", error_code)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_else(|| panic!("Error {}: fake error", error_code))` @@ -7,85 +7,85 @@ LL | with_none_and_format.expect(&format!("Error {}: fake error", error_code = note: `-D clippy::expect-fun-call` implied by `-D warnings` error: use of `expect` followed by a function call - --> $DIR/expect_fun_call.rs:37:26 + --> $DIR/expect_fun_call.rs:41:26 | LL | with_none_and_as_str.expect(format!("Error {}: fake error", error_code).as_str()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_else(|| panic!("Error {}: fake error", error_code))` error: use of `expect` followed by a function call - --> $DIR/expect_fun_call.rs:40:37 + --> $DIR/expect_fun_call.rs:44:37 | LL | with_none_and_format_with_macro.expect(format!("Error {}: fake error", one!()).as_str()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_else(|| panic!("Error {}: fake error", one!()))` error: use of `expect` followed by a function call - --> $DIR/expect_fun_call.rs:50:25 + --> $DIR/expect_fun_call.rs:54:25 | LL | with_err_and_format.expect(&format!("Error {}: fake error", error_code)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_else(|_| panic!("Error {}: fake error", error_code))` error: use of `expect` followed by a function call - --> $DIR/expect_fun_call.rs:53:25 + --> $DIR/expect_fun_call.rs:57:25 | LL | with_err_and_as_str.expect(format!("Error {}: fake error", error_code).as_str()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_else(|_| panic!("Error {}: fake error", error_code))` error: use of `expect` followed by a function call - --> $DIR/expect_fun_call.rs:65:17 + --> $DIR/expect_fun_call.rs:69:17 | LL | Some("foo").expect(format!("{} {}", 1, 2).as_ref()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_else(|| panic!("{} {}", 1, 2))` error: use of `expect` followed by a function call - --> $DIR/expect_fun_call.rs:86:21 + --> $DIR/expect_fun_call.rs:90:21 | LL | Some("foo").expect(&get_string()); | ^^^^^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_else(|| { panic!("{}", get_string()) })` error: use of `expect` followed by a function call - --> $DIR/expect_fun_call.rs:87:21 + --> $DIR/expect_fun_call.rs:91:21 | LL | Some("foo").expect(get_string().as_ref()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_else(|| { panic!("{}", get_string()) })` error: use of `expect` followed by a function call - --> $DIR/expect_fun_call.rs:88:21 + --> $DIR/expect_fun_call.rs:92:21 | LL | Some("foo").expect(get_string().as_str()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_else(|| { panic!("{}", get_string()) })` error: use of `expect` followed by a function call - --> $DIR/expect_fun_call.rs:90:21 + --> $DIR/expect_fun_call.rs:94:21 | LL | Some("foo").expect(get_static_str()); | ^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_else(|| { panic!("{}", get_static_str()) })` error: use of `expect` followed by a function call - --> $DIR/expect_fun_call.rs:91:21 + --> $DIR/expect_fun_call.rs:95:21 | LL | Some("foo").expect(get_non_static_str(&0)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_else(|| { panic!("{}", get_non_static_str(&0).to_string()) })` error: use of `expect` followed by a function call - --> $DIR/expect_fun_call.rs:95:16 + --> $DIR/expect_fun_call.rs:99:16 | LL | Some(true).expect(&format!("key {}, {}", 1, 2)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_else(|| panic!("key {}, {}", 1, 2))` error: use of `expect` followed by a function call - --> $DIR/expect_fun_call.rs:101:17 + --> $DIR/expect_fun_call.rs:105:17 | LL | opt_ref.expect(&format!("{:?}", opt_ref)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_else(|| panic!("{:?}", opt_ref))` error: use of `expect` followed by a function call - --> $DIR/expect_fun_call.rs:105:20 + --> $DIR/expect_fun_call.rs:109:20 | LL | format_capture.expect(&format!("{error_code}")); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_else(|| panic!("{error_code}"))` error: use of `expect` followed by a function call - --> $DIR/expect_fun_call.rs:108:30 + --> $DIR/expect_fun_call.rs:112:30 | LL | format_capture_and_value.expect(&format!("{error_code}, {}", 1)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_else(|| panic!("{error_code}, {}", 1))` diff --git a/tests/ui/explicit_deref_methods.fixed b/tests/ui/explicit_deref_methods.fixed index 1710b170fb8..4d72b58cdf8 100644 --- a/tests/ui/explicit_deref_methods.fixed +++ b/tests/ui/explicit_deref_methods.fixed @@ -7,7 +7,8 @@ clippy::explicit_auto_deref, clippy::needless_borrow, clippy::no_effect, - clippy::uninlined_format_args + clippy::uninlined_format_args, + clippy::unnecessary_literal_unwrap )] use std::ops::{Deref, DerefMut}; diff --git a/tests/ui/explicit_deref_methods.rs b/tests/ui/explicit_deref_methods.rs index 85147e1cb69..fcd945de338 100644 --- a/tests/ui/explicit_deref_methods.rs +++ b/tests/ui/explicit_deref_methods.rs @@ -7,7 +7,8 @@ clippy::explicit_auto_deref, clippy::needless_borrow, clippy::no_effect, - clippy::uninlined_format_args + clippy::uninlined_format_args, + clippy::unnecessary_literal_unwrap )] use std::ops::{Deref, DerefMut}; diff --git a/tests/ui/explicit_deref_methods.stderr b/tests/ui/explicit_deref_methods.stderr index 592563ffa8c..d025035b789 100644 --- a/tests/ui/explicit_deref_methods.stderr +++ b/tests/ui/explicit_deref_methods.stderr @@ -1,5 +1,5 @@ error: explicit `deref` method call - --> $DIR/explicit_deref_methods.rs:53:19 + --> $DIR/explicit_deref_methods.rs:54:19 | LL | let b: &str = a.deref(); | ^^^^^^^^^ help: try this: `&*a` @@ -7,67 +7,67 @@ LL | let b: &str = a.deref(); = note: `-D clippy::explicit-deref-methods` implied by `-D warnings` error: explicit `deref_mut` method call - --> $DIR/explicit_deref_methods.rs:55:23 + --> $DIR/explicit_deref_methods.rs:56:23 | LL | let b: &mut str = a.deref_mut(); | ^^^^^^^^^^^^^ help: try this: `&mut **a` error: explicit `deref` method call - --> $DIR/explicit_deref_methods.rs:58:39 + --> $DIR/explicit_deref_methods.rs:59:39 | LL | let b: String = format!("{}, {}", a.deref(), a.deref()); | ^^^^^^^^^ help: try this: `&*a` error: explicit `deref` method call - --> $DIR/explicit_deref_methods.rs:58:50 + --> $DIR/explicit_deref_methods.rs:59:50 | LL | let b: String = format!("{}, {}", a.deref(), a.deref()); | ^^^^^^^^^ help: try this: `&*a` error: explicit `deref` method call - --> $DIR/explicit_deref_methods.rs:60:20 + --> $DIR/explicit_deref_methods.rs:61:20 | LL | println!("{}", a.deref()); | ^^^^^^^^^ help: try this: `&*a` error: explicit `deref` method call - --> $DIR/explicit_deref_methods.rs:63:11 + --> $DIR/explicit_deref_methods.rs:64:11 | LL | match a.deref() { | ^^^^^^^^^ help: try this: `&*a` error: explicit `deref` method call - --> $DIR/explicit_deref_methods.rs:67:28 + --> $DIR/explicit_deref_methods.rs:68:28 | LL | let b: String = concat(a.deref()); | ^^^^^^^^^ help: try this: `&*a` error: explicit `deref` method call - --> $DIR/explicit_deref_methods.rs:69:13 + --> $DIR/explicit_deref_methods.rs:70:13 | LL | let b = just_return(a).deref(); | ^^^^^^^^^^^^^^^^^^^^^^ help: try this: `just_return(a)` error: explicit `deref` method call - --> $DIR/explicit_deref_methods.rs:71:28 + --> $DIR/explicit_deref_methods.rs:72:28 | LL | let b: String = concat(just_return(a).deref()); | ^^^^^^^^^^^^^^^^^^^^^^ help: try this: `just_return(a)` error: explicit `deref` method call - --> $DIR/explicit_deref_methods.rs:73:19 + --> $DIR/explicit_deref_methods.rs:74:19 | LL | let b: &str = a.deref().deref(); | ^^^^^^^^^^^^^^^^^ help: try this: `&**a` error: explicit `deref` method call - --> $DIR/explicit_deref_methods.rs:76:13 + --> $DIR/explicit_deref_methods.rs:77:13 | LL | let b = opt_a.unwrap().deref(); | ^^^^^^^^^^^^^^^^^^^^^^ help: try this: `&*opt_a.unwrap()` error: explicit `deref` method call - --> $DIR/explicit_deref_methods.rs:113:31 + --> $DIR/explicit_deref_methods.rs:114:31 | LL | let b: &str = expr_deref!(a.deref()); | ^^^^^^^^^ help: try this: `&*a` diff --git a/tests/ui/manual_unwrap_or.fixed b/tests/ui/manual_unwrap_or.fixed index c17634bffe3..20560b87c1a 100644 --- a/tests/ui/manual_unwrap_or.fixed +++ b/tests/ui/manual_unwrap_or.fixed @@ -1,6 +1,6 @@ //@run-rustfix #![allow(dead_code)] -#![allow(unused_variables, clippy::unnecessary_wraps)] +#![allow(unused_variables, clippy::unnecessary_wraps, clippy::unnecessary_literal_unwrap)] fn option_unwrap_or() { // int case diff --git a/tests/ui/manual_unwrap_or.rs b/tests/ui/manual_unwrap_or.rs index 6d49a6949fa..5dbc57565bf 100644 --- a/tests/ui/manual_unwrap_or.rs +++ b/tests/ui/manual_unwrap_or.rs @@ -1,6 +1,6 @@ //@run-rustfix #![allow(dead_code)] -#![allow(unused_variables, clippy::unnecessary_wraps)] +#![allow(unused_variables, clippy::unnecessary_wraps, clippy::unnecessary_literal_unwrap)] fn option_unwrap_or() { // int case diff --git a/tests/ui/missing_panics_doc.rs b/tests/ui/missing_panics_doc.rs index 7dc44529206..10aa436d6cd 100644 --- a/tests/ui/missing_panics_doc.rs +++ b/tests/ui/missing_panics_doc.rs @@ -1,5 +1,5 @@ #![warn(clippy::missing_panics_doc)] -#![allow(clippy::option_map_unit_fn)] +#![allow(clippy::option_map_unit_fn, clippy::unnecessary_literal_unwrap)] fn main() {} /// This needs to be documented diff --git a/tests/ui/needless_borrow.fixed b/tests/ui/needless_borrow.fixed index 425e6eb6200..80cdb4e472d 100644 --- a/tests/ui/needless_borrow.fixed +++ b/tests/ui/needless_borrow.fixed @@ -4,7 +4,8 @@ unused, clippy::uninlined_format_args, clippy::unnecessary_mut_passed, - clippy::unnecessary_to_owned + clippy::unnecessary_to_owned, + clippy::unnecessary_literal_unwrap )] #![warn(clippy::needless_borrow)] diff --git a/tests/ui/needless_borrow.rs b/tests/ui/needless_borrow.rs index 3f7fa4a9d7d..99f735127eb 100644 --- a/tests/ui/needless_borrow.rs +++ b/tests/ui/needless_borrow.rs @@ -4,7 +4,8 @@ unused, clippy::uninlined_format_args, clippy::unnecessary_mut_passed, - clippy::unnecessary_to_owned + clippy::unnecessary_to_owned, + clippy::unnecessary_literal_unwrap )] #![warn(clippy::needless_borrow)] diff --git a/tests/ui/needless_borrow.stderr b/tests/ui/needless_borrow.stderr index d26c317124b..f85b4fb46a6 100644 --- a/tests/ui/needless_borrow.stderr +++ b/tests/ui/needless_borrow.stderr @@ -1,5 +1,5 @@ error: this expression creates a reference which is immediately dereferenced by the compiler - --> $DIR/needless_borrow.rs:15:15 + --> $DIR/needless_borrow.rs:16:15 | LL | let _ = x(&&a); // warn | ^^^ help: change this to: `&a` @@ -7,211 +7,211 @@ LL | let _ = x(&&a); // warn = note: `-D clippy::needless-borrow` implied by `-D warnings` error: this expression creates a reference which is immediately dereferenced by the compiler - --> $DIR/needless_borrow.rs:19:13 + --> $DIR/needless_borrow.rs:20:13 | LL | mut_ref(&mut &mut b); // warn | ^^^^^^^^^^^ help: change this to: `&mut b` error: this expression creates a reference which is immediately dereferenced by the compiler - --> $DIR/needless_borrow.rs:31:13 + --> $DIR/needless_borrow.rs:32:13 | LL | &&a | ^^^ help: change this to: `&a` error: this expression creates a reference which is immediately dereferenced by the compiler - --> $DIR/needless_borrow.rs:33:15 + --> $DIR/needless_borrow.rs:34:15 | LL | 46 => &&a, | ^^^ help: change this to: `&a` error: this expression creates a reference which is immediately dereferenced by the compiler - --> $DIR/needless_borrow.rs:39:27 + --> $DIR/needless_borrow.rs:40:27 | LL | break &ref_a; | ^^^^^^ help: change this to: `ref_a` error: this expression creates a reference which is immediately dereferenced by the compiler - --> $DIR/needless_borrow.rs:46:15 + --> $DIR/needless_borrow.rs:47:15 | LL | let _ = x(&&&a); | ^^^^ help: change this to: `&a` error: this expression creates a reference which is immediately dereferenced by the compiler - --> $DIR/needless_borrow.rs:47:15 + --> $DIR/needless_borrow.rs:48:15 | LL | let _ = x(&mut &&a); | ^^^^^^^^ help: change this to: `&a` error: this expression creates a reference which is immediately dereferenced by the compiler - --> $DIR/needless_borrow.rs:48:15 + --> $DIR/needless_borrow.rs:49:15 | LL | let _ = x(&&&mut b); | ^^^^^^^^ help: change this to: `&mut b` error: this expression creates a reference which is immediately dereferenced by the compiler - --> $DIR/needless_borrow.rs:49:15 + --> $DIR/needless_borrow.rs:50:15 | LL | let _ = x(&&ref_a); | ^^^^^^^ help: change this to: `ref_a` error: this expression creates a reference which is immediately dereferenced by the compiler - --> $DIR/needless_borrow.rs:52:11 + --> $DIR/needless_borrow.rs:53:11 | LL | x(&b); | ^^ help: change this to: `b` error: this expression creates a reference which is immediately dereferenced by the compiler - --> $DIR/needless_borrow.rs:59:13 + --> $DIR/needless_borrow.rs:60:13 | LL | mut_ref(&mut x); | ^^^^^^ help: change this to: `x` error: this expression creates a reference which is immediately dereferenced by the compiler - --> $DIR/needless_borrow.rs:60:13 + --> $DIR/needless_borrow.rs:61:13 | LL | mut_ref(&mut &mut x); | ^^^^^^^^^^^ help: change this to: `x` error: this expression creates a reference which is immediately dereferenced by the compiler - --> $DIR/needless_borrow.rs:61:23 + --> $DIR/needless_borrow.rs:62:23 | LL | let y: &mut i32 = &mut x; | ^^^^^^ help: change this to: `x` error: this expression creates a reference which is immediately dereferenced by the compiler - --> $DIR/needless_borrow.rs:62:23 + --> $DIR/needless_borrow.rs:63:23 | LL | let y: &mut i32 = &mut &mut x; | ^^^^^^^^^^^ help: change this to: `x` error: this expression creates a reference which is immediately dereferenced by the compiler - --> $DIR/needless_borrow.rs:71:14 + --> $DIR/needless_borrow.rs:72:14 | LL | 0 => &mut x, | ^^^^^^ help: change this to: `x` error: this expression creates a reference which is immediately dereferenced by the compiler - --> $DIR/needless_borrow.rs:77:14 + --> $DIR/needless_borrow.rs:78:14 | LL | 0 => &mut x, | ^^^^^^ help: change this to: `x` error: this expression borrows a value the compiler would automatically borrow - --> $DIR/needless_borrow.rs:89:13 + --> $DIR/needless_borrow.rs:90:13 | LL | let _ = (&x).0; | ^^^^ help: change this to: `x` error: this expression borrows a value the compiler would automatically borrow - --> $DIR/needless_borrow.rs:91:22 + --> $DIR/needless_borrow.rs:92:22 | LL | let _ = unsafe { (&*x).0 }; | ^^^^^ help: change this to: `(*x)` error: this expression creates a reference which is immediately dereferenced by the compiler - --> $DIR/needless_borrow.rs:101:5 + --> $DIR/needless_borrow.rs:102:5 | LL | (&&()).foo(); | ^^^^^^ help: change this to: `(&())` error: this expression creates a reference which is immediately dereferenced by the compiler - --> $DIR/needless_borrow.rs:110:5 + --> $DIR/needless_borrow.rs:111:5 | LL | (&&5).foo(); | ^^^^^ help: change this to: `(&5)` error: the borrowed expression implements the required traits - --> $DIR/needless_borrow.rs:135:51 + --> $DIR/needless_borrow.rs:136:51 | LL | let _ = std::process::Command::new("ls").args(&["-a", "-l"]).status().unwrap(); | ^^^^^^^^^^^^^ help: change this to: `["-a", "-l"]` error: the borrowed expression implements the required traits - --> $DIR/needless_borrow.rs:136:44 + --> $DIR/needless_borrow.rs:137:44 | LL | let _ = std::path::Path::new(".").join(&&"."); | ^^^^^ help: change this to: `"."` error: the borrowed expression implements the required traits - --> $DIR/needless_borrow.rs:137:23 + --> $DIR/needless_borrow.rs:138:23 | LL | deref_target_is_x(&X); | ^^ help: change this to: `X` error: the borrowed expression implements the required traits - --> $DIR/needless_borrow.rs:138:26 + --> $DIR/needless_borrow.rs:139:26 | LL | multiple_constraints(&[[""]]); | ^^^^^^^ help: change this to: `[[""]]` error: the borrowed expression implements the required traits - --> $DIR/needless_borrow.rs:139:45 + --> $DIR/needless_borrow.rs:140:45 | LL | multiple_constraints_normalizes_to_same(&X, X); | ^^ help: change this to: `X` error: this expression creates a reference which is immediately dereferenced by the compiler - --> $DIR/needless_borrow.rs:140:32 + --> $DIR/needless_borrow.rs:141:32 | LL | let _ = Some("").unwrap_or(&""); | ^^^ help: change this to: `""` error: the borrowed expression implements the required traits - --> $DIR/needless_borrow.rs:141:33 + --> $DIR/needless_borrow.rs:142:33 | LL | let _ = std::fs::write("x", &"".to_string()); | ^^^^^^^^^^^^^^^ help: change this to: `"".to_string()` error: this expression borrows a value the compiler would automatically borrow - --> $DIR/needless_borrow.rs:190:13 + --> $DIR/needless_borrow.rs:191:13 | LL | (&self.f)() | ^^^^^^^^^ help: change this to: `(self.f)` error: this expression borrows a value the compiler would automatically borrow - --> $DIR/needless_borrow.rs:199:13 + --> $DIR/needless_borrow.rs:200:13 | LL | (&mut self.f)() | ^^^^^^^^^^^^^ help: change this to: `(self.f)` error: the borrowed expression implements the required traits - --> $DIR/needless_borrow.rs:283:20 + --> $DIR/needless_borrow.rs:284:20 | LL | takes_iter(&mut x) | ^^^^^^ help: change this to: `x` error: the borrowed expression implements the required traits - --> $DIR/needless_borrow.rs:297:55 + --> $DIR/needless_borrow.rs:298:55 | LL | let _ = std::process::Command::new("ls").args(&["-a", "-l"]).status().unwrap(); | ^^^^^^^^^^^^^ help: change this to: `["-a", "-l"]` error: the borrowed expression implements the required traits - --> $DIR/needless_borrow.rs:335:37 + --> $DIR/needless_borrow.rs:336:37 | LL | let _ = std::fs::write("x", &arg); | ^^^^ help: change this to: `arg` error: the borrowed expression implements the required traits - --> $DIR/needless_borrow.rs:336:37 + --> $DIR/needless_borrow.rs:337:37 | LL | let _ = std::fs::write("x", &loc); | ^^^^ help: change this to: `loc` error: the borrowed expression implements the required traits - --> $DIR/needless_borrow.rs:354:15 + --> $DIR/needless_borrow.rs:355:15 | LL | debug(&x); | ^^ help: change this to: `x` error: the borrowed expression implements the required traits - --> $DIR/needless_borrow.rs:363:15 + --> $DIR/needless_borrow.rs:364:15 | LL | use_x(&x); | ^^ help: change this to: `x` error: the borrowed expression implements the required traits - --> $DIR/needless_borrow.rs:457:13 + --> $DIR/needless_borrow.rs:458:13 | LL | foo(&a); | ^^ help: change this to: `a` diff --git a/tests/ui/needless_range_loop.rs b/tests/ui/needless_range_loop.rs index 1935ccb94bd..a16ef5a5bca 100644 --- a/tests/ui/needless_range_loop.rs +++ b/tests/ui/needless_range_loop.rs @@ -1,5 +1,9 @@ #![warn(clippy::needless_range_loop)] -#![allow(clippy::uninlined_format_args, clippy::useless_vec)] +#![allow( + clippy::uninlined_format_args, + clippy::unnecessary_literal_unwrap, + clippy::useless_vec +)] static STATIC: [usize; 4] = [0, 1, 8, 16]; const CONST: [usize; 4] = [0, 1, 8, 16]; diff --git a/tests/ui/needless_range_loop.stderr b/tests/ui/needless_range_loop.stderr index cffa19bec3a..8ca6b880cea 100644 --- a/tests/ui/needless_range_loop.stderr +++ b/tests/ui/needless_range_loop.stderr @@ -1,5 +1,5 @@ error: the loop variable `i` is only used to index `vec` - --> $DIR/needless_range_loop.rs:11:14 + --> $DIR/needless_range_loop.rs:15:14 | LL | for i in 0..vec.len() { | ^^^^^^^^^^^^ @@ -11,7 +11,7 @@ LL | for in &vec { | ~~~~~~ ~~~~ error: the loop variable `i` is only used to index `vec` - --> $DIR/needless_range_loop.rs:20:14 + --> $DIR/needless_range_loop.rs:24:14 | LL | for i in 0..vec.len() { | ^^^^^^^^^^^^ @@ -22,7 +22,7 @@ LL | for in &vec { | ~~~~~~ ~~~~ error: the loop variable `j` is only used to index `STATIC` - --> $DIR/needless_range_loop.rs:25:14 + --> $DIR/needless_range_loop.rs:29:14 | LL | for j in 0..4 { | ^^^^ @@ -33,7 +33,7 @@ LL | for in &STATIC { | ~~~~~~ ~~~~~~~ error: the loop variable `j` is only used to index `CONST` - --> $DIR/needless_range_loop.rs:29:14 + --> $DIR/needless_range_loop.rs:33:14 | LL | for j in 0..4 { | ^^^^ @@ -44,7 +44,7 @@ LL | for in &CONST { | ~~~~~~ ~~~~~~ error: the loop variable `i` is used to index `vec` - --> $DIR/needless_range_loop.rs:33:14 + --> $DIR/needless_range_loop.rs:37:14 | LL | for i in 0..vec.len() { | ^^^^^^^^^^^^ @@ -55,7 +55,7 @@ LL | for (i, ) in vec.iter().enumerate() { | ~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~ error: the loop variable `i` is only used to index `vec2` - --> $DIR/needless_range_loop.rs:41:14 + --> $DIR/needless_range_loop.rs:45:14 | LL | for i in 0..vec.len() { | ^^^^^^^^^^^^ @@ -66,7 +66,7 @@ LL | for in vec2.iter().take(vec.len()) { | ~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~ error: the loop variable `i` is only used to index `vec` - --> $DIR/needless_range_loop.rs:45:14 + --> $DIR/needless_range_loop.rs:49:14 | LL | for i in 5..vec.len() { | ^^^^^^^^^^^^ @@ -77,7 +77,7 @@ LL | for in vec.iter().skip(5) { | ~~~~~~ ~~~~~~~~~~~~~~~~~~ error: the loop variable `i` is only used to index `vec` - --> $DIR/needless_range_loop.rs:49:14 + --> $DIR/needless_range_loop.rs:53:14 | LL | for i in 0..MAX_LEN { | ^^^^^^^^^^ @@ -88,7 +88,7 @@ LL | for in vec.iter().take(MAX_LEN) { | ~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~ error: the loop variable `i` is only used to index `vec` - --> $DIR/needless_range_loop.rs:53:14 + --> $DIR/needless_range_loop.rs:57:14 | LL | for i in 0..=MAX_LEN { | ^^^^^^^^^^^ @@ -99,7 +99,7 @@ LL | for in vec.iter().take(MAX_LEN + 1) { | ~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ error: the loop variable `i` is only used to index `vec` - --> $DIR/needless_range_loop.rs:57:14 + --> $DIR/needless_range_loop.rs:61:14 | LL | for i in 5..10 { | ^^^^^ @@ -110,7 +110,7 @@ LL | for in vec.iter().take(10).skip(5) { | ~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~ error: the loop variable `i` is only used to index `vec` - --> $DIR/needless_range_loop.rs:61:14 + --> $DIR/needless_range_loop.rs:65:14 | LL | for i in 5..=10 { | ^^^^^^ @@ -121,7 +121,7 @@ LL | for in vec.iter().take(10 + 1).skip(5) { | ~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ error: the loop variable `i` is used to index `vec` - --> $DIR/needless_range_loop.rs:65:14 + --> $DIR/needless_range_loop.rs:69:14 | LL | for i in 5..vec.len() { | ^^^^^^^^^^^^ @@ -132,7 +132,7 @@ LL | for (i, ) in vec.iter().enumerate().skip(5) { | ~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ error: the loop variable `i` is used to index `vec` - --> $DIR/needless_range_loop.rs:69:14 + --> $DIR/needless_range_loop.rs:73:14 | LL | for i in 5..10 { | ^^^^^ @@ -143,7 +143,7 @@ LL | for (i, ) in vec.iter().enumerate().take(10).skip(5) { | ~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ error: the loop variable `i` is used to index `vec` - --> $DIR/needless_range_loop.rs:74:14 + --> $DIR/needless_range_loop.rs:78:14 | LL | for i in 0..vec.len() { | ^^^^^^^^^^^^ diff --git a/tests/ui/ok_expect.rs b/tests/ui/ok_expect.rs index ff68d38c73b..2047ee689d9 100644 --- a/tests/ui/ok_expect.rs +++ b/tests/ui/ok_expect.rs @@ -1,3 +1,5 @@ +#![allow(clippy::unnecessary_literal_unwrap)] + use std::io; struct MyError(()); // doesn't implement Debug diff --git a/tests/ui/ok_expect.stderr b/tests/ui/ok_expect.stderr index 6c40adbb53d..ab9df26ebc3 100644 --- a/tests/ui/ok_expect.stderr +++ b/tests/ui/ok_expect.stderr @@ -1,5 +1,5 @@ error: called `ok().expect()` on a `Result` value - --> $DIR/ok_expect.rs:14:5 + --> $DIR/ok_expect.rs:16:5 | LL | res.ok().expect("disaster!"); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -8,7 +8,7 @@ LL | res.ok().expect("disaster!"); = note: `-D clippy::ok-expect` implied by `-D warnings` error: called `ok().expect()` on a `Result` value - --> $DIR/ok_expect.rs:20:5 + --> $DIR/ok_expect.rs:22:5 | LL | res3.ok().expect("whoof"); | ^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -16,7 +16,7 @@ LL | res3.ok().expect("whoof"); = help: you can call `expect()` directly on the `Result` error: called `ok().expect()` on a `Result` value - --> $DIR/ok_expect.rs:22:5 + --> $DIR/ok_expect.rs:24:5 | LL | res4.ok().expect("argh"); | ^^^^^^^^^^^^^^^^^^^^^^^^ @@ -24,7 +24,7 @@ LL | res4.ok().expect("argh"); = help: you can call `expect()` directly on the `Result` error: called `ok().expect()` on a `Result` value - --> $DIR/ok_expect.rs:24:5 + --> $DIR/ok_expect.rs:26:5 | LL | res5.ok().expect("oops"); | ^^^^^^^^^^^^^^^^^^^^^^^^ @@ -32,7 +32,7 @@ LL | res5.ok().expect("oops"); = help: you can call `expect()` directly on the `Result` error: called `ok().expect()` on a `Result` value - --> $DIR/ok_expect.rs:26:5 + --> $DIR/ok_expect.rs:28:5 | LL | res6.ok().expect("meh"); | ^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/or_fun_call.fixed b/tests/ui/or_fun_call.fixed index 08a536a2844..703debb7a26 100644 --- a/tests/ui/or_fun_call.fixed +++ b/tests/ui/or_fun_call.fixed @@ -5,6 +5,7 @@ clippy::borrow_as_ptr, clippy::uninlined_format_args, clippy::unnecessary_wraps, + clippy::unnecessary_literal_unwrap, clippy::useless_vec )] diff --git a/tests/ui/or_fun_call.rs b/tests/ui/or_fun_call.rs index 83ba68382ef..bb86fe0d45f 100644 --- a/tests/ui/or_fun_call.rs +++ b/tests/ui/or_fun_call.rs @@ -5,6 +5,7 @@ clippy::borrow_as_ptr, clippy::uninlined_format_args, clippy::unnecessary_wraps, + clippy::unnecessary_literal_unwrap, clippy::useless_vec )] diff --git a/tests/ui/or_fun_call.stderr b/tests/ui/or_fun_call.stderr index ec87674b100..0b5c686bec0 100644 --- a/tests/ui/or_fun_call.stderr +++ b/tests/ui/or_fun_call.stderr @@ -1,5 +1,5 @@ error: use of `unwrap_or` followed by a function call - --> $DIR/or_fun_call.rs:53:22 + --> $DIR/or_fun_call.rs:54:22 | LL | with_constructor.unwrap_or(make()); | ^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_else(make)` @@ -7,163 +7,163 @@ LL | with_constructor.unwrap_or(make()); = note: `-D clippy::or-fun-call` implied by `-D warnings` error: use of `unwrap_or` followed by a call to `new` - --> $DIR/or_fun_call.rs:56:14 + --> $DIR/or_fun_call.rs:57:14 | LL | with_new.unwrap_or(Vec::new()); | ^^^^^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_default()` error: use of `unwrap_or` followed by a function call - --> $DIR/or_fun_call.rs:59:21 + --> $DIR/or_fun_call.rs:60:21 | LL | with_const_args.unwrap_or(Vec::with_capacity(12)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_else(|| Vec::with_capacity(12))` error: use of `unwrap_or` followed by a function call - --> $DIR/or_fun_call.rs:62:14 + --> $DIR/or_fun_call.rs:63:14 | LL | with_err.unwrap_or(make()); | ^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_else(|_| make())` error: use of `unwrap_or` followed by a function call - --> $DIR/or_fun_call.rs:65:19 + --> $DIR/or_fun_call.rs:66:19 | LL | with_err_args.unwrap_or(Vec::with_capacity(12)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_else(|_| Vec::with_capacity(12))` error: use of `unwrap_or` followed by a call to `default` - --> $DIR/or_fun_call.rs:68:24 + --> $DIR/or_fun_call.rs:69:24 | LL | with_default_trait.unwrap_or(Default::default()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_default()` error: use of `unwrap_or` followed by a call to `default` - --> $DIR/or_fun_call.rs:71:23 + --> $DIR/or_fun_call.rs:72:23 | LL | with_default_type.unwrap_or(u64::default()); | ^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_default()` error: use of `unwrap_or` followed by a function call - --> $DIR/or_fun_call.rs:74:18 + --> $DIR/or_fun_call.rs:75:18 | LL | self_default.unwrap_or(::default()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_else(::default)` error: use of `unwrap_or` followed by a call to `default` - --> $DIR/or_fun_call.rs:77:18 + --> $DIR/or_fun_call.rs:78:18 | LL | real_default.unwrap_or(::default()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_default()` error: use of `unwrap_or` followed by a call to `new` - --> $DIR/or_fun_call.rs:80:14 + --> $DIR/or_fun_call.rs:81:14 | LL | with_vec.unwrap_or(vec![]); | ^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_default()` error: use of `unwrap_or` followed by a function call - --> $DIR/or_fun_call.rs:83:21 + --> $DIR/or_fun_call.rs:84:21 | LL | without_default.unwrap_or(Foo::new()); | ^^^^^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_else(Foo::new)` error: use of `or_insert` followed by a call to `new` - --> $DIR/or_fun_call.rs:86:19 + --> $DIR/or_fun_call.rs:87:19 | LL | map.entry(42).or_insert(String::new()); | ^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `or_default()` error: use of `or_insert` followed by a call to `new` - --> $DIR/or_fun_call.rs:89:23 + --> $DIR/or_fun_call.rs:90:23 | LL | map_vec.entry(42).or_insert(vec![]); | ^^^^^^^^^^^^^^^^^ help: try this: `or_default()` error: use of `or_insert` followed by a call to `new` - --> $DIR/or_fun_call.rs:92:21 + --> $DIR/or_fun_call.rs:93:21 | LL | btree.entry(42).or_insert(String::new()); | ^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `or_default()` error: use of `or_insert` followed by a call to `new` - --> $DIR/or_fun_call.rs:95:25 + --> $DIR/or_fun_call.rs:96:25 | LL | btree_vec.entry(42).or_insert(vec![]); | ^^^^^^^^^^^^^^^^^ help: try this: `or_default()` error: use of `unwrap_or` followed by a call to `new` - --> $DIR/or_fun_call.rs:98:21 + --> $DIR/or_fun_call.rs:99:21 | LL | let _ = stringy.unwrap_or(String::new()); | ^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_default()` error: use of `unwrap_or` followed by a function call - --> $DIR/or_fun_call.rs:106:21 + --> $DIR/or_fun_call.rs:107:21 | LL | let _ = Some(1).unwrap_or(map[&1]); | ^^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_else(|| map[&1])` error: use of `unwrap_or` followed by a function call - --> $DIR/or_fun_call.rs:108:21 + --> $DIR/or_fun_call.rs:109:21 | LL | let _ = Some(1).unwrap_or(map[&1]); | ^^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_else(|| map[&1])` error: use of `or` followed by a function call - --> $DIR/or_fun_call.rs:132:35 + --> $DIR/or_fun_call.rs:133:35 | LL | let _ = Some("a".to_string()).or(Some("b".to_string())); | ^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `or_else(|| Some("b".to_string()))` error: use of `unwrap_or` followed by a function call - --> $DIR/or_fun_call.rs:171:14 + --> $DIR/or_fun_call.rs:172:14 | LL | None.unwrap_or(ptr_to_ref(s)); | ^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_else(|| ptr_to_ref(s))` error: use of `unwrap_or` followed by a function call - --> $DIR/or_fun_call.rs:177:14 + --> $DIR/or_fun_call.rs:178:14 | LL | None.unwrap_or(unsafe { ptr_to_ref(s) }); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_else(|| unsafe { ptr_to_ref(s) })` error: use of `unwrap_or` followed by a function call - --> $DIR/or_fun_call.rs:179:14 + --> $DIR/or_fun_call.rs:180:14 | LL | None.unwrap_or( unsafe { ptr_to_ref(s) } ); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_else(|| unsafe { ptr_to_ref(s) })` error: use of `unwrap_or` followed by a call to `new` - --> $DIR/or_fun_call.rs:193:14 + --> $DIR/or_fun_call.rs:194:14 | LL | .unwrap_or(String::new()); | ^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_default()` error: use of `unwrap_or` followed by a call to `new` - --> $DIR/or_fun_call.rs:206:14 + --> $DIR/or_fun_call.rs:207:14 | LL | .unwrap_or(String::new()); | ^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_default()` error: use of `unwrap_or` followed by a call to `new` - --> $DIR/or_fun_call.rs:218:14 + --> $DIR/or_fun_call.rs:219:14 | LL | .unwrap_or(String::new()); | ^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_default()` error: use of `unwrap_or` followed by a call to `new` - --> $DIR/or_fun_call.rs:229:10 + --> $DIR/or_fun_call.rs:230:10 | LL | .unwrap_or(String::new()); | ^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_default()` error: use of `map_or` followed by a function call - --> $DIR/or_fun_call.rs:254:25 + --> $DIR/or_fun_call.rs:255:25 | LL | let _ = Some(4).map_or(g(), |v| v); | ^^^^^^^^^^^^^^^^^^ help: try this: `map_or_else(g, |v| v)` error: use of `map_or` followed by a function call - --> $DIR/or_fun_call.rs:255:25 + --> $DIR/or_fun_call.rs:256:25 | LL | let _ = Some(4).map_or(g(), f); | ^^^^^^^^^^^^^^ help: try this: `map_or_else(g, f)` diff --git a/tests/ui/or_then_unwrap.fixed b/tests/ui/or_then_unwrap.fixed index 40badac4424..773dfc3c5d1 100644 --- a/tests/ui/or_then_unwrap.fixed +++ b/tests/ui/or_then_unwrap.fixed @@ -1,7 +1,7 @@ //@run-rustfix #![warn(clippy::or_then_unwrap)] -#![allow(clippy::map_identity, clippy::let_unit_value)] +#![allow(clippy::map_identity, clippy::let_unit_value, clippy::unnecessary_literal_unwrap)] struct SomeStruct; impl SomeStruct { diff --git a/tests/ui/or_then_unwrap.rs b/tests/ui/or_then_unwrap.rs index 76c9942fe6c..5867e014878 100644 --- a/tests/ui/or_then_unwrap.rs +++ b/tests/ui/or_then_unwrap.rs @@ -1,7 +1,7 @@ //@run-rustfix #![warn(clippy::or_then_unwrap)] -#![allow(clippy::map_identity, clippy::let_unit_value)] +#![allow(clippy::map_identity, clippy::let_unit_value, clippy::unnecessary_literal_unwrap)] struct SomeStruct; impl SomeStruct { diff --git a/tests/ui/redundant_clone.fixed b/tests/ui/redundant_clone.fixed index cb9583aa6ee..5037c08ebd5 100644 --- a/tests/ui/redundant_clone.fixed +++ b/tests/ui/redundant_clone.fixed @@ -2,7 +2,12 @@ // rustfix-only-machine-applicable #![feature(lint_reasons)] #![warn(clippy::redundant_clone)] -#![allow(clippy::drop_non_drop, clippy::implicit_clone, clippy::uninlined_format_args)] +#![allow( + clippy::drop_non_drop, + clippy::implicit_clone, + clippy::uninlined_format_args, + clippy::unnecessary_literal_unwrap +)] use std::ffi::OsString; use std::path::Path; diff --git a/tests/ui/redundant_clone.rs b/tests/ui/redundant_clone.rs index e5aeacbb56c..501898bf113 100644 --- a/tests/ui/redundant_clone.rs +++ b/tests/ui/redundant_clone.rs @@ -2,7 +2,12 @@ // rustfix-only-machine-applicable #![feature(lint_reasons)] #![warn(clippy::redundant_clone)] -#![allow(clippy::drop_non_drop, clippy::implicit_clone, clippy::uninlined_format_args)] +#![allow( + clippy::drop_non_drop, + clippy::implicit_clone, + clippy::uninlined_format_args, + clippy::unnecessary_literal_unwrap +)] use std::ffi::OsString; use std::path::Path; diff --git a/tests/ui/redundant_clone.stderr b/tests/ui/redundant_clone.stderr index bb5c602d63a..8660c0e1f6a 100644 --- a/tests/ui/redundant_clone.stderr +++ b/tests/ui/redundant_clone.stderr @@ -1,180 +1,180 @@ error: redundant clone - --> $DIR/redundant_clone.rs:11:42 + --> $DIR/redundant_clone.rs:16:42 | LL | let _s = ["lorem", "ipsum"].join(" ").to_string(); | ^^^^^^^^^^^^ help: remove this | note: this value is dropped without further use - --> $DIR/redundant_clone.rs:11:14 + --> $DIR/redundant_clone.rs:16:14 | LL | let _s = ["lorem", "ipsum"].join(" ").to_string(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ = note: `-D clippy::redundant-clone` implied by `-D warnings` error: redundant clone - --> $DIR/redundant_clone.rs:14:15 + --> $DIR/redundant_clone.rs:19:15 | LL | let _s = s.clone(); | ^^^^^^^^ help: remove this | note: this value is dropped without further use - --> $DIR/redundant_clone.rs:14:14 + --> $DIR/redundant_clone.rs:19:14 | LL | let _s = s.clone(); | ^ error: redundant clone - --> $DIR/redundant_clone.rs:17:15 + --> $DIR/redundant_clone.rs:22:15 | LL | let _s = s.to_string(); | ^^^^^^^^^^^^ help: remove this | note: this value is dropped without further use - --> $DIR/redundant_clone.rs:17:14 + --> $DIR/redundant_clone.rs:22:14 | LL | let _s = s.to_string(); | ^ error: redundant clone - --> $DIR/redundant_clone.rs:20:15 + --> $DIR/redundant_clone.rs:25:15 | LL | let _s = s.to_owned(); | ^^^^^^^^^^^ help: remove this | note: this value is dropped without further use - --> $DIR/redundant_clone.rs:20:14 + --> $DIR/redundant_clone.rs:25:14 | LL | let _s = s.to_owned(); | ^ error: redundant clone - --> $DIR/redundant_clone.rs:22:42 + --> $DIR/redundant_clone.rs:27:42 | LL | let _s = Path::new("/a/b/").join("c").to_owned(); | ^^^^^^^^^^^ help: remove this | note: this value is dropped without further use - --> $DIR/redundant_clone.rs:22:14 + --> $DIR/redundant_clone.rs:27:14 | LL | let _s = Path::new("/a/b/").join("c").to_owned(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: redundant clone - --> $DIR/redundant_clone.rs:24:42 + --> $DIR/redundant_clone.rs:29:42 | LL | let _s = Path::new("/a/b/").join("c").to_path_buf(); | ^^^^^^^^^^^^^^ help: remove this | note: this value is dropped without further use - --> $DIR/redundant_clone.rs:24:14 + --> $DIR/redundant_clone.rs:29:14 | LL | let _s = Path::new("/a/b/").join("c").to_path_buf(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: redundant clone - --> $DIR/redundant_clone.rs:26:29 + --> $DIR/redundant_clone.rs:31:29 | LL | let _s = OsString::new().to_owned(); | ^^^^^^^^^^^ help: remove this | note: this value is dropped without further use - --> $DIR/redundant_clone.rs:26:14 + --> $DIR/redundant_clone.rs:31:14 | LL | let _s = OsString::new().to_owned(); | ^^^^^^^^^^^^^^^ error: redundant clone - --> $DIR/redundant_clone.rs:28:29 + --> $DIR/redundant_clone.rs:33:29 | LL | let _s = OsString::new().to_os_string(); | ^^^^^^^^^^^^^^^ help: remove this | note: this value is dropped without further use - --> $DIR/redundant_clone.rs:28:14 + --> $DIR/redundant_clone.rs:33:14 | LL | let _s = OsString::new().to_os_string(); | ^^^^^^^^^^^^^^^ error: redundant clone - --> $DIR/redundant_clone.rs:39:19 + --> $DIR/redundant_clone.rs:44:19 | LL | let _t = tup.0.clone(); | ^^^^^^^^ help: remove this | note: this value is dropped without further use - --> $DIR/redundant_clone.rs:39:14 + --> $DIR/redundant_clone.rs:44:14 | LL | let _t = tup.0.clone(); | ^^^^^ error: redundant clone - --> $DIR/redundant_clone.rs:71:25 + --> $DIR/redundant_clone.rs:76:25 | LL | if b { (a.clone(), a.clone()) } else { (Alpha, a) } | ^^^^^^^^ help: remove this | note: this value is dropped without further use - --> $DIR/redundant_clone.rs:71:24 + --> $DIR/redundant_clone.rs:76:24 | LL | if b { (a.clone(), a.clone()) } else { (Alpha, a) } | ^ error: redundant clone - --> $DIR/redundant_clone.rs:128:15 + --> $DIR/redundant_clone.rs:133:15 | LL | let _s = s.clone(); | ^^^^^^^^ help: remove this | note: this value is dropped without further use - --> $DIR/redundant_clone.rs:128:14 + --> $DIR/redundant_clone.rs:133:14 | LL | let _s = s.clone(); | ^ error: redundant clone - --> $DIR/redundant_clone.rs:129:15 + --> $DIR/redundant_clone.rs:134:15 | LL | let _t = t.clone(); | ^^^^^^^^ help: remove this | note: this value is dropped without further use - --> $DIR/redundant_clone.rs:129:14 + --> $DIR/redundant_clone.rs:134:14 | LL | let _t = t.clone(); | ^ error: redundant clone - --> $DIR/redundant_clone.rs:139:19 + --> $DIR/redundant_clone.rs:144:19 | LL | let _f = f.clone(); | ^^^^^^^^ help: remove this | note: this value is dropped without further use - --> $DIR/redundant_clone.rs:139:18 + --> $DIR/redundant_clone.rs:144:18 | LL | let _f = f.clone(); | ^ error: redundant clone - --> $DIR/redundant_clone.rs:151:14 + --> $DIR/redundant_clone.rs:156:14 | LL | let y = x.clone().join("matthias"); | ^^^^^^^^ help: remove this | note: cloned value is neither consumed nor mutated - --> $DIR/redundant_clone.rs:151:13 + --> $DIR/redundant_clone.rs:156:13 | LL | let y = x.clone().join("matthias"); | ^^^^^^^^^ error: redundant clone - --> $DIR/redundant_clone.rs:205:11 + --> $DIR/redundant_clone.rs:210:11 | LL | foo(&x.clone(), move || { | ^^^^^^^^ help: remove this | note: this value is dropped without further use - --> $DIR/redundant_clone.rs:205:10 + --> $DIR/redundant_clone.rs:210:10 | LL | foo(&x.clone(), move || { | ^ diff --git a/tests/ui/uninlined_format_args.fixed b/tests/ui/uninlined_format_args.fixed index e25d123dd51..972e0356b62 100644 --- a/tests/ui/uninlined_format_args.fixed +++ b/tests/ui/uninlined_format_args.fixed @@ -2,7 +2,12 @@ //@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)] +#![allow( + clippy::eq_op, + clippy::format_in_format_args, + clippy::print_literal, + clippy::unnecessary_literal_unwrap +)] extern crate proc_macros; use proc_macros::with_span; diff --git a/tests/ui/uninlined_format_args.rs b/tests/ui/uninlined_format_args.rs index 6793ec24441..7614ffb38e6 100644 --- a/tests/ui/uninlined_format_args.rs +++ b/tests/ui/uninlined_format_args.rs @@ -2,7 +2,12 @@ //@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)] +#![allow( + clippy::eq_op, + clippy::format_in_format_args, + clippy::print_literal, + clippy::unnecessary_literal_unwrap +)] extern crate proc_macros; use proc_macros::with_span; diff --git a/tests/ui/uninlined_format_args.stderr b/tests/ui/uninlined_format_args.stderr index dc4af6ef42e..44ca61f008c 100644 --- a/tests/ui/uninlined_format_args.stderr +++ b/tests/ui/uninlined_format_args.stderr @@ -1,5 +1,5 @@ error: variables can be used directly in the `format!` string - --> $DIR/uninlined_format_args.rs:40:5 + --> $DIR/uninlined_format_args.rs:45:5 | LL | println!("val='{}'", local_i32); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -12,7 +12,7 @@ LL + println!("val='{local_i32}'"); | error: variables can be used directly in the `format!` string - --> $DIR/uninlined_format_args.rs:41:5 + --> $DIR/uninlined_format_args.rs:46:5 | LL | println!("val='{ }'", local_i32); // 3 spaces | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -24,7 +24,7 @@ LL + println!("val='{local_i32}'"); // 3 spaces | error: variables can be used directly in the `format!` string - --> $DIR/uninlined_format_args.rs:42:5 + --> $DIR/uninlined_format_args.rs:47:5 | LL | println!("val='{ }'", local_i32); // tab | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -36,7 +36,7 @@ LL + println!("val='{local_i32}'"); // tab | error: variables can be used directly in the `format!` string - --> $DIR/uninlined_format_args.rs:43:5 + --> $DIR/uninlined_format_args.rs:48:5 | LL | println!("val='{ }'", local_i32); // space+tab | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -48,7 +48,7 @@ LL + println!("val='{local_i32}'"); // space+tab | error: variables can be used directly in the `format!` string - --> $DIR/uninlined_format_args.rs:44:5 + --> $DIR/uninlined_format_args.rs:49:5 | LL | println!("val='{ }'", local_i32); // tab+space | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -60,7 +60,7 @@ LL + println!("val='{local_i32}'"); // tab+space | error: variables can be used directly in the `format!` string - --> $DIR/uninlined_format_args.rs:45:5 + --> $DIR/uninlined_format_args.rs:50:5 | LL | / println!( LL | | "val='{ @@ -70,7 +70,7 @@ LL | | ); | |_____^ error: variables can be used directly in the `format!` string - --> $DIR/uninlined_format_args.rs:50:5 + --> $DIR/uninlined_format_args.rs:55:5 | LL | println!("{}", local_i32); | ^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -82,7 +82,7 @@ LL + println!("{local_i32}"); | error: variables can be used directly in the `format!` string - --> $DIR/uninlined_format_args.rs:51:5 + --> $DIR/uninlined_format_args.rs:56:5 | LL | println!("{}", fn_arg); | ^^^^^^^^^^^^^^^^^^^^^^ @@ -94,7 +94,7 @@ LL + println!("{fn_arg}"); | error: variables can be used directly in the `format!` string - --> $DIR/uninlined_format_args.rs:52:5 + --> $DIR/uninlined_format_args.rs:57:5 | LL | println!("{:?}", local_i32); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -106,7 +106,7 @@ LL + println!("{local_i32:?}"); | error: variables can be used directly in the `format!` string - --> $DIR/uninlined_format_args.rs:53:5 + --> $DIR/uninlined_format_args.rs:58:5 | LL | println!("{:#?}", local_i32); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -118,7 +118,7 @@ LL + println!("{local_i32:#?}"); | error: variables can be used directly in the `format!` string - --> $DIR/uninlined_format_args.rs:54:5 + --> $DIR/uninlined_format_args.rs:59:5 | LL | println!("{:4}", local_i32); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -130,7 +130,7 @@ LL + println!("{local_i32:4}"); | error: variables can be used directly in the `format!` string - --> $DIR/uninlined_format_args.rs:55:5 + --> $DIR/uninlined_format_args.rs:60:5 | LL | println!("{:04}", local_i32); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -142,7 +142,7 @@ LL + println!("{local_i32:04}"); | error: variables can be used directly in the `format!` string - --> $DIR/uninlined_format_args.rs:56:5 + --> $DIR/uninlined_format_args.rs:61:5 | LL | println!("{:<3}", local_i32); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -154,7 +154,7 @@ LL + println!("{local_i32:<3}"); | error: variables can be used directly in the `format!` string - --> $DIR/uninlined_format_args.rs:57:5 + --> $DIR/uninlined_format_args.rs:62:5 | LL | println!("{:#010x}", local_i32); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -166,7 +166,7 @@ LL + println!("{local_i32:#010x}"); | error: variables can be used directly in the `format!` string - --> $DIR/uninlined_format_args.rs:58:5 + --> $DIR/uninlined_format_args.rs:63:5 | LL | println!("{:.1}", local_f64); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -178,7 +178,7 @@ LL + println!("{local_f64:.1}"); | error: variables can be used directly in the `format!` string - --> $DIR/uninlined_format_args.rs:62:5 + --> $DIR/uninlined_format_args.rs:67:5 | LL | println!("{} {}", local_i32, local_f64); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -190,7 +190,7 @@ LL + println!("{local_i32} {local_f64}"); | error: variables can be used directly in the `format!` string - --> $DIR/uninlined_format_args.rs:64:5 + --> $DIR/uninlined_format_args.rs:69:5 | LL | println!("{}", val); | ^^^^^^^^^^^^^^^^^^^ @@ -202,7 +202,7 @@ LL + println!("{val}"); | error: variables can be used directly in the `format!` string - --> $DIR/uninlined_format_args.rs:65:5 + --> $DIR/uninlined_format_args.rs:70:5 | LL | println!("{}", v = val); | ^^^^^^^^^^^^^^^^^^^^^^^ @@ -214,7 +214,7 @@ LL + println!("{val}"); | error: variables can be used directly in the `format!` string - --> $DIR/uninlined_format_args.rs:67:5 + --> $DIR/uninlined_format_args.rs:72:5 | LL | println!("val='{/t }'", local_i32); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -226,7 +226,7 @@ LL + println!("val='{local_i32}'"); | error: variables can be used directly in the `format!` string - --> $DIR/uninlined_format_args.rs:68:5 + --> $DIR/uninlined_format_args.rs:73:5 | LL | println!("val='{/n }'", local_i32); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -238,7 +238,7 @@ LL + println!("val='{local_i32}'"); | error: variables can be used directly in the `format!` string - --> $DIR/uninlined_format_args.rs:69:5 + --> $DIR/uninlined_format_args.rs:74:5 | LL | println!("val='{local_i32}'", local_i32 = local_i32); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -250,7 +250,7 @@ LL + println!("val='{local_i32}'"); | error: variables can be used directly in the `format!` string - --> $DIR/uninlined_format_args.rs:70:5 + --> $DIR/uninlined_format_args.rs:75:5 | LL | println!("val='{local_i32}'", local_i32 = fn_arg); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -262,7 +262,7 @@ LL + println!("val='{fn_arg}'"); | error: variables can be used directly in the `format!` string - --> $DIR/uninlined_format_args.rs:71:5 + --> $DIR/uninlined_format_args.rs:76:5 | LL | println!("{0}", local_i32); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -274,7 +274,7 @@ LL + println!("{local_i32}"); | error: variables can be used directly in the `format!` string - --> $DIR/uninlined_format_args.rs:72:5 + --> $DIR/uninlined_format_args.rs:77:5 | LL | println!("{0:?}", local_i32); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -286,7 +286,7 @@ LL + println!("{local_i32:?}"); | error: variables can be used directly in the `format!` string - --> $DIR/uninlined_format_args.rs:73:5 + --> $DIR/uninlined_format_args.rs:78:5 | LL | println!("{0:#?}", local_i32); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -298,7 +298,7 @@ LL + println!("{local_i32:#?}"); | error: variables can be used directly in the `format!` string - --> $DIR/uninlined_format_args.rs:74:5 + --> $DIR/uninlined_format_args.rs:79:5 | LL | println!("{0:04}", local_i32); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -310,7 +310,7 @@ LL + println!("{local_i32:04}"); | error: variables can be used directly in the `format!` string - --> $DIR/uninlined_format_args.rs:75:5 + --> $DIR/uninlined_format_args.rs:80:5 | LL | println!("{0:<3}", local_i32); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -322,7 +322,7 @@ LL + println!("{local_i32:<3}"); | error: variables can be used directly in the `format!` string - --> $DIR/uninlined_format_args.rs:76:5 + --> $DIR/uninlined_format_args.rs:81:5 | LL | println!("{0:#010x}", local_i32); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -334,7 +334,7 @@ LL + println!("{local_i32:#010x}"); | error: variables can be used directly in the `format!` string - --> $DIR/uninlined_format_args.rs:77:5 + --> $DIR/uninlined_format_args.rs:82:5 | LL | println!("{0:.1}", local_f64); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -346,7 +346,7 @@ LL + println!("{local_f64:.1}"); | error: variables can be used directly in the `format!` string - --> $DIR/uninlined_format_args.rs:78:5 + --> $DIR/uninlined_format_args.rs:83:5 | LL | println!("{0} {0}", local_i32); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -358,7 +358,7 @@ LL + println!("{local_i32} {local_i32}"); | error: variables can be used directly in the `format!` string - --> $DIR/uninlined_format_args.rs:79:5 + --> $DIR/uninlined_format_args.rs:84:5 | LL | println!("{1} {} {0} {}", local_i32, local_f64); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -370,7 +370,7 @@ LL + println!("{local_f64} {local_i32} {local_i32} {local_f64}"); | error: variables can be used directly in the `format!` string - --> $DIR/uninlined_format_args.rs:80:5 + --> $DIR/uninlined_format_args.rs:85:5 | LL | println!("{0} {1}", local_i32, local_f64); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -382,7 +382,7 @@ LL + println!("{local_i32} {local_f64}"); | error: variables can be used directly in the `format!` string - --> $DIR/uninlined_format_args.rs:81:5 + --> $DIR/uninlined_format_args.rs:86:5 | LL | println!("{1} {0}", local_i32, local_f64); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -394,7 +394,7 @@ LL + println!("{local_f64} {local_i32}"); | error: variables can be used directly in the `format!` string - --> $DIR/uninlined_format_args.rs:82:5 + --> $DIR/uninlined_format_args.rs:87:5 | LL | println!("{1} {0} {1} {0}", local_i32, local_f64); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -406,7 +406,7 @@ LL + println!("{local_f64} {local_i32} {local_f64} {local_i32}"); | error: variables can be used directly in the `format!` string - --> $DIR/uninlined_format_args.rs:84:5 + --> $DIR/uninlined_format_args.rs:89:5 | LL | println!("{v}", v = local_i32); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -418,7 +418,7 @@ LL + println!("{local_i32}"); | error: variables can be used directly in the `format!` string - --> $DIR/uninlined_format_args.rs:85:5 + --> $DIR/uninlined_format_args.rs:90:5 | LL | println!("{local_i32:0$}", width); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -430,7 +430,7 @@ LL + println!("{local_i32:width$}"); | error: variables can be used directly in the `format!` string - --> $DIR/uninlined_format_args.rs:86:5 + --> $DIR/uninlined_format_args.rs:91:5 | LL | println!("{local_i32:w$}", w = width); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -442,7 +442,7 @@ LL + println!("{local_i32:width$}"); | error: variables can be used directly in the `format!` string - --> $DIR/uninlined_format_args.rs:87:5 + --> $DIR/uninlined_format_args.rs:92:5 | LL | println!("{local_i32:.0$}", prec); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -454,7 +454,7 @@ LL + println!("{local_i32:.prec$}"); | error: variables can be used directly in the `format!` string - --> $DIR/uninlined_format_args.rs:88:5 + --> $DIR/uninlined_format_args.rs:93:5 | LL | println!("{local_i32:.p$}", p = prec); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -466,7 +466,7 @@ LL + println!("{local_i32:.prec$}"); | error: variables can be used directly in the `format!` string - --> $DIR/uninlined_format_args.rs:89:5 + --> $DIR/uninlined_format_args.rs:94:5 | LL | println!("{:0$}", v = val); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -478,7 +478,7 @@ LL + println!("{val:val$}"); | error: variables can be used directly in the `format!` string - --> $DIR/uninlined_format_args.rs:90:5 + --> $DIR/uninlined_format_args.rs:95:5 | LL | println!("{0:0$}", v = val); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -490,7 +490,7 @@ LL + println!("{val:val$}"); | error: variables can be used directly in the `format!` string - --> $DIR/uninlined_format_args.rs:91:5 + --> $DIR/uninlined_format_args.rs:96:5 | LL | println!("{:0$.0$}", v = val); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -502,7 +502,7 @@ LL + println!("{val:val$.val$}"); | error: variables can be used directly in the `format!` string - --> $DIR/uninlined_format_args.rs:92:5 + --> $DIR/uninlined_format_args.rs:97:5 | LL | println!("{0:0$.0$}", v = val); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -514,7 +514,7 @@ LL + println!("{val:val$.val$}"); | error: variables can be used directly in the `format!` string - --> $DIR/uninlined_format_args.rs:93:5 + --> $DIR/uninlined_format_args.rs:98:5 | LL | println!("{0:0$.v$}", v = val); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -526,7 +526,7 @@ LL + println!("{val:val$.val$}"); | error: variables can be used directly in the `format!` string - --> $DIR/uninlined_format_args.rs:94:5 + --> $DIR/uninlined_format_args.rs:99:5 | LL | println!("{0:v$.0$}", v = val); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -538,7 +538,7 @@ LL + println!("{val:val$.val$}"); | error: variables can be used directly in the `format!` string - --> $DIR/uninlined_format_args.rs:95:5 + --> $DIR/uninlined_format_args.rs:100:5 | LL | println!("{v:0$.0$}", v = val); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -550,7 +550,7 @@ LL + println!("{val:val$.val$}"); | error: variables can be used directly in the `format!` string - --> $DIR/uninlined_format_args.rs:96:5 + --> $DIR/uninlined_format_args.rs:101:5 | LL | println!("{v:v$.0$}", v = val); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -562,7 +562,7 @@ LL + println!("{val:val$.val$}"); | error: variables can be used directly in the `format!` string - --> $DIR/uninlined_format_args.rs:97:5 + --> $DIR/uninlined_format_args.rs:102:5 | LL | println!("{v:0$.v$}", v = val); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -574,7 +574,7 @@ LL + println!("{val:val$.val$}"); | error: variables can be used directly in the `format!` string - --> $DIR/uninlined_format_args.rs:98:5 + --> $DIR/uninlined_format_args.rs:103:5 | LL | println!("{v:v$.v$}", v = val); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -586,7 +586,7 @@ LL + println!("{val:val$.val$}"); | error: variables can be used directly in the `format!` string - --> $DIR/uninlined_format_args.rs:99:5 + --> $DIR/uninlined_format_args.rs:104:5 | LL | println!("{:0$}", width); | ^^^^^^^^^^^^^^^^^^^^^^^^ @@ -598,7 +598,7 @@ LL + println!("{width:width$}"); | error: variables can be used directly in the `format!` string - --> $DIR/uninlined_format_args.rs:100:5 + --> $DIR/uninlined_format_args.rs:105:5 | LL | println!("{:1$}", local_i32, width); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -610,7 +610,7 @@ LL + println!("{local_i32:width$}"); | error: variables can be used directly in the `format!` string - --> $DIR/uninlined_format_args.rs:101:5 + --> $DIR/uninlined_format_args.rs:106:5 | LL | println!("{:w$}", w = width); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -622,7 +622,7 @@ LL + println!("{width:width$}"); | error: variables can be used directly in the `format!` string - --> $DIR/uninlined_format_args.rs:102:5 + --> $DIR/uninlined_format_args.rs:107:5 | LL | println!("{:w$}", local_i32, w = width); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -634,7 +634,7 @@ LL + println!("{local_i32:width$}"); | error: variables can be used directly in the `format!` string - --> $DIR/uninlined_format_args.rs:103:5 + --> $DIR/uninlined_format_args.rs:108:5 | LL | println!("{:.0$}", prec); | ^^^^^^^^^^^^^^^^^^^^^^^^ @@ -646,7 +646,7 @@ LL + println!("{prec:.prec$}"); | error: variables can be used directly in the `format!` string - --> $DIR/uninlined_format_args.rs:104:5 + --> $DIR/uninlined_format_args.rs:109:5 | LL | println!("{:.1$}", local_i32, prec); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -658,7 +658,7 @@ LL + println!("{local_i32:.prec$}"); | error: variables can be used directly in the `format!` string - --> $DIR/uninlined_format_args.rs:105:5 + --> $DIR/uninlined_format_args.rs:110:5 | LL | println!("{:.p$}", p = prec); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -670,7 +670,7 @@ LL + println!("{prec:.prec$}"); | error: variables can be used directly in the `format!` string - --> $DIR/uninlined_format_args.rs:106:5 + --> $DIR/uninlined_format_args.rs:111:5 | LL | println!("{:.p$}", local_i32, p = prec); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -682,7 +682,7 @@ LL + println!("{local_i32:.prec$}"); | error: variables can be used directly in the `format!` string - --> $DIR/uninlined_format_args.rs:107:5 + --> $DIR/uninlined_format_args.rs:112:5 | LL | println!("{:0$.1$}", width, prec); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -694,7 +694,7 @@ LL + println!("{width:width$.prec$}"); | error: variables can be used directly in the `format!` string - --> $DIR/uninlined_format_args.rs:108:5 + --> $DIR/uninlined_format_args.rs:113:5 | LL | println!("{:0$.w$}", width, w = prec); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -706,7 +706,7 @@ LL + println!("{width:width$.prec$}"); | error: variables can be used directly in the `format!` string - --> $DIR/uninlined_format_args.rs:109:5 + --> $DIR/uninlined_format_args.rs:114:5 | LL | println!("{:1$.2$}", local_f64, width, prec); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -718,7 +718,7 @@ LL + println!("{local_f64:width$.prec$}"); | error: variables can be used directly in the `format!` string - --> $DIR/uninlined_format_args.rs:110:5 + --> $DIR/uninlined_format_args.rs:115:5 | LL | println!("{:1$.2$} {0} {1} {2}", local_f64, width, prec); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -730,7 +730,7 @@ LL + println!("{local_f64:width$.prec$} {local_f64} {width} {prec}"); | error: variables can be used directly in the `format!` string - --> $DIR/uninlined_format_args.rs:111:5 + --> $DIR/uninlined_format_args.rs:116:5 | LL | / println!( LL | | "{0:1$.2$} {0:2$.1$} {1:0$.2$} {1:2$.0$} {2:0$.1$} {2:1$.0$}", @@ -739,7 +739,7 @@ LL | | ); | |_____^ error: variables can be used directly in the `format!` string - --> $DIR/uninlined_format_args.rs:122:5 + --> $DIR/uninlined_format_args.rs:127:5 | LL | println!("Width = {}, value with width = {:0$}", local_i32, local_f64); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -751,7 +751,7 @@ LL + println!("Width = {local_i32}, value with width = {local_f64:local_i32$ | error: variables can be used directly in the `format!` string - --> $DIR/uninlined_format_args.rs:123:5 + --> $DIR/uninlined_format_args.rs:128:5 | LL | println!("{:w$.p$}", local_i32, w = width, p = prec); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -763,7 +763,7 @@ LL + println!("{local_i32:width$.prec$}"); | error: variables can be used directly in the `format!` string - --> $DIR/uninlined_format_args.rs:124:5 + --> $DIR/uninlined_format_args.rs:129:5 | LL | println!("{:w$.p$}", w = width, p = prec); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -775,7 +775,7 @@ LL + println!("{width:width$.prec$}"); | error: variables can be used directly in the `format!` string - --> $DIR/uninlined_format_args.rs:143:5 + --> $DIR/uninlined_format_args.rs:148:5 | LL | / println!( LL | | "{}", @@ -785,7 +785,7 @@ LL | | ); | |_____^ error: variables can be used directly in the `format!` string - --> $DIR/uninlined_format_args.rs:148:5 + --> $DIR/uninlined_format_args.rs:153:5 | LL | println!("{}", /* comment with a comma , in it */ val); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -797,7 +797,7 @@ LL + println!("{val}"); | error: variables can be used directly in the `format!` string - --> $DIR/uninlined_format_args.rs:154:9 + --> $DIR/uninlined_format_args.rs:159:9 | LL | panic!("p1 {}", local_i32); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -809,7 +809,7 @@ LL + panic!("p1 {local_i32}"); | error: variables can be used directly in the `format!` string - --> $DIR/uninlined_format_args.rs:157:9 + --> $DIR/uninlined_format_args.rs:162:9 | LL | panic!("p2 {0}", local_i32); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -821,7 +821,7 @@ LL + panic!("p2 {local_i32}"); | error: variables can be used directly in the `format!` string - --> $DIR/uninlined_format_args.rs:160:9 + --> $DIR/uninlined_format_args.rs:165:9 | LL | panic!("p3 {local_i32}", local_i32 = local_i32); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -833,7 +833,7 @@ LL + panic!("p3 {local_i32}"); | error: variables can be used directly in the `format!` string - --> $DIR/uninlined_format_args.rs:180:5 + --> $DIR/uninlined_format_args.rs:185:5 | LL | println!("expand='{}'", local_i32); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/unnecessary_lazy_eval.fixed b/tests/ui/unnecessary_lazy_eval.fixed index 565bd96cf30..75a42809ad2 100644 --- a/tests/ui/unnecessary_lazy_eval.fixed +++ b/tests/ui/unnecessary_lazy_eval.fixed @@ -5,6 +5,7 @@ #![allow(clippy::bind_instead_of_map)] #![allow(clippy::map_identity)] #![allow(clippy::needless_borrow)] +#![allow(clippy::unnecessary_literal_unwrap)] use std::ops::Deref; diff --git a/tests/ui/unnecessary_lazy_eval.rs b/tests/ui/unnecessary_lazy_eval.rs index 3627076b2af..3777b9c25c2 100644 --- a/tests/ui/unnecessary_lazy_eval.rs +++ b/tests/ui/unnecessary_lazy_eval.rs @@ -5,6 +5,7 @@ #![allow(clippy::bind_instead_of_map)] #![allow(clippy::map_identity)] #![allow(clippy::needless_borrow)] +#![allow(clippy::unnecessary_literal_unwrap)] use std::ops::Deref; diff --git a/tests/ui/unnecessary_lazy_eval.stderr b/tests/ui/unnecessary_lazy_eval.stderr index 2850a632fc7..458eed1f359 100644 --- a/tests/ui/unnecessary_lazy_eval.stderr +++ b/tests/ui/unnecessary_lazy_eval.stderr @@ -1,5 +1,5 @@ error: unnecessary closure used to substitute value for `Option::None` - --> $DIR/unnecessary_lazy_eval.rs:68:13 + --> $DIR/unnecessary_lazy_eval.rs:69:13 | LL | let _ = opt.unwrap_or_else(|| 2); | ^^^^-------------------- @@ -9,7 +9,7 @@ LL | let _ = opt.unwrap_or_else(|| 2); = note: `-D clippy::unnecessary-lazy-evaluations` implied by `-D warnings` error: unnecessary closure used to substitute value for `Option::None` - --> $DIR/unnecessary_lazy_eval.rs:69:13 + --> $DIR/unnecessary_lazy_eval.rs:70:13 | LL | let _ = opt.unwrap_or_else(|| astronomers_pi); | ^^^^--------------------------------- @@ -17,7 +17,7 @@ LL | let _ = opt.unwrap_or_else(|| astronomers_pi); | help: use `unwrap_or(..)` instead: `unwrap_or(astronomers_pi)` error: unnecessary closure used to substitute value for `Option::None` - --> $DIR/unnecessary_lazy_eval.rs:70:13 + --> $DIR/unnecessary_lazy_eval.rs:71:13 | LL | let _ = opt.unwrap_or_else(|| ext_str.some_field); | ^^^^------------------------------------- @@ -25,7 +25,7 @@ LL | let _ = opt.unwrap_or_else(|| ext_str.some_field); | help: use `unwrap_or(..)` instead: `unwrap_or(ext_str.some_field)` error: unnecessary closure used to substitute value for `Option::None` - --> $DIR/unnecessary_lazy_eval.rs:72:13 + --> $DIR/unnecessary_lazy_eval.rs:73:13 | LL | let _ = opt.and_then(|_| ext_opt); | ^^^^--------------------- @@ -33,7 +33,7 @@ LL | let _ = opt.and_then(|_| ext_opt); | help: use `and(..)` instead: `and(ext_opt)` error: unnecessary closure used to substitute value for `Option::None` - --> $DIR/unnecessary_lazy_eval.rs:73:13 + --> $DIR/unnecessary_lazy_eval.rs:74:13 | LL | let _ = opt.or_else(|| ext_opt); | ^^^^------------------- @@ -41,7 +41,7 @@ LL | let _ = opt.or_else(|| ext_opt); | help: use `or(..)` instead: `or(ext_opt)` error: unnecessary closure used to substitute value for `Option::None` - --> $DIR/unnecessary_lazy_eval.rs:74:13 + --> $DIR/unnecessary_lazy_eval.rs:75:13 | LL | let _ = opt.or_else(|| None); | ^^^^---------------- @@ -49,7 +49,7 @@ LL | let _ = opt.or_else(|| None); | help: use `or(..)` instead: `or(None)` error: unnecessary closure used to substitute value for `Option::None` - --> $DIR/unnecessary_lazy_eval.rs:75:13 + --> $DIR/unnecessary_lazy_eval.rs:76:13 | LL | let _ = opt.get_or_insert_with(|| 2); | ^^^^------------------------ @@ -57,7 +57,7 @@ LL | let _ = opt.get_or_insert_with(|| 2); | help: use `get_or_insert(..)` instead: `get_or_insert(2)` error: unnecessary closure used to substitute value for `Option::None` - --> $DIR/unnecessary_lazy_eval.rs:76:13 + --> $DIR/unnecessary_lazy_eval.rs:77:13 | LL | let _ = opt.ok_or_else(|| 2); | ^^^^---------------- @@ -65,7 +65,7 @@ LL | let _ = opt.ok_or_else(|| 2); | help: use `ok_or(..)` instead: `ok_or(2)` error: unnecessary closure used to substitute value for `Option::None` - --> $DIR/unnecessary_lazy_eval.rs:77:13 + --> $DIR/unnecessary_lazy_eval.rs:78:13 | LL | let _ = nested_tuple_opt.unwrap_or_else(|| Some((1, 2))); | ^^^^^^^^^^^^^^^^^------------------------------- @@ -73,7 +73,7 @@ LL | let _ = nested_tuple_opt.unwrap_or_else(|| Some((1, 2))); | help: use `unwrap_or(..)` instead: `unwrap_or(Some((1, 2)))` error: unnecessary closure used with `bool::then` - --> $DIR/unnecessary_lazy_eval.rs:78:13 + --> $DIR/unnecessary_lazy_eval.rs:79:13 | LL | let _ = cond.then(|| astronomers_pi); | ^^^^^----------------------- @@ -81,7 +81,7 @@ LL | let _ = cond.then(|| astronomers_pi); | help: use `then_some(..)` instead: `then_some(astronomers_pi)` error: unnecessary closure used to substitute value for `Option::None` - --> $DIR/unnecessary_lazy_eval.rs:82:13 + --> $DIR/unnecessary_lazy_eval.rs:83:13 | LL | let _ = Some(1).unwrap_or_else(|| *r); | ^^^^^^^^--------------------- @@ -89,7 +89,7 @@ LL | let _ = Some(1).unwrap_or_else(|| *r); | help: use `unwrap_or(..)` instead: `unwrap_or(*r)` error: unnecessary closure used to substitute value for `Option::None` - --> $DIR/unnecessary_lazy_eval.rs:84:13 + --> $DIR/unnecessary_lazy_eval.rs:85:13 | LL | let _ = Some(1).unwrap_or_else(|| *b); | ^^^^^^^^--------------------- @@ -97,7 +97,7 @@ LL | let _ = Some(1).unwrap_or_else(|| *b); | help: use `unwrap_or(..)` instead: `unwrap_or(*b)` error: unnecessary closure used to substitute value for `Option::None` - --> $DIR/unnecessary_lazy_eval.rs:86:13 + --> $DIR/unnecessary_lazy_eval.rs:87:13 | LL | let _ = Some(1).as_ref().unwrap_or_else(|| &r); | ^^^^^^^^^^^^^^^^^--------------------- @@ -105,7 +105,7 @@ LL | let _ = Some(1).as_ref().unwrap_or_else(|| &r); | help: use `unwrap_or(..)` instead: `unwrap_or(&r)` error: unnecessary closure used to substitute value for `Option::None` - --> $DIR/unnecessary_lazy_eval.rs:87:13 + --> $DIR/unnecessary_lazy_eval.rs:88:13 | LL | let _ = Some(1).as_ref().unwrap_or_else(|| &b); | ^^^^^^^^^^^^^^^^^--------------------- @@ -113,7 +113,7 @@ LL | let _ = Some(1).as_ref().unwrap_or_else(|| &b); | help: use `unwrap_or(..)` instead: `unwrap_or(&b)` error: unnecessary closure used to substitute value for `Option::None` - --> $DIR/unnecessary_lazy_eval.rs:90:13 + --> $DIR/unnecessary_lazy_eval.rs:91:13 | LL | let _ = Some(10).unwrap_or_else(|| 2); | ^^^^^^^^^-------------------- @@ -121,7 +121,7 @@ LL | let _ = Some(10).unwrap_or_else(|| 2); | help: use `unwrap_or(..)` instead: `unwrap_or(2)` error: unnecessary closure used to substitute value for `Option::None` - --> $DIR/unnecessary_lazy_eval.rs:91:13 + --> $DIR/unnecessary_lazy_eval.rs:92:13 | LL | let _ = Some(10).and_then(|_| ext_opt); | ^^^^^^^^^--------------------- @@ -129,7 +129,7 @@ LL | let _ = Some(10).and_then(|_| ext_opt); | help: use `and(..)` instead: `and(ext_opt)` error: unnecessary closure used to substitute value for `Option::None` - --> $DIR/unnecessary_lazy_eval.rs:92:28 + --> $DIR/unnecessary_lazy_eval.rs:93:28 | LL | let _: Option = None.or_else(|| ext_opt); | ^^^^^------------------- @@ -137,7 +137,7 @@ LL | let _: Option = None.or_else(|| ext_opt); | help: use `or(..)` instead: `or(ext_opt)` error: unnecessary closure used to substitute value for `Option::None` - --> $DIR/unnecessary_lazy_eval.rs:93:13 + --> $DIR/unnecessary_lazy_eval.rs:94:13 | LL | let _ = None.get_or_insert_with(|| 2); | ^^^^^------------------------ @@ -145,7 +145,7 @@ LL | let _ = None.get_or_insert_with(|| 2); | help: use `get_or_insert(..)` instead: `get_or_insert(2)` error: unnecessary closure used to substitute value for `Option::None` - --> $DIR/unnecessary_lazy_eval.rs:94:35 + --> $DIR/unnecessary_lazy_eval.rs:95:35 | LL | let _: Result = None.ok_or_else(|| 2); | ^^^^^---------------- @@ -153,7 +153,7 @@ LL | let _: Result = None.ok_or_else(|| 2); | help: use `ok_or(..)` instead: `ok_or(2)` error: unnecessary closure used to substitute value for `Option::None` - --> $DIR/unnecessary_lazy_eval.rs:95:28 + --> $DIR/unnecessary_lazy_eval.rs:96:28 | LL | let _: Option = None.or_else(|| None); | ^^^^^---------------- @@ -161,7 +161,7 @@ LL | let _: Option = None.or_else(|| None); | help: use `or(..)` instead: `or(None)` error: unnecessary closure used to substitute value for `Option::None` - --> $DIR/unnecessary_lazy_eval.rs:98:13 + --> $DIR/unnecessary_lazy_eval.rs:99:13 | LL | let _ = deep.0.unwrap_or_else(|| 2); | ^^^^^^^-------------------- @@ -169,7 +169,7 @@ LL | let _ = deep.0.unwrap_or_else(|| 2); | help: use `unwrap_or(..)` instead: `unwrap_or(2)` error: unnecessary closure used to substitute value for `Option::None` - --> $DIR/unnecessary_lazy_eval.rs:99:13 + --> $DIR/unnecessary_lazy_eval.rs:100:13 | LL | let _ = deep.0.and_then(|_| ext_opt); | ^^^^^^^--------------------- @@ -177,7 +177,7 @@ LL | let _ = deep.0.and_then(|_| ext_opt); | help: use `and(..)` instead: `and(ext_opt)` error: unnecessary closure used to substitute value for `Option::None` - --> $DIR/unnecessary_lazy_eval.rs:100:13 + --> $DIR/unnecessary_lazy_eval.rs:101:13 | LL | let _ = deep.0.or_else(|| None); | ^^^^^^^---------------- @@ -185,7 +185,7 @@ LL | let _ = deep.0.or_else(|| None); | help: use `or(..)` instead: `or(None)` error: unnecessary closure used to substitute value for `Option::None` - --> $DIR/unnecessary_lazy_eval.rs:101:13 + --> $DIR/unnecessary_lazy_eval.rs:102:13 | LL | let _ = deep.0.get_or_insert_with(|| 2); | ^^^^^^^------------------------ @@ -193,7 +193,7 @@ LL | let _ = deep.0.get_or_insert_with(|| 2); | help: use `get_or_insert(..)` instead: `get_or_insert(2)` error: unnecessary closure used to substitute value for `Option::None` - --> $DIR/unnecessary_lazy_eval.rs:102:13 + --> $DIR/unnecessary_lazy_eval.rs:103:13 | LL | let _ = deep.0.ok_or_else(|| 2); | ^^^^^^^---------------- @@ -201,7 +201,7 @@ LL | let _ = deep.0.ok_or_else(|| 2); | help: use `ok_or(..)` instead: `ok_or(2)` error: unnecessary closure used to substitute value for `Option::None` - --> $DIR/unnecessary_lazy_eval.rs:132:28 + --> $DIR/unnecessary_lazy_eval.rs:133:28 | LL | let _: Option = None.or_else(|| Some(3)); | ^^^^^------------------- @@ -209,7 +209,7 @@ LL | let _: Option = None.or_else(|| Some(3)); | help: use `or(..)` instead: `or(Some(3))` error: unnecessary closure used to substitute value for `Option::None` - --> $DIR/unnecessary_lazy_eval.rs:133:13 + --> $DIR/unnecessary_lazy_eval.rs:134:13 | LL | let _ = deep.0.or_else(|| Some(3)); | ^^^^^^^------------------- @@ -217,7 +217,7 @@ LL | let _ = deep.0.or_else(|| Some(3)); | help: use `or(..)` instead: `or(Some(3))` error: unnecessary closure used to substitute value for `Option::None` - --> $DIR/unnecessary_lazy_eval.rs:134:13 + --> $DIR/unnecessary_lazy_eval.rs:135:13 | LL | let _ = opt.or_else(|| Some(3)); | ^^^^------------------- @@ -225,7 +225,7 @@ LL | let _ = opt.or_else(|| Some(3)); | help: use `or(..)` instead: `or(Some(3))` error: unnecessary closure used to substitute value for `Result::Err` - --> $DIR/unnecessary_lazy_eval.rs:140:13 + --> $DIR/unnecessary_lazy_eval.rs:141:13 | LL | let _ = res2.unwrap_or_else(|_| 2); | ^^^^^--------------------- @@ -233,7 +233,7 @@ LL | let _ = res2.unwrap_or_else(|_| 2); | help: use `unwrap_or(..)` instead: `unwrap_or(2)` error: unnecessary closure used to substitute value for `Result::Err` - --> $DIR/unnecessary_lazy_eval.rs:141:13 + --> $DIR/unnecessary_lazy_eval.rs:142:13 | LL | let _ = res2.unwrap_or_else(|_| astronomers_pi); | ^^^^^---------------------------------- @@ -241,7 +241,7 @@ LL | let _ = res2.unwrap_or_else(|_| astronomers_pi); | help: use `unwrap_or(..)` instead: `unwrap_or(astronomers_pi)` error: unnecessary closure used to substitute value for `Result::Err` - --> $DIR/unnecessary_lazy_eval.rs:142:13 + --> $DIR/unnecessary_lazy_eval.rs:143:13 | LL | let _ = res2.unwrap_or_else(|_| ext_str.some_field); | ^^^^^-------------------------------------- @@ -249,7 +249,7 @@ LL | let _ = res2.unwrap_or_else(|_| ext_str.some_field); | help: use `unwrap_or(..)` instead: `unwrap_or(ext_str.some_field)` error: unnecessary closure used to substitute value for `Result::Err` - --> $DIR/unnecessary_lazy_eval.rs:164:35 + --> $DIR/unnecessary_lazy_eval.rs:165:35 | LL | let _: Result = res.and_then(|_| Err(2)); | ^^^^-------------------- @@ -257,7 +257,7 @@ LL | let _: Result = res.and_then(|_| Err(2)); | help: use `and(..)` instead: `and(Err(2))` error: unnecessary closure used to substitute value for `Result::Err` - --> $DIR/unnecessary_lazy_eval.rs:165:35 + --> $DIR/unnecessary_lazy_eval.rs:166:35 | LL | let _: Result = res.and_then(|_| Err(astronomers_pi)); | ^^^^--------------------------------- @@ -265,7 +265,7 @@ LL | let _: Result = res.and_then(|_| Err(astronomers_pi)); | help: use `and(..)` instead: `and(Err(astronomers_pi))` error: unnecessary closure used to substitute value for `Result::Err` - --> $DIR/unnecessary_lazy_eval.rs:166:35 + --> $DIR/unnecessary_lazy_eval.rs:167:35 | LL | let _: Result = res.and_then(|_| Err(ext_str.some_field)); | ^^^^------------------------------------- @@ -273,7 +273,7 @@ LL | let _: Result = res.and_then(|_| Err(ext_str.some_field)) | help: use `and(..)` instead: `and(Err(ext_str.some_field))` error: unnecessary closure used to substitute value for `Result::Err` - --> $DIR/unnecessary_lazy_eval.rs:168:35 + --> $DIR/unnecessary_lazy_eval.rs:169:35 | LL | let _: Result = res.or_else(|_| Ok(2)); | ^^^^------------------ @@ -281,7 +281,7 @@ LL | let _: Result = res.or_else(|_| Ok(2)); | help: use `or(..)` instead: `or(Ok(2))` error: unnecessary closure used to substitute value for `Result::Err` - --> $DIR/unnecessary_lazy_eval.rs:169:35 + --> $DIR/unnecessary_lazy_eval.rs:170:35 | LL | let _: Result = res.or_else(|_| Ok(astronomers_pi)); | ^^^^------------------------------- @@ -289,7 +289,7 @@ LL | let _: Result = res.or_else(|_| Ok(astronomers_pi)); | help: use `or(..)` instead: `or(Ok(astronomers_pi))` error: unnecessary closure used to substitute value for `Result::Err` - --> $DIR/unnecessary_lazy_eval.rs:170:35 + --> $DIR/unnecessary_lazy_eval.rs:171:35 | LL | let _: Result = res.or_else(|_| Ok(ext_str.some_field)); | ^^^^----------------------------------- @@ -297,7 +297,7 @@ LL | let _: Result = res.or_else(|_| Ok(ext_str.some_field)); | help: use `or(..)` instead: `or(Ok(ext_str.some_field))` error: unnecessary closure used to substitute value for `Result::Err` - --> $DIR/unnecessary_lazy_eval.rs:171:35 + --> $DIR/unnecessary_lazy_eval.rs:172:35 | LL | let _: Result = res. | ___________________________________^ diff --git a/tests/ui/unnecessary_lazy_eval_unfixable.rs b/tests/ui/unnecessary_lazy_eval_unfixable.rs index b05dd143bfd..b4a1f81679a 100644 --- a/tests/ui/unnecessary_lazy_eval_unfixable.rs +++ b/tests/ui/unnecessary_lazy_eval_unfixable.rs @@ -1,4 +1,5 @@ #![warn(clippy::unnecessary_lazy_evaluations)] +#![allow(clippy::unnecessary_literal_unwrap)] struct Deep(Option); diff --git a/tests/ui/unnecessary_lazy_eval_unfixable.stderr b/tests/ui/unnecessary_lazy_eval_unfixable.stderr index 20acab6e844..7f353ba0698 100644 --- a/tests/ui/unnecessary_lazy_eval_unfixable.stderr +++ b/tests/ui/unnecessary_lazy_eval_unfixable.stderr @@ -1,5 +1,5 @@ error: unnecessary closure used to substitute value for `Result::Err` - --> $DIR/unnecessary_lazy_eval_unfixable.rs:12:13 + --> $DIR/unnecessary_lazy_eval_unfixable.rs:13:13 | LL | let _ = Ok(1).unwrap_or_else(|()| 2); | ^^^^^^---------------------- @@ -9,7 +9,7 @@ LL | let _ = Ok(1).unwrap_or_else(|()| 2); = note: `-D clippy::unnecessary-lazy-evaluations` implied by `-D warnings` error: unnecessary closure used to substitute value for `Result::Err` - --> $DIR/unnecessary_lazy_eval_unfixable.rs:16:13 + --> $DIR/unnecessary_lazy_eval_unfixable.rs:17:13 | LL | let _ = Ok(1).unwrap_or_else(|e::E| 2); | ^^^^^^------------------------ @@ -17,7 +17,7 @@ LL | let _ = Ok(1).unwrap_or_else(|e::E| 2); | help: use `unwrap_or(..)` instead: `unwrap_or(2)` error: unnecessary closure used to substitute value for `Result::Err` - --> $DIR/unnecessary_lazy_eval_unfixable.rs:17:13 + --> $DIR/unnecessary_lazy_eval_unfixable.rs:18:13 | LL | let _ = Ok(1).unwrap_or_else(|SomeStruct { .. }| 2); | ^^^^^^------------------------------------- diff --git a/tests/ui/unwrap.rs b/tests/ui/unwrap.rs index d9fd402e7cf..64d6437834e 100644 --- a/tests/ui/unwrap.rs +++ b/tests/ui/unwrap.rs @@ -1,4 +1,5 @@ #![warn(clippy::unwrap_used)] +#![allow(clippy::unnecessary_literal_unwrap)] fn unwrap_option() { let opt = Some(0); diff --git a/tests/ui/unwrap.stderr b/tests/ui/unwrap.stderr index d49bf2b3228..3796d942ff9 100644 --- a/tests/ui/unwrap.stderr +++ b/tests/ui/unwrap.stderr @@ -1,5 +1,5 @@ error: used `unwrap()` on an `Option` value - --> $DIR/unwrap.rs:5:13 + --> $DIR/unwrap.rs:6:13 | LL | let _ = opt.unwrap(); | ^^^^^^^^^^^^ @@ -8,7 +8,7 @@ LL | let _ = opt.unwrap(); = note: `-D clippy::unwrap-used` implied by `-D warnings` error: used `unwrap()` on a `Result` value - --> $DIR/unwrap.rs:10:13 + --> $DIR/unwrap.rs:11:13 | LL | let _ = res.unwrap(); | ^^^^^^^^^^^^ @@ -16,7 +16,7 @@ LL | let _ = res.unwrap(); = help: if you don't want to handle the `Err` case gracefully, consider using `expect()` to provide a better panic message error: used `unwrap_err()` on a `Result` value - --> $DIR/unwrap.rs:11:13 + --> $DIR/unwrap.rs:12:13 | LL | let _ = res.unwrap_err(); | ^^^^^^^^^^^^^^^^ diff --git a/tests/ui/unwrap_expect_used.rs b/tests/ui/unwrap_expect_used.rs index 9f27fef8249..7f57efc53c9 100644 --- a/tests/ui/unwrap_expect_used.rs +++ b/tests/ui/unwrap_expect_used.rs @@ -1,4 +1,5 @@ #![warn(clippy::unwrap_used, clippy::expect_used)] +#![allow(clippy::unnecessary_literal_unwrap)] trait OptionExt { type Item; diff --git a/tests/ui/unwrap_expect_used.stderr b/tests/ui/unwrap_expect_used.stderr index fe4ecef1145..1a551ab5ab8 100644 --- a/tests/ui/unwrap_expect_used.stderr +++ b/tests/ui/unwrap_expect_used.stderr @@ -1,5 +1,5 @@ error: used `unwrap()` on an `Option` value - --> $DIR/unwrap_expect_used.rs:23:5 + --> $DIR/unwrap_expect_used.rs:24:5 | LL | Some(3).unwrap(); | ^^^^^^^^^^^^^^^^ @@ -8,7 +8,7 @@ LL | Some(3).unwrap(); = note: `-D clippy::unwrap-used` implied by `-D warnings` error: used `expect()` on an `Option` value - --> $DIR/unwrap_expect_used.rs:24:5 + --> $DIR/unwrap_expect_used.rs:25:5 | LL | Some(3).expect("Hello world!"); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -17,7 +17,7 @@ LL | Some(3).expect("Hello world!"); = note: `-D clippy::expect-used` implied by `-D warnings` error: used `unwrap()` on a `Result` value - --> $DIR/unwrap_expect_used.rs:31:5 + --> $DIR/unwrap_expect_used.rs:32:5 | LL | a.unwrap(); | ^^^^^^^^^^ @@ -25,7 +25,7 @@ LL | a.unwrap(); = help: if this value is an `Err`, it will panic error: used `expect()` on a `Result` value - --> $DIR/unwrap_expect_used.rs:32:5 + --> $DIR/unwrap_expect_used.rs:33:5 | LL | a.expect("Hello world!"); | ^^^^^^^^^^^^^^^^^^^^^^^^ @@ -33,7 +33,7 @@ LL | a.expect("Hello world!"); = help: if this value is an `Err`, it will panic error: used `unwrap_err()` on a `Result` value - --> $DIR/unwrap_expect_used.rs:33:5 + --> $DIR/unwrap_expect_used.rs:34:5 | LL | a.unwrap_err(); | ^^^^^^^^^^^^^^ @@ -41,7 +41,7 @@ LL | a.unwrap_err(); = help: if this value is an `Ok`, it will panic error: used `expect_err()` on a `Result` value - --> $DIR/unwrap_expect_used.rs:34:5 + --> $DIR/unwrap_expect_used.rs:35:5 | LL | a.expect_err("Hello error!"); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/unwrap_or.rs b/tests/ui/unwrap_or.rs index a0c003f5b1e..5bea85e6692 100644 --- a/tests/ui/unwrap_or.rs +++ b/tests/ui/unwrap_or.rs @@ -1,4 +1,5 @@ #![warn(clippy::all, clippy::or_fun_call)] +#![allow(clippy::unnecessary_literal_unwrap)] fn main() { let s = Some(String::from("test string")).unwrap_or("Fail".to_string()).len(); diff --git a/tests/ui/unwrap_or.stderr b/tests/ui/unwrap_or.stderr index c3a7464fd47..cf720eaaf05 100644 --- a/tests/ui/unwrap_or.stderr +++ b/tests/ui/unwrap_or.stderr @@ -1,5 +1,5 @@ error: use of `unwrap_or` followed by a function call - --> $DIR/unwrap_or.rs:4:47 + --> $DIR/unwrap_or.rs:5:47 | LL | let s = Some(String::from("test string")).unwrap_or("Fail".to_string()).len(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_else(|| "Fail".to_string())` @@ -7,7 +7,7 @@ LL | let s = Some(String::from("test string")).unwrap_or("Fail".to_string()) = note: `-D clippy::or-fun-call` implied by `-D warnings` error: use of `unwrap_or` followed by a function call - --> $DIR/unwrap_or.rs:8:47 + --> $DIR/unwrap_or.rs:9:47 | LL | let s = Some(String::from("test string")).unwrap_or("Fail".to_string()).len(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_else(|| "Fail".to_string())` diff --git a/tests/ui/unwrap_or_else_default.fixed b/tests/ui/unwrap_or_else_default.fixed index 59a0ca3f192..08b89a18bbb 100644 --- a/tests/ui/unwrap_or_else_default.fixed +++ b/tests/ui/unwrap_or_else_default.fixed @@ -2,7 +2,7 @@ #![warn(clippy::unwrap_or_else_default)] #![allow(dead_code)] -#![allow(clippy::unnecessary_wraps)] +#![allow(clippy::unnecessary_wraps, clippy::unnecessary_literal_unwrap)] /// Checks implementation of the `UNWRAP_OR_ELSE_DEFAULT` lint. fn unwrap_or_else_default() { diff --git a/tests/ui/unwrap_or_else_default.rs b/tests/ui/unwrap_or_else_default.rs index 97cafa336ed..ad2a744908f 100644 --- a/tests/ui/unwrap_or_else_default.rs +++ b/tests/ui/unwrap_or_else_default.rs @@ -2,7 +2,7 @@ #![warn(clippy::unwrap_or_else_default)] #![allow(dead_code)] -#![allow(clippy::unnecessary_wraps)] +#![allow(clippy::unnecessary_wraps, clippy::unnecessary_literal_unwrap)] /// Checks implementation of the `UNWRAP_OR_ELSE_DEFAULT` lint. fn unwrap_or_else_default() { From 6702c7a7a6b47b3aed254e6b2f1575de234511c3 Mon Sep 17 00:00:00 2001 From: Centri3 <114838443+Centri3@users.noreply.github.com> Date: Mon, 12 Jun 2023 11:09:52 -0500 Subject: [PATCH 173/310] Add lint [`single_range_in_vec_init`] --- CHANGELOG.md | 1 + clippy_lints/src/declared_lints.rs | 1 + clippy_lints/src/lib.rs | 2 + clippy_lints/src/single_range_in_vec_init.rs | 153 +++++++++++++++++++ tests/ui/single_element_loop.fixed | 2 + tests/ui/single_element_loop.rs | 2 + tests/ui/single_element_loop.stderr | 14 +- tests/ui/single_range_in_vec_init.rs | 58 +++++++ tests/ui/single_range_in_vec_init.stderr | 145 ++++++++++++++++++ tests/ui/while_let_on_iterator.fixed | 1 + tests/ui/while_let_on_iterator.rs | 1 + tests/ui/while_let_on_iterator.stderr | 52 +++---- 12 files changed, 399 insertions(+), 33 deletions(-) create mode 100644 clippy_lints/src/single_range_in_vec_init.rs create mode 100644 tests/ui/single_range_in_vec_init.rs create mode 100644 tests/ui/single_range_in_vec_init.stderr diff --git a/CHANGELOG.md b/CHANGELOG.md index 85fddc97047..238c2584221 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5164,6 +5164,7 @@ Released 2018-09-13 [`single_element_loop`]: https://rust-lang.github.io/rust-clippy/master/index.html#single_element_loop [`single_match`]: https://rust-lang.github.io/rust-clippy/master/index.html#single_match [`single_match_else`]: https://rust-lang.github.io/rust-clippy/master/index.html#single_match_else +[`single_range_in_vec_init`]: https://rust-lang.github.io/rust-clippy/master/index.html#single_range_in_vec_init [`size_of_in_element_count`]: https://rust-lang.github.io/rust-clippy/master/index.html#size_of_in_element_count [`size_of_ref`]: https://rust-lang.github.io/rust-clippy/master/index.html#size_of_ref [`skip_while_next`]: https://rust-lang.github.io/rust-clippy/master/index.html#skip_while_next diff --git a/clippy_lints/src/declared_lints.rs b/clippy_lints/src/declared_lints.rs index 523faa302dc..ec127857ab2 100644 --- a/clippy_lints/src/declared_lints.rs +++ b/clippy_lints/src/declared_lints.rs @@ -569,6 +569,7 @@ pub(crate) static LINTS: &[&crate::LintInfo] = &[ crate::significant_drop_tightening::SIGNIFICANT_DROP_TIGHTENING_INFO, crate::single_char_lifetime_names::SINGLE_CHAR_LIFETIME_NAMES_INFO, crate::single_component_path_imports::SINGLE_COMPONENT_PATH_IMPORTS_INFO, + crate::single_range_in_vec_init::SINGLE_RANGE_IN_VEC_INIT_INFO, crate::size_of_in_element_count::SIZE_OF_IN_ELEMENT_COUNT_INFO, crate::size_of_ref::SIZE_OF_REF_INFO, crate::slow_vector_initialization::SLOW_VECTOR_INITIALIZATION_INFO, diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index 243d1fd8606..cf6499b9616 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -288,6 +288,7 @@ mod shadow; mod significant_drop_tightening; mod single_char_lifetime_names; mod single_component_path_imports; +mod single_range_in_vec_init; mod size_of_in_element_count; mod size_of_ref; mod slow_vector_initialization; @@ -1045,6 +1046,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: }); let stack_size_threshold = conf.stack_size_threshold; store.register_late_pass(move |_| Box::new(large_stack_frames::LargeStackFrames::new(stack_size_threshold))); + store.register_late_pass(|_| Box::new(single_range_in_vec_init::SingleRangeInVecInit)); // add lints here, do not remove this comment, it's used in `new_lint` } diff --git a/clippy_lints/src/single_range_in_vec_init.rs b/clippy_lints/src/single_range_in_vec_init.rs new file mode 100644 index 00000000000..2d3f18a62c0 --- /dev/null +++ b/clippy_lints/src/single_range_in_vec_init.rs @@ -0,0 +1,153 @@ +use clippy_utils::{ + diagnostics::span_lint_and_then, + get_trait_def_id, + higher::VecArgs, + macros::root_macro_call_first_node, + source::{snippet_opt, snippet_with_applicability}, + ty::implements_trait, +}; +use rustc_ast::{LitIntType, LitKind, UintTy}; +use rustc_errors::Applicability; +use rustc_hir::{Expr, ExprKind, LangItem, QPath}; +use rustc_lint::{LateContext, LateLintPass}; +use rustc_session::{declare_lint_pass, declare_tool_lint}; +use std::fmt::{self, Display, Formatter}; + +declare_clippy_lint! { + /// ### What it does + /// Checks for `Vec` or array initializations that contain only one range. + /// + /// ### Why is this bad? + /// This is almost always incorrect, as it will result in a `Vec` that has only element. Almost + /// always, the programmer intended for it to include all elements in the range or for the end + /// of the range to be the length instead. + /// + /// ### Example + /// ```rust + /// let x = [0..200]; + /// ``` + /// Use instead: + /// ```rust + /// // If it was intended to include every element in the range... + /// let x = (0..200).collect::>(); + /// // ...Or if 200 was meant to be the len + /// let x = [0; 200]; + /// ``` + #[clippy::version = "1.72.0"] + pub SINGLE_RANGE_IN_VEC_INIT, + suspicious, + "checks for initialization of `Vec` or arrays which consist of a single range" +} +declare_lint_pass!(SingleRangeInVecInit => [SINGLE_RANGE_IN_VEC_INIT]); + +enum SuggestedType { + Vec, + Array, +} + +impl SuggestedType { + fn starts_with(&self) -> &'static str { + if matches!(self, SuggestedType::Vec) { + "vec!" + } else { + "[" + } + } + + fn ends_with(&self) -> &'static str { + if matches!(self, SuggestedType::Vec) { "" } else { "]" } + } +} + +impl Display for SuggestedType { + fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { + if matches!(&self, SuggestedType::Vec) { + write!(f, "a `Vec`") + } else { + write!(f, "an array") + } + } +} + +impl LateLintPass<'_> for SingleRangeInVecInit { + fn check_expr<'tcx>(&mut self, cx: &LateContext<'tcx>, expr: &Expr<'tcx>) { + // inner_expr: `vec![0..200]` or `[0..200]` + // ^^^^^^ ^^^^^^^ + // span: `vec![0..200]` or `[0..200]` + // ^^^^^^^^^^^^ ^^^^^^^^ + // kind: What to print, an array or a `Vec` + let (inner_expr, span, kind) = if let ExprKind::Array([inner_expr]) = expr.kind + && !expr.span.from_expansion() + { + (inner_expr, expr.span, SuggestedType::Array) + } else if let Some(macro_call) = root_macro_call_first_node(cx, expr) + && let Some(VecArgs::Vec([expr])) = VecArgs::hir(cx, expr) + { + (expr, macro_call.span, SuggestedType::Vec) + } else { + return; + }; + + let ExprKind::Struct(QPath::LangItem(lang_item, ..), [start, end], None) = inner_expr.kind else { + return; + }; + + if matches!(lang_item, LangItem::Range) + && let ty = cx.typeck_results().expr_ty(start.expr) + && let Some(snippet) = snippet_opt(cx, span) + // `is_from_proc_macro` will skip any `vec![]`. Let's not! + && snippet.starts_with(kind.starts_with()) + && snippet.ends_with(kind.ends_with()) + { + let mut app = Applicability::MaybeIncorrect; + let start_snippet = snippet_with_applicability(cx, start.span, "...", &mut app); + let end_snippet = snippet_with_applicability(cx, end.span, "...", &mut app); + + let should_emit_every_value = if let Some(step_def_id) = get_trait_def_id(cx, &["core", "iter", "Step"]) + && implements_trait(cx, ty, step_def_id, &[]) + { + true + } else { + false + }; + let should_emit_of_len = if let Some(copy_def_id) = cx.tcx.lang_items().copy_trait() + && implements_trait(cx, ty, copy_def_id, &[]) + && let ExprKind::Lit(lit_kind) = end.expr.kind + && let LitKind::Int(.., suffix_type) = lit_kind.node + && let LitIntType::Unsigned(UintTy::Usize) | LitIntType::Unsuffixed = suffix_type + { + true + } else { + false + }; + + if should_emit_every_value || should_emit_of_len { + span_lint_and_then( + cx, + SINGLE_RANGE_IN_VEC_INIT, + span, + &format!("{kind} of `Range` that is only one element"), + |diag| { + if should_emit_every_value { + diag.span_suggestion( + span, + "if you wanted a `Vec` that contains every value in the range, try", + format!("({start_snippet}..{end_snippet}).collect::>()"), + app, + ); + } + + if should_emit_of_len { + diag.span_suggestion( + inner_expr.span, + format!("if you wanted {kind} of len {end_snippet}, try"), + format!("{start_snippet}; {end_snippet}"), + app, + ); + } + }, + ); + } + } + } +} diff --git a/tests/ui/single_element_loop.fixed b/tests/ui/single_element_loop.fixed index 1697a0cf29b..598f259415d 100644 --- a/tests/ui/single_element_loop.fixed +++ b/tests/ui/single_element_loop.fixed @@ -1,6 +1,8 @@ //@run-rustfix // Tests from for_loop.rs that don't have suggestions +#![allow(clippy::single_range_in_vec_init)] + #[warn(clippy::single_element_loop)] fn main() { let item1 = 2; diff --git a/tests/ui/single_element_loop.rs b/tests/ui/single_element_loop.rs index 860424f42dd..3fc461735a4 100644 --- a/tests/ui/single_element_loop.rs +++ b/tests/ui/single_element_loop.rs @@ -1,6 +1,8 @@ //@run-rustfix // Tests from for_loop.rs that don't have suggestions +#![allow(clippy::single_range_in_vec_init)] + #[warn(clippy::single_element_loop)] fn main() { let item1 = 2; diff --git a/tests/ui/single_element_loop.stderr b/tests/ui/single_element_loop.stderr index 14437a59745..c40c6198945 100644 --- a/tests/ui/single_element_loop.stderr +++ b/tests/ui/single_element_loop.stderr @@ -1,5 +1,5 @@ error: for loop over a single element - --> $DIR/single_element_loop.rs:7:5 + --> $DIR/single_element_loop.rs:9:5 | LL | / for item in &[item1] { LL | | dbg!(item); @@ -16,7 +16,7 @@ LL + } | error: for loop over a single element - --> $DIR/single_element_loop.rs:11:5 + --> $DIR/single_element_loop.rs:13:5 | LL | / for item in [item1].iter() { LL | | dbg!(item); @@ -32,7 +32,7 @@ LL + } | error: for loop over a single element - --> $DIR/single_element_loop.rs:15:5 + --> $DIR/single_element_loop.rs:17:5 | LL | / for item in &[0..5] { LL | | dbg!(item); @@ -48,7 +48,7 @@ LL + } | error: for loop over a single element - --> $DIR/single_element_loop.rs:19:5 + --> $DIR/single_element_loop.rs:21:5 | LL | / for item in [0..5].iter_mut() { LL | | dbg!(item); @@ -64,7 +64,7 @@ LL + } | error: for loop over a single element - --> $DIR/single_element_loop.rs:23:5 + --> $DIR/single_element_loop.rs:25:5 | LL | / for item in [0..5] { LL | | dbg!(item); @@ -80,7 +80,7 @@ LL + } | error: for loop over a single element - --> $DIR/single_element_loop.rs:27:5 + --> $DIR/single_element_loop.rs:29:5 | LL | / for item in [0..5].into_iter() { LL | | dbg!(item); @@ -96,7 +96,7 @@ LL + } | error: for loop over a single element - --> $DIR/single_element_loop.rs:46:5 + --> $DIR/single_element_loop.rs:48:5 | LL | / for _ in [42] { LL | | let _f = |n: u32| { diff --git a/tests/ui/single_range_in_vec_init.rs b/tests/ui/single_range_in_vec_init.rs new file mode 100644 index 00000000000..abf784e0f0e --- /dev/null +++ b/tests/ui/single_range_in_vec_init.rs @@ -0,0 +1,58 @@ +//@aux-build:proc_macros.rs +#![allow(clippy::no_effect, clippy::useless_vec, unused)] +#![warn(clippy::single_range_in_vec_init)] +#![feature(generic_arg_infer)] + +#[macro_use] +extern crate proc_macros; + +macro_rules! a { + () => { + vec![0..200]; + }; +} + +fn awa(start: T, end: T) { + [start..end]; +} + +fn awa_vec(start: T, end: T) { + vec![start..end]; +} + +fn main() { + // Lint + [0..200]; + vec![0..200]; + [0u8..200]; + [0usize..200]; + [0..200usize]; + vec![0u8..200]; + vec![0usize..200]; + vec![0..200usize]; + // Only suggest collect + [0..200isize]; + vec![0..200isize]; + // Do not lint + [0..200, 0..100]; + vec![0..200, 0..100]; + [0.0..200.0]; + vec![0.0..200.0]; + // `Copy` is not implemented for `Range`, so this doesn't matter + // [0..200; 2]; + // [vec!0..200; 2]; + + // Unfortunately skips any macros + a!(); + + // Skip external macros and procedural macros + external! { + [0..200]; + vec![0..200]; + } + with_span! { + span + [0..200]; + vec![0..200]; + } +} diff --git a/tests/ui/single_range_in_vec_init.stderr b/tests/ui/single_range_in_vec_init.stderr new file mode 100644 index 00000000000..fc03b2205e2 --- /dev/null +++ b/tests/ui/single_range_in_vec_init.stderr @@ -0,0 +1,145 @@ +error: an array of `Range` that is only one element + --> $DIR/single_range_in_vec_init.rs:25:5 + | +LL | [0..200]; + | ^^^^^^^^ + | + = note: `-D clippy::single-range-in-vec-init` implied by `-D warnings` +help: if you wanted a `Vec` that contains every value in the range, try + | +LL | (0..200).collect::>(); + | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +help: if you wanted an array of len 200, try + | +LL | [0; 200]; + | ~~~~~~ + +error: a `Vec` of `Range` that is only one element + --> $DIR/single_range_in_vec_init.rs:26:5 + | +LL | vec![0..200]; + | ^^^^^^^^^^^^ + | +help: if you wanted a `Vec` that contains every value in the range, try + | +LL | (0..200).collect::>(); + | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +help: if you wanted a `Vec` of len 200, try + | +LL | vec![0; 200]; + | ~~~~~~ + +error: an array of `Range` that is only one element + --> $DIR/single_range_in_vec_init.rs:27:5 + | +LL | [0u8..200]; + | ^^^^^^^^^^ + | +help: if you wanted a `Vec` that contains every value in the range, try + | +LL | (0u8..200).collect::>(); + | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +help: if you wanted an array of len 200, try + | +LL | [0u8; 200]; + | ~~~~~~~~ + +error: an array of `Range` that is only one element + --> $DIR/single_range_in_vec_init.rs:28:5 + | +LL | [0usize..200]; + | ^^^^^^^^^^^^^ + | +help: if you wanted a `Vec` that contains every value in the range, try + | +LL | (0usize..200).collect::>(); + | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +help: if you wanted an array of len 200, try + | +LL | [0usize; 200]; + | ~~~~~~~~~~~ + +error: an array of `Range` that is only one element + --> $DIR/single_range_in_vec_init.rs:29:5 + | +LL | [0..200usize]; + | ^^^^^^^^^^^^^ + | +help: if you wanted a `Vec` that contains every value in the range, try + | +LL | (0..200usize).collect::>(); + | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +help: if you wanted an array of len 200usize, try + | +LL | [0; 200usize]; + | ~~~~~~~~~~~ + +error: a `Vec` of `Range` that is only one element + --> $DIR/single_range_in_vec_init.rs:30:5 + | +LL | vec![0u8..200]; + | ^^^^^^^^^^^^^^ + | +help: if you wanted a `Vec` that contains every value in the range, try + | +LL | (0u8..200).collect::>(); + | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +help: if you wanted a `Vec` of len 200, try + | +LL | vec![0u8; 200]; + | ~~~~~~~~ + +error: a `Vec` of `Range` that is only one element + --> $DIR/single_range_in_vec_init.rs:31:5 + | +LL | vec![0usize..200]; + | ^^^^^^^^^^^^^^^^^ + | +help: if you wanted a `Vec` that contains every value in the range, try + | +LL | (0usize..200).collect::>(); + | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +help: if you wanted a `Vec` of len 200, try + | +LL | vec![0usize; 200]; + | ~~~~~~~~~~~ + +error: a `Vec` of `Range` that is only one element + --> $DIR/single_range_in_vec_init.rs:32:5 + | +LL | vec![0..200usize]; + | ^^^^^^^^^^^^^^^^^ + | +help: if you wanted a `Vec` that contains every value in the range, try + | +LL | (0..200usize).collect::>(); + | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +help: if you wanted a `Vec` of len 200usize, try + | +LL | vec![0; 200usize]; + | ~~~~~~~~~~~ + +error: an array of `Range` that is only one element + --> $DIR/single_range_in_vec_init.rs:34:5 + | +LL | [0..200isize]; + | ^^^^^^^^^^^^^ + | +help: if you wanted a `Vec` that contains every value in the range, try + | +LL | (0..200isize).collect::>(); + | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +error: a `Vec` of `Range` that is only one element + --> $DIR/single_range_in_vec_init.rs:35:5 + | +LL | vec![0..200isize]; + | ^^^^^^^^^^^^^^^^^ + | +help: if you wanted a `Vec` that contains every value in the range, try + | +LL | (0..200isize).collect::>(); + | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +error: aborting due to 10 previous errors + diff --git a/tests/ui/while_let_on_iterator.fixed b/tests/ui/while_let_on_iterator.fixed index 11f0de07c62..41a380ab8f6 100644 --- a/tests/ui/while_let_on_iterator.fixed +++ b/tests/ui/while_let_on_iterator.fixed @@ -6,6 +6,7 @@ clippy::manual_find, clippy::never_loop, clippy::redundant_closure_call, + clippy::single_range_in_vec_init, clippy::uninlined_format_args, clippy::useless_vec )] diff --git a/tests/ui/while_let_on_iterator.rs b/tests/ui/while_let_on_iterator.rs index e54575dd3b4..4c6433880b6 100644 --- a/tests/ui/while_let_on_iterator.rs +++ b/tests/ui/while_let_on_iterator.rs @@ -6,6 +6,7 @@ clippy::manual_find, clippy::never_loop, clippy::redundant_closure_call, + clippy::single_range_in_vec_init, clippy::uninlined_format_args, clippy::useless_vec )] diff --git a/tests/ui/while_let_on_iterator.stderr b/tests/ui/while_let_on_iterator.stderr index f8a66f2ad3e..3236765e1db 100644 --- a/tests/ui/while_let_on_iterator.stderr +++ b/tests/ui/while_let_on_iterator.stderr @@ -1,5 +1,5 @@ error: this loop could be written as a `for` loop - --> $DIR/while_let_on_iterator.rs:15:5 + --> $DIR/while_let_on_iterator.rs:16:5 | LL | while let Option::Some(x) = iter.next() { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `for x in iter` @@ -7,151 +7,151 @@ LL | while let Option::Some(x) = iter.next() { = note: `-D clippy::while-let-on-iterator` implied by `-D warnings` error: this loop could be written as a `for` loop - --> $DIR/while_let_on_iterator.rs:20:5 + --> $DIR/while_let_on_iterator.rs:21:5 | LL | while let Some(x) = iter.next() { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `for x in iter` error: this loop could be written as a `for` loop - --> $DIR/while_let_on_iterator.rs:25:5 + --> $DIR/while_let_on_iterator.rs:26:5 | LL | while let Some(_) = iter.next() {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `for _ in iter` error: this loop could be written as a `for` loop - --> $DIR/while_let_on_iterator.rs:101:9 + --> $DIR/while_let_on_iterator.rs:102:9 | LL | while let Some([..]) = it.next() {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `for [..] in it` error: this loop could be written as a `for` loop - --> $DIR/while_let_on_iterator.rs:108:9 + --> $DIR/while_let_on_iterator.rs:109:9 | LL | while let Some([_x]) = it.next() {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `for [_x] in it` error: this loop could be written as a `for` loop - --> $DIR/while_let_on_iterator.rs:121:9 + --> $DIR/while_let_on_iterator.rs:122:9 | LL | while let Some(x @ [_]) = it.next() { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `for x @ [_] in it` error: this loop could be written as a `for` loop - --> $DIR/while_let_on_iterator.rs:141:9 + --> $DIR/while_let_on_iterator.rs:142:9 | LL | while let Some(_) = y.next() { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `for _ in y` error: this loop could be written as a `for` loop - --> $DIR/while_let_on_iterator.rs:198:9 + --> $DIR/while_let_on_iterator.rs:199:9 | LL | while let Some(m) = it.next() { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `for m in it.by_ref()` error: this loop could be written as a `for` loop - --> $DIR/while_let_on_iterator.rs:209:5 + --> $DIR/while_let_on_iterator.rs:210:5 | LL | while let Some(n) = it.next() { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `for n in it` error: this loop could be written as a `for` loop - --> $DIR/while_let_on_iterator.rs:211:9 + --> $DIR/while_let_on_iterator.rs:212:9 | LL | while let Some(m) = it.next() { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `for m in it` error: this loop could be written as a `for` loop - --> $DIR/while_let_on_iterator.rs:220:9 + --> $DIR/while_let_on_iterator.rs:221:9 | LL | while let Some(m) = it.next() { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `for m in it` error: this loop could be written as a `for` loop - --> $DIR/while_let_on_iterator.rs:229:9 + --> $DIR/while_let_on_iterator.rs:230:9 | LL | while let Some(m) = it.next() { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `for m in it.by_ref()` error: this loop could be written as a `for` loop - --> $DIR/while_let_on_iterator.rs:246:9 + --> $DIR/while_let_on_iterator.rs:247:9 | LL | while let Some(m) = it.next() { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `for m in it.by_ref()` error: this loop could be written as a `for` loop - --> $DIR/while_let_on_iterator.rs:261:13 + --> $DIR/while_let_on_iterator.rs:262:13 | LL | while let Some(i) = self.0.next() { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `for i in self.0.by_ref()` error: this loop could be written as a `for` loop - --> $DIR/while_let_on_iterator.rs:293:13 + --> $DIR/while_let_on_iterator.rs:294:13 | LL | while let Some(i) = self.0.0.0.next() { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `for i in self.0.0.0.by_ref()` error: this loop could be written as a `for` loop - --> $DIR/while_let_on_iterator.rs:322:5 + --> $DIR/while_let_on_iterator.rs:323:5 | LL | while let Some(n) = it.next() { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `for n in it.by_ref()` error: this loop could be written as a `for` loop - --> $DIR/while_let_on_iterator.rs:334:9 + --> $DIR/while_let_on_iterator.rs:335:9 | LL | while let Some(x) = it.next() { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `for x in it.by_ref()` error: this loop could be written as a `for` loop - --> $DIR/while_let_on_iterator.rs:348:5 + --> $DIR/while_let_on_iterator.rs:349:5 | LL | while let Some(x) = it.next() { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `for x in it.by_ref()` error: this loop could be written as a `for` loop - --> $DIR/while_let_on_iterator.rs:359:5 + --> $DIR/while_let_on_iterator.rs:360:5 | LL | while let Some(x) = it.0.next() { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `for x in it.0.by_ref()` error: this loop could be written as a `for` loop - --> $DIR/while_let_on_iterator.rs:394:5 + --> $DIR/while_let_on_iterator.rs:395:5 | LL | while let Some(x) = s.x.next() { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `for x in s.x.by_ref()` error: this loop could be written as a `for` loop - --> $DIR/while_let_on_iterator.rs:401:5 + --> $DIR/while_let_on_iterator.rs:402:5 | LL | while let Some(x) = x[0].next() { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `for x in x[0].by_ref()` error: this loop could be written as a `for` loop - --> $DIR/while_let_on_iterator.rs:409:9 + --> $DIR/while_let_on_iterator.rs:410:9 | LL | while let Some(x) = it.next() { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `for x in it` error: this loop could be written as a `for` loop - --> $DIR/while_let_on_iterator.rs:419:9 + --> $DIR/while_let_on_iterator.rs:420:9 | LL | while let Some(x) = it.next() { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `for x in it` error: this loop could be written as a `for` loop - --> $DIR/while_let_on_iterator.rs:429:9 + --> $DIR/while_let_on_iterator.rs:430:9 | LL | while let Some(x) = it.next() { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `for x in it.by_ref()` error: this loop could be written as a `for` loop - --> $DIR/while_let_on_iterator.rs:439:9 + --> $DIR/while_let_on_iterator.rs:440:9 | LL | while let Some(x) = it.next() { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `for x in it` error: this loop could be written as a `for` loop - --> $DIR/while_let_on_iterator.rs:449:5 + --> $DIR/while_let_on_iterator.rs:450:5 | LL | while let Some(..) = it.next() { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `for _ in it` From 357e80ea0d19d7081b0a1f91b52053c49ed93bf5 Mon Sep 17 00:00:00 2001 From: Centri3 <114838443+Centri3@users.noreply.github.com> Date: Tue, 13 Jun 2023 06:51:56 -0500 Subject: [PATCH 174/310] Ignore more type aliases in `unnecessary_cast` --- clippy_lints/src/casts/unnecessary_cast.rs | 71 +++++++++++++++++++- tests/ui/auxiliary/extern_fake_libc.rs | 10 +++ tests/ui/unnecessary_cast.fixed | 27 +++++++- tests/ui/unnecessary_cast.rs | 27 +++++++- tests/ui/unnecessary_cast.stderr | 76 +++++++++++----------- 5 files changed, 166 insertions(+), 45 deletions(-) create mode 100644 tests/ui/auxiliary/extern_fake_libc.rs diff --git a/clippy_lints/src/casts/unnecessary_cast.rs b/clippy_lints/src/casts/unnecessary_cast.rs index 41055c168fc..71cf2aea0f8 100644 --- a/clippy_lints/src/casts/unnecessary_cast.rs +++ b/clippy_lints/src/casts/unnecessary_cast.rs @@ -1,15 +1,17 @@ use clippy_utils::diagnostics::span_lint_and_sugg; use clippy_utils::numeric_literal::NumericLiteral; use clippy_utils::source::snippet_opt; -use clippy_utils::{get_parent_expr, is_hir_ty_cfg_dependant, is_ty_alias, path_to_local}; +use clippy_utils::visitors::{for_each_expr, Visitable}; +use clippy_utils::{get_parent_expr, get_parent_node, is_hir_ty_cfg_dependant, is_ty_alias, path_to_local}; use if_chain::if_chain; use rustc_ast::{LitFloatType, LitIntType, LitKind}; use rustc_errors::Applicability; -use rustc_hir::def::Res; +use rustc_hir::def::{DefKind, Res}; use rustc_hir::{Expr, ExprKind, Lit, Node, Path, QPath, TyKind, UnOp}; use rustc_lint::{LateContext, LintContext}; use rustc_middle::lint::in_external_macro; use rustc_middle::ty::{self, FloatTy, InferTy, Ty}; +use std::ops::ControlFlow; use super::UNNECESSARY_CAST; @@ -59,7 +61,7 @@ pub(super) fn check<'tcx>( } } - // skip cast of local to type alias + // skip cast of local that is a type alias if let ExprKind::Cast(inner, ..) = expr.kind && let ExprKind::Path(qpath) = inner.kind && let QPath::Resolved(None, Path { res, .. }) = qpath @@ -83,6 +85,11 @@ pub(super) fn check<'tcx>( } } + // skip cast of fn call that returns type alias + if let ExprKind::Cast(inner, ..) = expr.kind && is_cast_from_ty_alias(cx, inner, cast_from) { + return false; + } + // skip cast to non-primitive type if_chain! { if let ExprKind::Cast(_, cast_to) = expr.kind; @@ -223,3 +230,61 @@ fn fp_ty_mantissa_nbits(typ: Ty<'_>) -> u32 { _ => 0, } } + +/// Finds whether an `Expr` returns a type alias. +/// +/// TODO: Maybe we should move this to `clippy_utils` so others won't need to go down this dark, +/// dark path reimplementing this (or something similar). +fn is_cast_from_ty_alias<'tcx>(cx: &LateContext<'tcx>, expr: impl Visitable<'tcx>, cast_from: Ty<'tcx>) -> bool { + for_each_expr(expr, |expr| { + // Calls are a `Path`, and usage of locals are a `Path`. So, this checks + // - call() as i32 + // - local as i32 + if let ExprKind::Path(qpath) = expr.kind { + let res = cx.qpath_res(&qpath, expr.hir_id); + // Function call + if let Res::Def(DefKind::Fn, def_id) = res { + let Some(snippet) = snippet_opt(cx, cx.tcx.def_span(def_id)) else { + return ControlFlow::Continue(()); + }; + // This is the worst part of this entire function. This is the only way I know of to + // check whether a function returns a type alias. Sure, you can get the return type + // from a function in the current crate as an hir ty, but how do you get it for + // external functions?? Simple: It's impossible. So, we check whether a part of the + // function's declaration snippet is exactly equal to the `Ty`. That way, we can + // see whether it's a type alias. + // + // Will this work for more complex types? Probably not! + if !snippet + .split("->") + .skip(0) + .map(|s| { + s.trim() == cast_from.to_string() + || s.split("where").any(|ty| ty.trim() == cast_from.to_string()) + }) + .any(|a| a) + { + return ControlFlow::Break(()); + } + // Local usage + } else if let Res::Local(hir_id) = res + && let Some(parent) = get_parent_node(cx.tcx, hir_id) + && let Node::Local(l) = parent + { + if let Some(e) = l.init && is_cast_from_ty_alias(cx, e, cast_from) { + return ControlFlow::Break::<()>(()); + } + + if let Some(ty) = l.ty + && let TyKind::Path(qpath) = ty.kind + && is_ty_alias(&qpath) + { + return ControlFlow::Break::<()>(()); + } + } + } + + ControlFlow::Continue(()) + }) + .is_some() +} diff --git a/tests/ui/auxiliary/extern_fake_libc.rs b/tests/ui/auxiliary/extern_fake_libc.rs new file mode 100644 index 00000000000..eb5a5d2b836 --- /dev/null +++ b/tests/ui/auxiliary/extern_fake_libc.rs @@ -0,0 +1,10 @@ +#![allow(nonstandard_style)] +#![allow(clippy::missing_safety_doc, unused)] + +type pid_t = i32; +pub unsafe fn getpid() -> pid_t { + pid_t::from(0) +} +pub fn getpid_SAFE_TRUTH() -> pid_t { + unsafe { getpid() } +} diff --git a/tests/ui/unnecessary_cast.fixed b/tests/ui/unnecessary_cast.fixed index f56cee3a364..8efd44baf59 100644 --- a/tests/ui/unnecessary_cast.fixed +++ b/tests/ui/unnecessary_cast.fixed @@ -1,13 +1,17 @@ //@run-rustfix +//@aux-build:extern_fake_libc.rs #![warn(clippy::unnecessary_cast)] #![allow( - unused, clippy::borrow_as_ptr, clippy::no_effect, clippy::nonstandard_macro_braces, - clippy::unnecessary_operation + clippy::unnecessary_operation, + nonstandard_style, + unused )] +extern crate extern_fake_libc; + type PtrConstU8 = *const u8; type PtrMutU8 = *mut u8; @@ -19,6 +23,21 @@ fn uwu(ptr: *const T) -> *const U { ptr as *const U } +mod fake_libc { + type pid_t = i32; + pub unsafe fn getpid() -> pid_t { + pid_t::from(0) + } + // Make sure a where clause does not break it + pub fn getpid_SAFE_TRUTH(t: &T) -> pid_t + where + T: Clone, + { + t; + unsafe { getpid() } + } +} + #[rustfmt::skip] fn main() { // Test cast_unnecessary @@ -82,6 +101,10 @@ fn main() { // or from let x: I32Alias = 1; let y = x as u64; + fake_libc::getpid_SAFE_TRUTH(&0u32) as i32; + extern_fake_libc::getpid_SAFE_TRUTH() as i32; + let pid = unsafe { fake_libc::getpid() }; + pid as i32; let i8_ptr: *const i8 = &1; let u8_ptr: *const u8 = &1; diff --git a/tests/ui/unnecessary_cast.rs b/tests/ui/unnecessary_cast.rs index b4623df6909..c7723ef51f9 100644 --- a/tests/ui/unnecessary_cast.rs +++ b/tests/ui/unnecessary_cast.rs @@ -1,13 +1,17 @@ //@run-rustfix +//@aux-build:extern_fake_libc.rs #![warn(clippy::unnecessary_cast)] #![allow( - unused, clippy::borrow_as_ptr, clippy::no_effect, clippy::nonstandard_macro_braces, - clippy::unnecessary_operation + clippy::unnecessary_operation, + nonstandard_style, + unused )] +extern crate extern_fake_libc; + type PtrConstU8 = *const u8; type PtrMutU8 = *mut u8; @@ -19,6 +23,21 @@ fn uwu(ptr: *const T) -> *const U { ptr as *const U } +mod fake_libc { + type pid_t = i32; + pub unsafe fn getpid() -> pid_t { + pid_t::from(0) + } + // Make sure a where clause does not break it + pub fn getpid_SAFE_TRUTH(t: &T) -> pid_t + where + T: Clone, + { + t; + unsafe { getpid() } + } +} + #[rustfmt::skip] fn main() { // Test cast_unnecessary @@ -82,6 +101,10 @@ fn main() { // or from let x: I32Alias = 1; let y = x as u64; + fake_libc::getpid_SAFE_TRUTH(&0u32) as i32; + extern_fake_libc::getpid_SAFE_TRUTH() as i32; + let pid = unsafe { fake_libc::getpid() }; + pid as i32; let i8_ptr: *const i8 = &1; let u8_ptr: *const u8 = &1; diff --git a/tests/ui/unnecessary_cast.stderr b/tests/ui/unnecessary_cast.stderr index 618fbd4faaf..f0443556fb4 100644 --- a/tests/ui/unnecessary_cast.stderr +++ b/tests/ui/unnecessary_cast.stderr @@ -1,5 +1,5 @@ error: casting raw pointers to the same type and constness is unnecessary (`*const T` -> `*const T`) - --> $DIR/unnecessary_cast.rs:15:5 + --> $DIR/unnecessary_cast.rs:19:5 | LL | ptr as *const T | ^^^^^^^^^^^^^^^ help: try: `ptr` @@ -7,223 +7,223 @@ LL | ptr as *const T = note: `-D clippy::unnecessary-cast` implied by `-D warnings` error: casting integer literal to `i32` is unnecessary - --> $DIR/unnecessary_cast.rs:25:5 + --> $DIR/unnecessary_cast.rs:44:5 | LL | 1i32 as i32; | ^^^^^^^^^^^ help: try: `1_i32` error: casting float literal to `f32` is unnecessary - --> $DIR/unnecessary_cast.rs:26:5 + --> $DIR/unnecessary_cast.rs:45:5 | LL | 1f32 as f32; | ^^^^^^^^^^^ help: try: `1_f32` error: casting to the same type is unnecessary (`bool` -> `bool`) - --> $DIR/unnecessary_cast.rs:27:5 + --> $DIR/unnecessary_cast.rs:46:5 | LL | false as bool; | ^^^^^^^^^^^^^ help: try: `false` error: casting integer literal to `i32` is unnecessary - --> $DIR/unnecessary_cast.rs:30:5 + --> $DIR/unnecessary_cast.rs:49:5 | LL | -1_i32 as i32; | ^^^^^^^^^^^^^ help: try: `-1_i32` error: casting integer literal to `i32` is unnecessary - --> $DIR/unnecessary_cast.rs:31:5 + --> $DIR/unnecessary_cast.rs:50:5 | LL | - 1_i32 as i32; | ^^^^^^^^^^^^^^ help: try: `- 1_i32` error: casting float literal to `f32` is unnecessary - --> $DIR/unnecessary_cast.rs:32:5 + --> $DIR/unnecessary_cast.rs:51:5 | LL | -1f32 as f32; | ^^^^^^^^^^^^ help: try: `-1_f32` error: casting integer literal to `i32` is unnecessary - --> $DIR/unnecessary_cast.rs:33:5 + --> $DIR/unnecessary_cast.rs:52:5 | LL | 1_i32 as i32; | ^^^^^^^^^^^^ help: try: `1_i32` error: casting float literal to `f32` is unnecessary - --> $DIR/unnecessary_cast.rs:34:5 + --> $DIR/unnecessary_cast.rs:53:5 | LL | 1_f32 as f32; | ^^^^^^^^^^^^ help: try: `1_f32` error: casting raw pointers to the same type and constness is unnecessary (`*const u8` -> `*const u8`) - --> $DIR/unnecessary_cast.rs:36:22 + --> $DIR/unnecessary_cast.rs:55:22 | LL | let _: *mut u8 = [1u8, 2].as_ptr() as *const u8 as *mut u8; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `[1u8, 2].as_ptr()` error: casting raw pointers to the same type and constness is unnecessary (`*const u8` -> `*const u8`) - --> $DIR/unnecessary_cast.rs:38:5 + --> $DIR/unnecessary_cast.rs:57:5 | LL | [1u8, 2].as_ptr() as *const u8; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `[1u8, 2].as_ptr()` error: casting raw pointers to the same type and constness is unnecessary (`*mut u8` -> `*mut u8`) - --> $DIR/unnecessary_cast.rs:40:5 + --> $DIR/unnecessary_cast.rs:59:5 | LL | [1u8, 2].as_mut_ptr() as *mut u8; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `[1u8, 2].as_mut_ptr()` error: casting raw pointers to the same type and constness is unnecessary (`*const u32` -> `*const u32`) - --> $DIR/unnecessary_cast.rs:51:5 + --> $DIR/unnecessary_cast.rs:70:5 | LL | owo::([1u32].as_ptr()) as *const u32; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `owo::([1u32].as_ptr())` error: casting raw pointers to the same type and constness is unnecessary (`*const u8` -> `*const u8`) - --> $DIR/unnecessary_cast.rs:52:5 + --> $DIR/unnecessary_cast.rs:71:5 | LL | uwu::([1u32].as_ptr()) as *const u8; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `uwu::([1u32].as_ptr())` error: casting raw pointers to the same type and constness is unnecessary (`*const u32` -> `*const u32`) - --> $DIR/unnecessary_cast.rs:54:5 + --> $DIR/unnecessary_cast.rs:73:5 | LL | uwu::([1u32].as_ptr()) as *const u32; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `uwu::([1u32].as_ptr())` error: casting integer literal to `f32` is unnecessary - --> $DIR/unnecessary_cast.rs:116:9 + --> $DIR/unnecessary_cast.rs:139:9 | LL | 100 as f32; | ^^^^^^^^^^ help: try: `100_f32` error: casting integer literal to `f64` is unnecessary - --> $DIR/unnecessary_cast.rs:117:9 + --> $DIR/unnecessary_cast.rs:140:9 | LL | 100 as f64; | ^^^^^^^^^^ help: try: `100_f64` error: casting integer literal to `f64` is unnecessary - --> $DIR/unnecessary_cast.rs:118:9 + --> $DIR/unnecessary_cast.rs:141:9 | LL | 100_i32 as f64; | ^^^^^^^^^^^^^^ help: try: `100_f64` error: casting integer literal to `f32` is unnecessary - --> $DIR/unnecessary_cast.rs:119:17 + --> $DIR/unnecessary_cast.rs:142:17 | LL | let _ = -100 as f32; | ^^^^^^^^^^^ help: try: `-100_f32` error: casting integer literal to `f64` is unnecessary - --> $DIR/unnecessary_cast.rs:120:17 + --> $DIR/unnecessary_cast.rs:143:17 | LL | let _ = -100 as f64; | ^^^^^^^^^^^ help: try: `-100_f64` error: casting integer literal to `f64` is unnecessary - --> $DIR/unnecessary_cast.rs:121:17 + --> $DIR/unnecessary_cast.rs:144:17 | LL | let _ = -100_i32 as f64; | ^^^^^^^^^^^^^^^ help: try: `-100_f64` error: casting float literal to `f32` is unnecessary - --> $DIR/unnecessary_cast.rs:122:9 + --> $DIR/unnecessary_cast.rs:145:9 | LL | 100. as f32; | ^^^^^^^^^^^ help: try: `100_f32` error: casting float literal to `f64` is unnecessary - --> $DIR/unnecessary_cast.rs:123:9 + --> $DIR/unnecessary_cast.rs:146:9 | LL | 100. as f64; | ^^^^^^^^^^^ help: try: `100_f64` error: casting integer literal to `u32` is unnecessary - --> $DIR/unnecessary_cast.rs:135:9 + --> $DIR/unnecessary_cast.rs:158:9 | LL | 1 as u32; | ^^^^^^^^ help: try: `1_u32` error: casting integer literal to `i32` is unnecessary - --> $DIR/unnecessary_cast.rs:136:9 + --> $DIR/unnecessary_cast.rs:159:9 | LL | 0x10 as i32; | ^^^^^^^^^^^ help: try: `0x10_i32` error: casting integer literal to `usize` is unnecessary - --> $DIR/unnecessary_cast.rs:137:9 + --> $DIR/unnecessary_cast.rs:160:9 | LL | 0b10 as usize; | ^^^^^^^^^^^^^ help: try: `0b10_usize` error: casting integer literal to `u16` is unnecessary - --> $DIR/unnecessary_cast.rs:138:9 + --> $DIR/unnecessary_cast.rs:161:9 | LL | 0o73 as u16; | ^^^^^^^^^^^ help: try: `0o73_u16` error: casting integer literal to `u32` is unnecessary - --> $DIR/unnecessary_cast.rs:139:9 + --> $DIR/unnecessary_cast.rs:162:9 | LL | 1_000_000_000 as u32; | ^^^^^^^^^^^^^^^^^^^^ help: try: `1_000_000_000_u32` error: casting float literal to `f64` is unnecessary - --> $DIR/unnecessary_cast.rs:141:9 + --> $DIR/unnecessary_cast.rs:164:9 | LL | 1.0 as f64; | ^^^^^^^^^^ help: try: `1.0_f64` error: casting float literal to `f32` is unnecessary - --> $DIR/unnecessary_cast.rs:142:9 + --> $DIR/unnecessary_cast.rs:165:9 | LL | 0.5 as f32; | ^^^^^^^^^^ help: try: `0.5_f32` error: casting integer literal to `i32` is unnecessary - --> $DIR/unnecessary_cast.rs:146:17 + --> $DIR/unnecessary_cast.rs:169:17 | LL | let _ = -1 as i32; | ^^^^^^^^^ help: try: `-1_i32` error: casting float literal to `f32` is unnecessary - --> $DIR/unnecessary_cast.rs:147:17 + --> $DIR/unnecessary_cast.rs:170:17 | LL | let _ = -1.0 as f32; | ^^^^^^^^^^^ help: try: `-1.0_f32` error: casting to the same type is unnecessary (`i32` -> `i32`) - --> $DIR/unnecessary_cast.rs:153:18 + --> $DIR/unnecessary_cast.rs:176:18 | LL | let _ = &(x as i32); | ^^^^^^^^^^ help: try: `{ x }` error: casting integer literal to `i32` is unnecessary - --> $DIR/unnecessary_cast.rs:159:22 + --> $DIR/unnecessary_cast.rs:182:22 | LL | let _: i32 = -(1) as i32; | ^^^^^^^^^^^ help: try: `-1_i32` error: casting integer literal to `i64` is unnecessary - --> $DIR/unnecessary_cast.rs:161:22 + --> $DIR/unnecessary_cast.rs:184:22 | LL | let _: i64 = -(1) as i64; | ^^^^^^^^^^^ help: try: `-1_i64` error: casting float literal to `f64` is unnecessary - --> $DIR/unnecessary_cast.rs:168:22 + --> $DIR/unnecessary_cast.rs:191:22 | LL | let _: f64 = (-8.0 as f64).exp(); | ^^^^^^^^^^^^^ help: try: `(-8.0_f64)` error: casting float literal to `f64` is unnecessary - --> $DIR/unnecessary_cast.rs:170:23 + --> $DIR/unnecessary_cast.rs:193:23 | LL | let _: f64 = -(8.0 as f64).exp(); // should suggest `-8.0_f64.exp()` here not to change code behavior | ^^^^^^^^^^^^ help: try: `8.0_f64` error: casting to the same type is unnecessary (`f32` -> `f32`) - --> $DIR/unnecessary_cast.rs:178:20 + --> $DIR/unnecessary_cast.rs:201:20 | LL | let _num = foo() as f32; | ^^^^^^^^^^^^ help: try: `foo()` From d5b2f113403313a3f79e30832cd029bebfd93958 Mon Sep 17 00:00:00 2001 From: blyxyas Date: Sun, 11 Jun 2023 21:55:49 +0200 Subject: [PATCH 175/310] Now `cargo collect-metadata` updates the `CHANGELOG.md` --- CHANGELOG.md | 59 +++++++++++++++++++ .../internal_lints/metadata_collector.rs | 18 ++++++ clippy_lints/src/utils/mod.rs | 7 +++ 3 files changed, 84 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index abc35e8546f..35b1075ff01 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5322,3 +5322,62 @@ Released 2018-09-13 [`zero_width_space`]: https://rust-lang.github.io/rust-clippy/master/index.html#zero_width_space [`zst_offset`]: https://rust-lang.github.io/rust-clippy/master/index.html#zst_offset + +[`arithmetic-side-effects-allowed`]: https://doc.rust-lang.org/clippy/lint_configuration.html#arithmetic-side-effects-allowed +[`arithmetic-side-effects-allowed-binary`]: https://doc.rust-lang.org/clippy/lint_configuration.html#arithmetic-side-effects-allowed-binary +[`arithmetic-side-effects-allowed-unary`]: https://doc.rust-lang.org/clippy/lint_configuration.html#arithmetic-side-effects-allowed-unary +[`avoid-breaking-exported-api`]: https://doc.rust-lang.org/clippy/lint_configuration.html#avoid-breaking-exported-api +[`msrv`]: https://doc.rust-lang.org/clippy/lint_configuration.html#msrv +[`cognitive-complexity-threshold`]: https://doc.rust-lang.org/clippy/lint_configuration.html#cognitive-complexity-threshold +[`excessive-nesting-threshold`]: https://doc.rust-lang.org/clippy/lint_configuration.html#excessive-nesting-threshold +[`disallowed-names`]: https://doc.rust-lang.org/clippy/lint_configuration.html#disallowed-names +[`semicolon-inside-block-ignore-singleline`]: https://doc.rust-lang.org/clippy/lint_configuration.html#semicolon-inside-block-ignore-singleline +[`semicolon-outside-block-ignore-multiline`]: https://doc.rust-lang.org/clippy/lint_configuration.html#semicolon-outside-block-ignore-multiline +[`doc-valid-idents`]: https://doc.rust-lang.org/clippy/lint_configuration.html#doc-valid-idents +[`too-many-arguments-threshold`]: https://doc.rust-lang.org/clippy/lint_configuration.html#too-many-arguments-threshold +[`type-complexity-threshold`]: https://doc.rust-lang.org/clippy/lint_configuration.html#type-complexity-threshold +[`single-char-binding-names-threshold`]: https://doc.rust-lang.org/clippy/lint_configuration.html#single-char-binding-names-threshold +[`too-large-for-stack`]: https://doc.rust-lang.org/clippy/lint_configuration.html#too-large-for-stack +[`enum-variant-name-threshold`]: https://doc.rust-lang.org/clippy/lint_configuration.html#enum-variant-name-threshold +[`enum-variant-size-threshold`]: https://doc.rust-lang.org/clippy/lint_configuration.html#enum-variant-size-threshold +[`verbose-bit-mask-threshold`]: https://doc.rust-lang.org/clippy/lint_configuration.html#verbose-bit-mask-threshold +[`literal-representation-threshold`]: https://doc.rust-lang.org/clippy/lint_configuration.html#literal-representation-threshold +[`trivial-copy-size-limit`]: https://doc.rust-lang.org/clippy/lint_configuration.html#trivial-copy-size-limit +[`pass-by-value-size-limit`]: https://doc.rust-lang.org/clippy/lint_configuration.html#pass-by-value-size-limit +[`too-many-lines-threshold`]: https://doc.rust-lang.org/clippy/lint_configuration.html#too-many-lines-threshold +[`array-size-threshold`]: https://doc.rust-lang.org/clippy/lint_configuration.html#array-size-threshold +[`stack-size-threshold`]: https://doc.rust-lang.org/clippy/lint_configuration.html#stack-size-threshold +[`vec-box-size-threshold`]: https://doc.rust-lang.org/clippy/lint_configuration.html#vec-box-size-threshold +[`max-trait-bounds`]: https://doc.rust-lang.org/clippy/lint_configuration.html#max-trait-bounds +[`max-struct-bools`]: https://doc.rust-lang.org/clippy/lint_configuration.html#max-struct-bools +[`max-fn-params-bools`]: https://doc.rust-lang.org/clippy/lint_configuration.html#max-fn-params-bools +[`warn-on-all-wildcard-imports`]: https://doc.rust-lang.org/clippy/lint_configuration.html#warn-on-all-wildcard-imports +[`disallowed-macros`]: https://doc.rust-lang.org/clippy/lint_configuration.html#disallowed-macros +[`disallowed-methods`]: https://doc.rust-lang.org/clippy/lint_configuration.html#disallowed-methods +[`disallowed-types`]: https://doc.rust-lang.org/clippy/lint_configuration.html#disallowed-types +[`unreadable-literal-lint-fractions`]: https://doc.rust-lang.org/clippy/lint_configuration.html#unreadable-literal-lint-fractions +[`upper-case-acronyms-aggressive`]: https://doc.rust-lang.org/clippy/lint_configuration.html#upper-case-acronyms-aggressive +[`matches-for-let-else`]: https://doc.rust-lang.org/clippy/lint_configuration.html#matches-for-let-else +[`cargo-ignore-publish`]: https://doc.rust-lang.org/clippy/lint_configuration.html#cargo-ignore-publish +[`standard-macro-braces`]: https://doc.rust-lang.org/clippy/lint_configuration.html#standard-macro-braces +[`enforced-import-renames`]: https://doc.rust-lang.org/clippy/lint_configuration.html#enforced-import-renames +[`allowed-scripts`]: https://doc.rust-lang.org/clippy/lint_configuration.html#allowed-scripts +[`enable-raw-pointer-heuristic-for-send`]: https://doc.rust-lang.org/clippy/lint_configuration.html#enable-raw-pointer-heuristic-for-send +[`max-suggested-slice-pattern-length`]: https://doc.rust-lang.org/clippy/lint_configuration.html#max-suggested-slice-pattern-length +[`await-holding-invalid-types`]: https://doc.rust-lang.org/clippy/lint_configuration.html#await-holding-invalid-types +[`max-include-file-size`]: https://doc.rust-lang.org/clippy/lint_configuration.html#max-include-file-size +[`allow-expect-in-tests`]: https://doc.rust-lang.org/clippy/lint_configuration.html#allow-expect-in-tests +[`allow-unwrap-in-tests`]: https://doc.rust-lang.org/clippy/lint_configuration.html#allow-unwrap-in-tests +[`allow-dbg-in-tests`]: https://doc.rust-lang.org/clippy/lint_configuration.html#allow-dbg-in-tests +[`allow-print-in-tests`]: https://doc.rust-lang.org/clippy/lint_configuration.html#allow-print-in-tests +[`large-error-threshold`]: https://doc.rust-lang.org/clippy/lint_configuration.html#large-error-threshold +[`ignore-interior-mutability`]: https://doc.rust-lang.org/clippy/lint_configuration.html#ignore-interior-mutability +[`allow-mixed-uninlined-format-args`]: https://doc.rust-lang.org/clippy/lint_configuration.html#allow-mixed-uninlined-format-args +[`suppress-restriction-lint-in-const`]: https://doc.rust-lang.org/clippy/lint_configuration.html#suppress-restriction-lint-in-const +[`missing-docs-in-crate-items`]: https://doc.rust-lang.org/clippy/lint_configuration.html#missing-docs-in-crate-items +[`future-size-threshold`]: https://doc.rust-lang.org/clippy/lint_configuration.html#future-size-threshold +[`unnecessary-box-size`]: https://doc.rust-lang.org/clippy/lint_configuration.html#unnecessary-box-size +[`allow-private-module-inception`]: https://doc.rust-lang.org/clippy/lint_configuration.html#allow-private-module-inception +[`allowed-idents-below-min-chars`]: https://doc.rust-lang.org/clippy/lint_configuration.html#allowed-idents-below-min-chars +[`min-ident-chars-threshold`]: https://doc.rust-lang.org/clippy/lint_configuration.html#min-ident-chars-threshold + diff --git a/clippy_lints/src/utils/internal_lints/metadata_collector.rs b/clippy_lints/src/utils/internal_lints/metadata_collector.rs index 2a9aba0a116..107a62806a8 100644 --- a/clippy_lints/src/utils/internal_lints/metadata_collector.rs +++ b/clippy_lints/src/utils/internal_lints/metadata_collector.rs @@ -104,6 +104,8 @@ const APPLICABILITY_UNRESOLVED_STR: &str = "Unresolved"; /// The version that will be displayed if none has been defined const VERSION_DEFAULT_STR: &str = "Unknown"; +const CHANGELOG_PATH: &str = "../CHANGELOG.md"; + declare_clippy_lint! { /// ### What it does /// Collects metadata about clippy lints for the website. @@ -260,6 +262,22 @@ Please use that command to update the file and do not edit it by hand. self.get_markdown_docs(), ) .unwrap(); + + // Write configuration links to CHANGELOG.md + let mut changelog = std::fs::read_to_string(CHANGELOG_PATH).unwrap(); + let mut changelog_file = OpenOptions::new().read(true).write(true).open(CHANGELOG_PATH).unwrap(); + + if let Some(position) = changelog.find("") { + // I know this is kinda wasteful, we just don't have regex on `clippy_lints` so... this is the best + // we can do AFAIK. + changelog = changelog[..position].to_string(); + } + writeln!( + changelog_file, + "{changelog}\n{}\n", + self.configs_to_markdown(ClippyConfiguration::to_markdown_link) + ) + .unwrap(); } } diff --git a/clippy_lints/src/utils/mod.rs b/clippy_lints/src/utils/mod.rs index 884edec2d79..fb08256931f 100644 --- a/clippy_lints/src/utils/mod.rs +++ b/clippy_lints/src/utils/mod.rs @@ -12,6 +12,9 @@ fn to_kebab(config_name: &str) -> String { config_name.replace('_', "-") } +#[cfg(feature = "internal")] +const BOOK_CONFIGS_PATH: &str = "https://doc.rust-lang.org/clippy/lint_configuration.html"; + // ================================================================== // Configuration // ================================================================== @@ -66,6 +69,10 @@ impl ClippyConfiguration { .join("\n"), ) } + #[cfg(feature = "internal")] + fn to_markdown_link(&self) -> String { + format!("[`{}`]: {BOOK_CONFIGS_PATH}#{}", self.name, self.name) + } } #[cfg(feature = "internal")] From bcaf655b70671275ca07b7f5c924f27125ee8c0b Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Tue, 13 Jun 2023 16:41:16 +0200 Subject: [PATCH 176/310] Remove dead code in `needless_pass_by_value` --- clippy_lints/src/needless_pass_by_value.rs | 27 +++------------------- 1 file changed, 3 insertions(+), 24 deletions(-) diff --git a/clippy_lints/src/needless_pass_by_value.rs b/clippy_lints/src/needless_pass_by_value.rs index 7d53fe65658..3b118239a21 100644 --- a/clippy_lints/src/needless_pass_by_value.rs +++ b/clippy_lints/src/needless_pass_by_value.rs @@ -7,13 +7,12 @@ use clippy_utils::ty::{ use clippy_utils::{get_trait_def_id, is_self, paths}; use if_chain::if_chain; use rustc_ast::ast::Attribute; -use rustc_data_structures::fx::FxHashSet; use rustc_errors::{Applicability, Diagnostic}; use rustc_hir::intravisit::FnKind; use rustc_hir::{ BindingAnnotation, Body, FnDecl, GenericArg, HirId, Impl, ItemKind, Mutability, Node, PatKind, QPath, TyKind, }; -use rustc_hir::{HirIdMap, HirIdSet, LangItem}; +use rustc_hir::{HirIdSet, LangItem}; use rustc_hir_typeck::expr_use_visitor as euv; use rustc_infer::infer::TyCtxtInferExt; use rustc_lint::{LateContext, LateLintPass}; @@ -136,11 +135,7 @@ impl<'tcx> LateLintPass<'tcx> for NeedlessPassByValue { // Collect moved variables and spans which will need dereferencings from the // function body. - let MovedVariablesCtxt { - moved_vars, - spans_need_deref, - .. - } = { + let MovedVariablesCtxt { moved_vars } = { let mut ctx = MovedVariablesCtxt::default(); let infcx = cx.tcx.infer_ctxt().build(); euv::ExprUseVisitor::new(&mut ctx, &infcx, fn_def_id, cx.param_env, cx.typeck_results()).consume_body(body); @@ -211,7 +206,6 @@ impl<'tcx> LateLintPass<'tcx> for NeedlessPassByValue { } } - let deref_span = spans_need_deref.get(&canonical_id); if_chain! { if is_type_diagnostic_item(cx, ty, sym::Vec); if let Some(clone_spans) = @@ -247,7 +241,6 @@ impl<'tcx> LateLintPass<'tcx> for NeedlessPassByValue { } // cannot be destructured, no need for `*` suggestion - assert!(deref_span.is_none()); return; } } @@ -275,23 +268,12 @@ impl<'tcx> LateLintPass<'tcx> for NeedlessPassByValue { ); } - assert!(deref_span.is_none()); return; } } - let mut spans = vec![(input.span, format!("&{}", snippet(cx, input.span, "_")))]; + let spans = vec![(input.span, format!("&{}", snippet(cx, input.span, "_")))]; - // Suggests adding `*` to dereference the added reference. - if let Some(deref_span) = deref_span { - spans.extend( - deref_span - .iter() - .copied() - .map(|span| (span, format!("*{}", snippet(cx, span, "")))), - ); - spans.sort_by_key(|&(span, _)| span); - } multispan_sugg(diag, "consider taking a reference instead", spans); }; @@ -320,9 +302,6 @@ fn requires_exact_signature(attrs: &[Attribute]) -> bool { #[derive(Default)] struct MovedVariablesCtxt { moved_vars: HirIdSet, - /// Spans which need to be prefixed with `*` for dereferencing the - /// suggested additional reference. - spans_need_deref: HirIdMap>, } impl MovedVariablesCtxt { From 9bc5a146fdfb521034eb7b9b907e1d113791d30d Mon Sep 17 00:00:00 2001 From: Centri3 <114838443+Centri3@users.noreply.github.com> Date: Sun, 11 Jun 2023 04:49:09 -0500 Subject: [PATCH 177/310] remove `in_move` --- clippy_utils/src/qualify_min_const_fn.rs | 38 ++++++++++++------------ 1 file changed, 19 insertions(+), 19 deletions(-) diff --git a/clippy_utils/src/qualify_min_const_fn.rs b/clippy_utils/src/qualify_min_const_fn.rs index 3dbda478b2f..9af6456924d 100644 --- a/clippy_utils/src/qualify_min_const_fn.rs +++ b/clippy_utils/src/qualify_min_const_fn.rs @@ -135,9 +135,9 @@ fn check_rvalue<'tcx>( match rvalue { Rvalue::ThreadLocalRef(_) => Err((span, "cannot access thread local storage in const fn".into())), Rvalue::Len(place) | Rvalue::Discriminant(place) | Rvalue::Ref(_, _, place) | Rvalue::AddressOf(_, place) => { - check_place(tcx, *place, span, body, false) + check_place(tcx, *place, span, body) }, - Rvalue::CopyForDeref(place) => check_place(tcx, *place, span, body, false), + Rvalue::CopyForDeref(place) => check_place(tcx, *place, span, body), Rvalue::Repeat(operand, _) | Rvalue::Use(operand) | Rvalue::Cast( @@ -230,14 +230,14 @@ fn check_statement<'tcx>( let span = statement.source_info.span; match &statement.kind { StatementKind::Assign(box (place, rval)) => { - check_place(tcx, *place, span, body, false)?; + check_place(tcx, *place, span, body)?; check_rvalue(tcx, body, def_id, rval, span) }, - StatementKind::FakeRead(box (_, place)) => check_place(tcx, *place, span, body, false), + StatementKind::FakeRead(box (_, place)) => check_place(tcx, *place, span, body), // just an assignment StatementKind::SetDiscriminant { place, .. } | StatementKind::Deinit(place) => { - check_place(tcx, **place, span, body, false) + check_place(tcx, **place, span, body) }, StatementKind::Intrinsic(box NonDivergingIntrinsic::Assume(op)) => check_operand(tcx, op, span, body), @@ -263,8 +263,19 @@ fn check_statement<'tcx>( fn check_operand<'tcx>(tcx: TyCtxt<'tcx>, operand: &Operand<'tcx>, span: Span, body: &Body<'tcx>) -> McfResult { match operand { - Operand::Move(place) => check_place(tcx, *place, span, body, true), - Operand::Copy(place) => check_place(tcx, *place, span, body, false), + Operand::Move(place) => { + if !place.projection.as_ref().is_empty() + && !is_ty_const_destruct(tcx, place.ty(&body.local_decls, tcx).ty, body) + { + return Err(( + span, + "cannot drop locals with a non constant destructor in const fn".into(), + )); + } + + check_place(tcx, *place, span, body) + }, + Operand::Copy(place) => check_place(tcx, *place, span, body), Operand::Constant(c) => match c.check_static_ptr(tcx) { Some(_) => Err((span, "cannot access `static` items in const fn".into())), None => Ok(()), @@ -272,20 +283,9 @@ fn check_operand<'tcx>(tcx: TyCtxt<'tcx>, operand: &Operand<'tcx>, span: Span, b } } -fn check_place<'tcx>(tcx: TyCtxt<'tcx>, place: Place<'tcx>, span: Span, body: &Body<'tcx>, in_move: bool) -> McfResult { +fn check_place<'tcx>(tcx: TyCtxt<'tcx>, place: Place<'tcx>, span: Span, body: &Body<'tcx>) -> McfResult { let mut cursor = place.projection.as_ref(); - if let [proj_base] = cursor - && let ProjectionElem::Field(_, ty) = proj_base - && !is_ty_const_destruct(tcx, *ty, body) - && in_move - { - return Err(( - span, - "cannot drop locals with a non constant destructor in const fn".into(), - )); - } - while let [ref proj_base @ .., elem] = *cursor { cursor = proj_base; match elem { From d255e7a53fb62e77cdfa7ce1459fc5a06072e21a Mon Sep 17 00:00:00 2001 From: Centri3 <114838443+Centri3@users.noreply.github.com> Date: Tue, 13 Jun 2023 12:29:50 -0500 Subject: [PATCH 178/310] [`no_effect`]: suggest adding `return` if applicable make cargo test pass Revert "Make it `Unspecified`" This reverts commit 774863041c1878ab7fb6e27c1c61c04de0e25bc8. Make it `Unspecified` --- clippy_lints/src/no_effect.rs | 47 ++++++++++++++++-- tests/ui/no_effect_return.rs | 81 ++++++++++++++++++++++++++++++++ tests/ui/no_effect_return.stderr | 70 +++++++++++++++++++++++++++ 3 files changed, 195 insertions(+), 3 deletions(-) create mode 100644 tests/ui/no_effect_return.rs create mode 100644 tests/ui/no_effect_return.stderr diff --git a/clippy_lints/src/no_effect.rs b/clippy_lints/src/no_effect.rs index e3712190e67..a4c7da7e48d 100644 --- a/clippy_lints/src/no_effect.rs +++ b/clippy_lints/src/no_effect.rs @@ -1,11 +1,16 @@ use clippy_utils::diagnostics::{span_lint_hir, span_lint_hir_and_then}; -use clippy_utils::is_lint_allowed; use clippy_utils::peel_blocks; use clippy_utils::source::snippet_opt; use clippy_utils::ty::has_drop; +use clippy_utils::{get_parent_node, is_lint_allowed}; use rustc_errors::Applicability; use rustc_hir::def::{DefKind, Res}; -use rustc_hir::{is_range_literal, BinOpKind, BlockCheckMode, Expr, ExprKind, PatKind, Stmt, StmtKind, UnsafeSource}; +use rustc_hir::{ + is_range_literal, BinOpKind, BlockCheckMode, Expr, ExprKind, FnRetTy, ItemKind, Node, PatKind, Stmt, StmtKind, + UnsafeSource, +}; +use rustc_hir_analysis::hir_ty_to_ty; +use rustc_infer::infer::TyCtxtInferExt as _; use rustc_lint::{LateContext, LateLintPass, LintContext}; use rustc_middle::lint::in_external_macro; use rustc_session::{declare_lint_pass, declare_tool_lint}; @@ -86,7 +91,43 @@ impl<'tcx> LateLintPass<'tcx> for NoEffect { fn check_no_effect(cx: &LateContext<'_>, stmt: &Stmt<'_>) -> bool { if let StmtKind::Semi(expr) = stmt.kind { if has_no_effect(cx, expr) { - span_lint_hir(cx, NO_EFFECT, expr.hir_id, stmt.span, "statement with no effect"); + span_lint_hir_and_then( + cx, + NO_EFFECT, + expr.hir_id, + stmt.span, + "statement with no effect", + |diag| { + for parent in cx.tcx.hir().parent_iter(stmt.hir_id) { + if let Node::Item(item) = parent.1 + && let ItemKind::Fn(sig, ..) = item.kind + && let FnRetTy::Return(ret_ty) = sig.decl.output + && let Some(Node::Block(block)) = get_parent_node(cx.tcx, stmt.hir_id) + && let [.., final_stmt] = block.stmts + && final_stmt.hir_id == stmt.hir_id + { + let expr_ty = cx.typeck_results().expr_ty(expr); + let mut ret_ty = hir_ty_to_ty(cx.tcx, ret_ty); + + // Remove `impl Future` to get `T` + if cx.tcx.ty_is_opaque_future(ret_ty) && + let Some(true_ret_ty) = cx.tcx.infer_ctxt().build().get_impl_future_output_ty(ret_ty) + { + ret_ty = true_ret_ty; + } + + if ret_ty == expr_ty { + diag.span_suggestion( + stmt.span.shrink_to_lo(), + "did you mean to return it?", + "return ", + Applicability::MaybeIncorrect, + ); + } + } + } + }, + ); return true; } } else if let StmtKind::Local(local) = stmt.kind { diff --git a/tests/ui/no_effect_return.rs b/tests/ui/no_effect_return.rs new file mode 100644 index 00000000000..231dd063ad8 --- /dev/null +++ b/tests/ui/no_effect_return.rs @@ -0,0 +1,81 @@ +#![allow(clippy::unused_unit, dead_code, unused)] +#![no_main] + +use std::ops::ControlFlow; + +fn a() -> u32 { + { + 0u32; + } + 0 +} + +async fn b() -> u32 { + { + 0u32; + } + 0 +} + +type C = i32; +async fn c() -> C { + { + 0i32 as C; + } + 0 +} + +fn d() -> u128 { + { + // not last stmt + 0u128; + println!("lol"); + } + 0 +} + +fn e() -> u32 { + { + // mismatched types + 0u16; + } + 0 +} + +fn f() -> [u16; 1] { + { + [1u16]; + } + [1] +} + +fn g() -> ControlFlow<()> { + { + ControlFlow::Break::<()>(()); + } + ControlFlow::Continue(()) +} + +fn h() -> Vec { + { + // function call, so this won't trigger `no_effect`. not an issue with this change, but the + // lint itself (but also not really.) + vec![0u16]; + } + vec![] +} + +fn i() -> () { + { + (); + } + () +} + +fn j() { + { + // does not suggest on function without explicit return type + (); + } + () +} diff --git a/tests/ui/no_effect_return.stderr b/tests/ui/no_effect_return.stderr new file mode 100644 index 00000000000..779900e1859 --- /dev/null +++ b/tests/ui/no_effect_return.stderr @@ -0,0 +1,70 @@ +error: statement with no effect + --> $DIR/no_effect_return.rs:8:9 + | +LL | 0u32; + | -^^^^ + | | + | help: did you mean to return it?: `return` + | + = note: `-D clippy::no-effect` implied by `-D warnings` + +error: statement with no effect + --> $DIR/no_effect_return.rs:15:9 + | +LL | 0u32; + | -^^^^ + | | + | help: did you mean to return it?: `return` + +error: statement with no effect + --> $DIR/no_effect_return.rs:23:9 + | +LL | 0i32 as C; + | -^^^^^^^^^ + | | + | help: did you mean to return it?: `return` + +error: statement with no effect + --> $DIR/no_effect_return.rs:31:9 + | +LL | 0u128; + | ^^^^^^ + +error: statement with no effect + --> $DIR/no_effect_return.rs:40:9 + | +LL | 0u16; + | ^^^^^ + +error: statement with no effect + --> $DIR/no_effect_return.rs:47:9 + | +LL | [1u16]; + | -^^^^^^ + | | + | help: did you mean to return it?: `return` + +error: statement with no effect + --> $DIR/no_effect_return.rs:54:9 + | +LL | ControlFlow::Break::<()>(()); + | -^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | | + | help: did you mean to return it?: `return` + +error: statement with no effect + --> $DIR/no_effect_return.rs:70:9 + | +LL | (); + | -^^ + | | + | help: did you mean to return it?: `return` + +error: statement with no effect + --> $DIR/no_effect_return.rs:78:9 + | +LL | (); + | ^^^ + +error: aborting due to 9 previous errors + From 74a0c9c62f1f8084175f776577ef39e197680171 Mon Sep 17 00:00:00 2001 From: Centri3 <114838443+Centri3@users.noreply.github.com> Date: Tue, 13 Jun 2023 14:05:22 -0500 Subject: [PATCH 179/310] [`needless_lifetimes`]' suggestion now points at the lifetimes --- clippy_lints/src/lifetimes.rs | 15 +- tests/ui/crashes/ice-2774.stderr | 4 +- .../needless_lifetimes_impl_trait.stderr | 4 +- tests/ui/issue_4266.stderr | 8 +- tests/ui/needless_lifetimes.stderr | 184 +++++++++--------- 5 files changed, 114 insertions(+), 101 deletions(-) diff --git a/clippy_lints/src/lifetimes.rs b/clippy_lints/src/lifetimes.rs index 7bc901e4e7f..852f6736585 100644 --- a/clippy_lints/src/lifetimes.rs +++ b/clippy_lints/src/lifetimes.rs @@ -1,5 +1,6 @@ use clippy_utils::diagnostics::{span_lint, span_lint_and_then}; use clippy_utils::trait_ref_of_method; +use itertools::Itertools; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_errors::Applicability; use rustc_hir::intravisit::nested_filter::{self as hir_nested_filter, NestedFilter}; @@ -201,7 +202,19 @@ fn check_fn_inner<'tcx>( span_lint_and_then( cx, NEEDLESS_LIFETIMES, - span.with_hi(sig.decl.output.span().hi()), + elidable_lts + .iter() + .map(|<| cx.tcx.def_span(lt)) + .chain(usages.iter().filter_map(|usage| { + if let LifetimeName::Param(def_id) = usage.res + && elidable_lts.contains(&def_id) + { + return Some(usage.ident.span); + } + + None + })) + .collect_vec(), &format!("the following explicit lifetimes could be elided: {lts}"), |diag| { if sig.header.is_async() { diff --git a/tests/ui/crashes/ice-2774.stderr b/tests/ui/crashes/ice-2774.stderr index c5ea0b16d1b..a166ccb3ee8 100644 --- a/tests/ui/crashes/ice-2774.stderr +++ b/tests/ui/crashes/ice-2774.stderr @@ -1,8 +1,8 @@ error: the following explicit lifetimes could be elided: 'a - --> $DIR/ice-2774.rs:15:1 + --> $DIR/ice-2774.rs:15:28 | LL | pub fn add_barfoos_to_foos<'a>(bars: &HashSet<&'a Bar>) { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^ ^^ | = note: `-D clippy::needless-lifetimes` implied by `-D warnings` help: elide the lifetimes diff --git a/tests/ui/crashes/needless_lifetimes_impl_trait.stderr b/tests/ui/crashes/needless_lifetimes_impl_trait.stderr index 0b0e0ad2684..37484f5ebd7 100644 --- a/tests/ui/crashes/needless_lifetimes_impl_trait.stderr +++ b/tests/ui/crashes/needless_lifetimes_impl_trait.stderr @@ -1,8 +1,8 @@ error: the following explicit lifetimes could be elided: 'a - --> $DIR/needless_lifetimes_impl_trait.rs:15:5 + --> $DIR/needless_lifetimes_impl_trait.rs:15:12 | LL | fn baz<'a>(&'a self) -> impl Foo + 'a { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^ ^^ ^^ | note: the lint level is defined here --> $DIR/needless_lifetimes_impl_trait.rs:1:9 diff --git a/tests/ui/issue_4266.stderr b/tests/ui/issue_4266.stderr index fd553aa4538..5b60646ef21 100644 --- a/tests/ui/issue_4266.stderr +++ b/tests/ui/issue_4266.stderr @@ -1,16 +1,16 @@ error: the following explicit lifetimes could be elided: 'a - --> $DIR/issue_4266.rs:4:1 + --> $DIR/issue_4266.rs:4:16 | LL | async fn sink1<'a>(_: &'a str) {} // lint - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^ ^^ | = note: `-D clippy::needless-lifetimes` implied by `-D warnings` error: the following explicit lifetimes could be elided: 'a - --> $DIR/issue_4266.rs:8:1 + --> $DIR/issue_4266.rs:8:21 | LL | async fn one_to_one<'a>(s: &'a str) -> &'a str { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^ ^^ error: methods called `new` usually take no `self` --> $DIR/issue_4266.rs:28:22 diff --git a/tests/ui/needless_lifetimes.stderr b/tests/ui/needless_lifetimes.stderr index 86acc4e0046..0da67b600a3 100644 --- a/tests/ui/needless_lifetimes.stderr +++ b/tests/ui/needless_lifetimes.stderr @@ -1,8 +1,8 @@ error: the following explicit lifetimes could be elided: 'a, 'b - --> $DIR/needless_lifetimes.rs:18:1 + --> $DIR/needless_lifetimes.rs:18:23 | LL | fn distinct_lifetimes<'a, 'b>(_x: &'a u8, _y: &'b u8, _z: u8) {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^ ^^ ^^ ^^ | = note: `-D clippy::needless-lifetimes` implied by `-D warnings` help: elide the lifetimes @@ -12,10 +12,10 @@ LL + fn distinct_lifetimes(_x: &u8, _y: &u8, _z: u8) {} | error: the following explicit lifetimes could be elided: 'a, 'b - --> $DIR/needless_lifetimes.rs:20:1 + --> $DIR/needless_lifetimes.rs:20:24 | LL | fn distinct_and_static<'a, 'b>(_x: &'a u8, _y: &'b u8, _z: &'static u8) {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^ ^^ ^^ ^^ | help: elide the lifetimes | @@ -24,10 +24,10 @@ LL + fn distinct_and_static(_x: &u8, _y: &u8, _z: &'static u8) {} | error: the following explicit lifetimes could be elided: 'a - --> $DIR/needless_lifetimes.rs:30:1 + --> $DIR/needless_lifetimes.rs:30:15 | LL | fn in_and_out<'a>(x: &'a u8, _y: u8) -> &'a u8 { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^ ^^ ^^ | help: elide the lifetimes | @@ -36,10 +36,10 @@ LL + fn in_and_out(x: &u8, _y: u8) -> &u8 { | error: the following explicit lifetimes could be elided: 'b - --> $DIR/needless_lifetimes.rs:42:1 + --> $DIR/needless_lifetimes.rs:42:31 | LL | fn multiple_in_and_out_2a<'a, 'b>(x: &'a u8, _y: &'b u8) -> &'a u8 { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^ ^^ | help: elide the lifetimes | @@ -48,10 +48,10 @@ LL + fn multiple_in_and_out_2a<'a>(x: &'a u8, _y: &u8) -> &'a u8 { | error: the following explicit lifetimes could be elided: 'a - --> $DIR/needless_lifetimes.rs:49:1 + --> $DIR/needless_lifetimes.rs:49:27 | LL | fn multiple_in_and_out_2b<'a, 'b>(_x: &'a u8, y: &'b u8) -> &'b u8 { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^ ^^ | help: elide the lifetimes | @@ -60,10 +60,10 @@ LL + fn multiple_in_and_out_2b<'b>(_x: &u8, y: &'b u8) -> &'b u8 { | error: the following explicit lifetimes could be elided: 'b - --> $DIR/needless_lifetimes.rs:66:1 + --> $DIR/needless_lifetimes.rs:66:26 | LL | fn deep_reference_1a<'a, 'b>(x: &'a u8, _y: &'b u8) -> Result<&'a u8, ()> { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^ ^^ | help: elide the lifetimes | @@ -72,10 +72,10 @@ LL + fn deep_reference_1a<'a>(x: &'a u8, _y: &u8) -> Result<&'a u8, ()> { | error: the following explicit lifetimes could be elided: 'a - --> $DIR/needless_lifetimes.rs:73:1 + --> $DIR/needless_lifetimes.rs:73:22 | LL | fn deep_reference_1b<'a, 'b>(_x: &'a u8, y: &'b u8) -> Result<&'b u8, ()> { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^ ^^ | help: elide the lifetimes | @@ -84,10 +84,10 @@ LL + fn deep_reference_1b<'b>(_x: &u8, y: &'b u8) -> Result<&'b u8, ()> { | error: the following explicit lifetimes could be elided: 'a - --> $DIR/needless_lifetimes.rs:82:1 + --> $DIR/needless_lifetimes.rs:82:21 | LL | fn deep_reference_3<'a>(x: &'a u8, _y: u8) -> Result<&'a u8, ()> { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^ ^^ ^^ | help: elide the lifetimes | @@ -96,10 +96,10 @@ LL + fn deep_reference_3(x: &u8, _y: u8) -> Result<&u8, ()> { | error: the following explicit lifetimes could be elided: 'a - --> $DIR/needless_lifetimes.rs:87:1 + --> $DIR/needless_lifetimes.rs:87:28 | LL | fn where_clause_without_lt<'a, T>(x: &'a u8, _y: u8) -> Result<&'a u8, ()> - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^ ^^ ^^ | help: elide the lifetimes | @@ -108,10 +108,10 @@ LL + fn where_clause_without_lt(x: &u8, _y: u8) -> Result<&u8, ()> | error: the following explicit lifetimes could be elided: 'a, 'b - --> $DIR/needless_lifetimes.rs:99:1 + --> $DIR/needless_lifetimes.rs:99:21 | LL | fn lifetime_param_2<'a, 'b>(_x: Ref<'a>, _y: &'b u8) {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^ ^^ ^^ ^^ | help: elide the lifetimes | @@ -120,10 +120,10 @@ LL + fn lifetime_param_2(_x: Ref<'_>, _y: &u8) {} | error: the following explicit lifetimes could be elided: 'a - --> $DIR/needless_lifetimes.rs:123:1 + --> $DIR/needless_lifetimes.rs:123:15 | LL | fn fn_bound_2<'a, F, I>(_m: Lt<'a, I>, _f: F) -> Lt<'a, I> - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^ ^^ ^^ | help: elide the lifetimes | @@ -132,10 +132,10 @@ LL + fn fn_bound_2(_m: Lt<'_, I>, _f: F) -> Lt<'_, I> | error: the following explicit lifetimes could be elided: 's - --> $DIR/needless_lifetimes.rs:153:5 + --> $DIR/needless_lifetimes.rs:153:21 | LL | fn self_and_out<'s>(&'s self) -> &'s u8 { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^ ^^ ^^ | help: elide the lifetimes | @@ -144,10 +144,10 @@ LL + fn self_and_out(&self) -> &u8 { | error: the following explicit lifetimes could be elided: 't - --> $DIR/needless_lifetimes.rs:160:5 + --> $DIR/needless_lifetimes.rs:160:30 | LL | fn self_and_in_out_1<'s, 't>(&'s self, _x: &'t u8) -> &'s u8 { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^ ^^ | help: elide the lifetimes | @@ -156,10 +156,10 @@ LL + fn self_and_in_out_1<'s>(&'s self, _x: &u8) -> &'s u8 { | error: the following explicit lifetimes could be elided: 's - --> $DIR/needless_lifetimes.rs:167:5 + --> $DIR/needless_lifetimes.rs:167:26 | LL | fn self_and_in_out_2<'s, 't>(&'s self, x: &'t u8) -> &'t u8 { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^ ^^ | help: elide the lifetimes | @@ -168,10 +168,10 @@ LL + fn self_and_in_out_2<'t>(&self, x: &'t u8) -> &'t u8 { | error: the following explicit lifetimes could be elided: 's, 't - --> $DIR/needless_lifetimes.rs:171:5 + --> $DIR/needless_lifetimes.rs:171:29 | LL | fn distinct_self_and_in<'s, 't>(&'s self, _x: &'t u8) {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^ ^^ ^^ ^^ | help: elide the lifetimes | @@ -180,10 +180,10 @@ LL + fn distinct_self_and_in(&self, _x: &u8) {} | error: the following explicit lifetimes could be elided: 'a - --> $DIR/needless_lifetimes.rs:190:1 + --> $DIR/needless_lifetimes.rs:190:19 | LL | fn struct_with_lt<'a>(_foo: Foo<'a>) -> &'a str { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^ ^^ ^^ | help: elide the lifetimes | @@ -192,10 +192,10 @@ LL + fn struct_with_lt(_foo: Foo<'_>) -> &str { | error: the following explicit lifetimes could be elided: 'b - --> $DIR/needless_lifetimes.rs:208:1 + --> $DIR/needless_lifetimes.rs:208:25 | LL | fn struct_with_lt4a<'a, 'b>(_foo: &'a Foo<'b>) -> &'a str { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^ ^^ | help: elide the lifetimes | @@ -204,10 +204,10 @@ LL + fn struct_with_lt4a<'a>(_foo: &'a Foo<'_>) -> &'a str { | error: the following explicit lifetimes could be elided: 'a - --> $DIR/needless_lifetimes.rs:216:1 + --> $DIR/needless_lifetimes.rs:216:21 | LL | fn struct_with_lt4b<'a, 'b>(_foo: &'a Foo<'b>) -> &'b str { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^ ^^ | help: elide the lifetimes | @@ -216,10 +216,10 @@ LL + fn struct_with_lt4b<'b>(_foo: &Foo<'b>) -> &'b str { | error: the following explicit lifetimes could be elided: 'a - --> $DIR/needless_lifetimes.rs:231:1 + --> $DIR/needless_lifetimes.rs:231:22 | LL | fn trait_obj_elided2<'a>(_arg: &'a dyn Drop) -> &'a str { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^ ^^ ^^ | help: elide the lifetimes | @@ -228,10 +228,10 @@ LL + fn trait_obj_elided2(_arg: &dyn Drop) -> &str { | error: the following explicit lifetimes could be elided: 'a - --> $DIR/needless_lifetimes.rs:237:1 + --> $DIR/needless_lifetimes.rs:237:18 | LL | fn alias_with_lt<'a>(_foo: FooAlias<'a>) -> &'a str { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^ ^^ ^^ | help: elide the lifetimes | @@ -240,10 +240,10 @@ LL + fn alias_with_lt(_foo: FooAlias<'_>) -> &str { | error: the following explicit lifetimes could be elided: 'b - --> $DIR/needless_lifetimes.rs:255:1 + --> $DIR/needless_lifetimes.rs:255:24 | LL | fn alias_with_lt4a<'a, 'b>(_foo: &'a FooAlias<'b>) -> &'a str { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^ ^^ | help: elide the lifetimes | @@ -252,10 +252,10 @@ LL + fn alias_with_lt4a<'a>(_foo: &'a FooAlias<'_>) -> &'a str { | error: the following explicit lifetimes could be elided: 'a - --> $DIR/needless_lifetimes.rs:263:1 + --> $DIR/needless_lifetimes.rs:263:20 | LL | fn alias_with_lt4b<'a, 'b>(_foo: &'a FooAlias<'b>) -> &'b str { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^ ^^ | help: elide the lifetimes | @@ -264,10 +264,10 @@ LL + fn alias_with_lt4b<'b>(_foo: &FooAlias<'b>) -> &'b str { | error: the following explicit lifetimes could be elided: 'a - --> $DIR/needless_lifetimes.rs:267:1 + --> $DIR/needless_lifetimes.rs:267:30 | LL | fn named_input_elided_output<'a>(_arg: &'a str) -> &str { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^ ^^ ^ | help: elide the lifetimes | @@ -276,10 +276,10 @@ LL + fn named_input_elided_output(_arg: &str) -> &str { | error: the following explicit lifetimes could be elided: 'a - --> $DIR/needless_lifetimes.rs:275:1 + --> $DIR/needless_lifetimes.rs:275:19 | LL | fn trait_bound_ok<'a, T: WithLifetime<'static>>(_: &'a u8, _: T) { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^ ^^ | help: elide the lifetimes | @@ -288,10 +288,10 @@ LL + fn trait_bound_ok>(_: &u8, _: T) { | error: the following explicit lifetimes could be elided: 'a - --> $DIR/needless_lifetimes.rs:311:1 + --> $DIR/needless_lifetimes.rs:311:24 | LL | fn out_return_type_lts<'a>(e: &'a str) -> Cow<'a> { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^ ^^ ^^ | help: elide the lifetimes | @@ -300,10 +300,10 @@ LL + fn out_return_type_lts(e: &str) -> Cow<'_> { | error: the following explicit lifetimes could be elided: 'a - --> $DIR/needless_lifetimes.rs:318:9 + --> $DIR/needless_lifetimes.rs:318:24 | LL | fn needless_lt<'a>(x: &'a u8) {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^ ^^ | help: elide the lifetimes | @@ -312,10 +312,10 @@ LL + fn needless_lt(x: &u8) {} | error: the following explicit lifetimes could be elided: 'a - --> $DIR/needless_lifetimes.rs:322:9 + --> $DIR/needless_lifetimes.rs:322:24 | LL | fn needless_lt<'a>(_x: &'a u8) {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^ ^^ | help: elide the lifetimes | @@ -324,10 +324,10 @@ LL + fn needless_lt(_x: &u8) {} | error: the following explicit lifetimes could be elided: 'a - --> $DIR/needless_lifetimes.rs:335:9 + --> $DIR/needless_lifetimes.rs:335:16 | LL | fn baz<'a>(&'a self) -> impl Foo + 'a { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^ ^^ ^^ | help: elide the lifetimes | @@ -336,10 +336,10 @@ LL + fn baz(&self) -> impl Foo + '_ { | error: the following explicit lifetimes could be elided: 'a - --> $DIR/needless_lifetimes.rs:367:5 + --> $DIR/needless_lifetimes.rs:367:55 | LL | fn impl_trait_elidable_nested_anonymous_lifetimes<'a>(i: &'a i32, f: impl Fn(&i32) -> &i32) -> &'a i32 { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^ ^^ ^^ | help: elide the lifetimes | @@ -348,10 +348,10 @@ LL + fn impl_trait_elidable_nested_anonymous_lifetimes(i: &i32, f: impl Fn(& | error: the following explicit lifetimes could be elided: 'a - --> $DIR/needless_lifetimes.rs:376:5 + --> $DIR/needless_lifetimes.rs:376:26 | LL | fn generics_elidable<'a, T: Fn(&i32) -> &i32>(i: &'a i32, f: T) -> &'a i32 { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^ ^^ ^^ | help: elide the lifetimes | @@ -360,10 +360,10 @@ LL + fn generics_elidable &i32>(i: &i32, f: T) -> &i32 { | error: the following explicit lifetimes could be elided: 'a - --> $DIR/needless_lifetimes.rs:388:5 + --> $DIR/needless_lifetimes.rs:388:32 | LL | fn where_clause_elidadable<'a, T>(i: &'a i32, f: T) -> &'a i32 - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^ ^^ ^^ | help: elide the lifetimes | @@ -372,10 +372,10 @@ LL + fn where_clause_elidadable(i: &i32, f: T) -> &i32 | error: the following explicit lifetimes could be elided: 'a - --> $DIR/needless_lifetimes.rs:403:5 + --> $DIR/needless_lifetimes.rs:403:28 | LL | fn pointer_fn_elidable<'a>(i: &'a i32, f: fn(&i32) -> &i32) -> &'a i32 { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^ ^^ ^^ | help: elide the lifetimes | @@ -384,10 +384,10 @@ LL + fn pointer_fn_elidable(i: &i32, f: fn(&i32) -> &i32) -> &i32 { | error: the following explicit lifetimes could be elided: 'a - --> $DIR/needless_lifetimes.rs:416:5 + --> $DIR/needless_lifetimes.rs:416:28 | LL | fn nested_fn_pointer_3<'a>(_: &'a i32) -> fn(fn(&i32) -> &i32) -> i32 { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^ ^^ | help: elide the lifetimes | @@ -396,10 +396,10 @@ LL + fn nested_fn_pointer_3(_: &i32) -> fn(fn(&i32) -> &i32) -> i32 { | error: the following explicit lifetimes could be elided: 'a - --> $DIR/needless_lifetimes.rs:419:5 + --> $DIR/needless_lifetimes.rs:419:28 | LL | fn nested_fn_pointer_4<'a>(_: &'a i32) -> impl Fn(fn(&i32)) { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^ ^^ | help: elide the lifetimes | @@ -408,10 +408,10 @@ LL + fn nested_fn_pointer_4(_: &i32) -> impl Fn(fn(&i32)) { | error: the following explicit lifetimes could be elided: 'a - --> $DIR/needless_lifetimes.rs:441:9 + --> $DIR/needless_lifetimes.rs:441:21 | LL | fn implicit<'a>(&'a self) -> &'a () { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^ ^^ ^^ | help: elide the lifetimes | @@ -420,10 +420,10 @@ LL + fn implicit(&self) -> &() { | error: the following explicit lifetimes could be elided: 'a - --> $DIR/needless_lifetimes.rs:444:9 + --> $DIR/needless_lifetimes.rs:444:25 | LL | fn implicit_mut<'a>(&'a mut self) -> &'a () { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^ ^^ ^^ | help: elide the lifetimes | @@ -432,10 +432,10 @@ LL + fn implicit_mut(&mut self) -> &() { | error: the following explicit lifetimes could be elided: 'a - --> $DIR/needless_lifetimes.rs:455:9 + --> $DIR/needless_lifetimes.rs:455:31 | LL | fn lifetime_elsewhere<'a>(self: Box, here: &'a ()) -> &'a () { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^ ^^ ^^ | help: elide the lifetimes | @@ -444,10 +444,10 @@ LL + fn lifetime_elsewhere(self: Box, here: &()) -> &() { | error: the following explicit lifetimes could be elided: 'a - --> $DIR/needless_lifetimes.rs:461:9 + --> $DIR/needless_lifetimes.rs:461:21 | LL | fn implicit<'a>(&'a self) -> &'a (); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^ ^^ ^^ | help: elide the lifetimes | @@ -456,10 +456,10 @@ LL + fn implicit(&self) -> &(); | error: the following explicit lifetimes could be elided: 'a - --> $DIR/needless_lifetimes.rs:462:9 + --> $DIR/needless_lifetimes.rs:462:30 | LL | fn implicit_provided<'a>(&'a self) -> &'a () { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^ ^^ ^^ | help: elide the lifetimes | @@ -468,10 +468,10 @@ LL + fn implicit_provided(&self) -> &() { | error: the following explicit lifetimes could be elided: 'a - --> $DIR/needless_lifetimes.rs:471:9 + --> $DIR/needless_lifetimes.rs:471:31 | LL | fn lifetime_elsewhere<'a>(self: Box, here: &'a ()) -> &'a (); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^ ^^ ^^ | help: elide the lifetimes | @@ -480,10 +480,10 @@ LL + fn lifetime_elsewhere(self: Box, here: &()) -> &(); | error: the following explicit lifetimes could be elided: 'a - --> $DIR/needless_lifetimes.rs:472:9 + --> $DIR/needless_lifetimes.rs:472:40 | LL | fn lifetime_elsewhere_provided<'a>(self: Box, here: &'a ()) -> &'a () { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^ ^^ ^^ | help: elide the lifetimes | @@ -492,10 +492,10 @@ LL + fn lifetime_elsewhere_provided(self: Box, here: &()) -> &() { | error: the following explicit lifetimes could be elided: 'a - --> $DIR/needless_lifetimes.rs:481:5 + --> $DIR/needless_lifetimes.rs:481:12 | LL | fn foo<'a>(x: &'a u8, y: &'_ u8) {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^ ^^ | help: elide the lifetimes | @@ -504,10 +504,10 @@ LL + fn foo(x: &u8, y: &'_ u8) {} | error: the following explicit lifetimes could be elided: 'a - --> $DIR/needless_lifetimes.rs:483:5 + --> $DIR/needless_lifetimes.rs:483:12 | LL | fn bar<'a>(x: &'a u8, y: &'_ u8, z: &'_ u8) {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^ ^^ | help: elide the lifetimes | @@ -516,10 +516,10 @@ LL + fn bar(x: &u8, y: &'_ u8, z: &'_ u8) {} | error: the following explicit lifetimes could be elided: 'a - --> $DIR/needless_lifetimes.rs:490:5 + --> $DIR/needless_lifetimes.rs:490:18 | LL | fn one_input<'a>(x: &'a u8) -> &'a u8 { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^ ^^ ^^ | help: elide the lifetimes | @@ -528,10 +528,10 @@ LL + fn one_input(x: &u8) -> &u8 { | error: the following explicit lifetimes could be elided: 'a - --> $DIR/needless_lifetimes.rs:495:5 + --> $DIR/needless_lifetimes.rs:495:42 | LL | fn multiple_inputs_output_not_elided<'a, 'b>(x: &'a u8, y: &'b u8, z: &'b u8) -> &'b u8 { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^ ^^ | help: elide the lifetimes | @@ -540,10 +540,10 @@ LL + fn multiple_inputs_output_not_elided<'b>(x: &u8, y: &'b u8, z: &'b u8) | error: the following explicit lifetimes could be elided: 'a - --> $DIR/needless_lifetimes.rs:511:9 + --> $DIR/needless_lifetimes.rs:511:22 | LL | fn one_input<'a>(x: &'a u8) -> &'a u8 { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^ ^^ ^^ | = note: this error originates in the macro `__inline_mac_mod_in_macro` (in Nightly builds, run with -Z macro-backtrace for more info) help: elide the lifetimes From d2725402a9e2c753858e221f3e871c7dd9cb7242 Mon Sep 17 00:00:00 2001 From: Centri3 <114838443+Centri3@users.noreply.github.com> Date: Tue, 13 Jun 2023 14:55:54 -0500 Subject: [PATCH 180/310] [`borrow_as_ptr`]: Ignore temporaries --- clippy_lints/src/casts/borrow_as_ptr.rs | 8 +++++++- tests/ui/borrow_as_ptr.fixed | 9 +++++++++ tests/ui/borrow_as_ptr.rs | 9 +++++++++ tests/ui/borrow_as_ptr.stderr | 4 ++-- 4 files changed, 27 insertions(+), 3 deletions(-) diff --git a/clippy_lints/src/casts/borrow_as_ptr.rs b/clippy_lints/src/casts/borrow_as_ptr.rs index 294d22d34de..e93f2765337 100644 --- a/clippy_lints/src/casts/borrow_as_ptr.rs +++ b/clippy_lints/src/casts/borrow_as_ptr.rs @@ -1,6 +1,8 @@ -use clippy_utils::diagnostics::span_lint_and_sugg; +use std::ops::ControlFlow; + use clippy_utils::is_no_std_crate; use clippy_utils::source::snippet_with_context; +use clippy_utils::{diagnostics::span_lint_and_sugg, visitors::for_each_unconsumed_temporary}; use rustc_errors::Applicability; use rustc_hir::{BorrowKind, Expr, ExprKind, Mutability, Ty, TyKind}; use rustc_lint::LateContext; @@ -23,6 +25,10 @@ pub(super) fn check<'tcx>( }; let mut app = Applicability::MachineApplicable; let snip = snippet_with_context(cx, e.span, cast_expr.span.ctxt(), "..", &mut app).0; + // Fix #9884 + if for_each_unconsumed_temporary(cx, expr, |_| ControlFlow::Break(true)).is_break() { + return; + } span_lint_and_sugg( cx, diff --git a/tests/ui/borrow_as_ptr.fixed b/tests/ui/borrow_as_ptr.fixed index 3f440ce0045..996cc3650ff 100644 --- a/tests/ui/borrow_as_ptr.fixed +++ b/tests/ui/borrow_as_ptr.fixed @@ -1,9 +1,18 @@ //@run-rustfix #![warn(clippy::borrow_as_ptr)] +#![allow(clippy::useless_vec)] + +fn a() -> i32 { + 0 +} fn main() { let val = 1; let _p = std::ptr::addr_of!(val); + let _p = &0 as *const i32; + let _p = &a() as *const i32; + let vec = vec![1]; + let _p = &vec.len() as *const usize; let mut val_mut = 1; let _p_mut = std::ptr::addr_of_mut!(val_mut); diff --git a/tests/ui/borrow_as_ptr.rs b/tests/ui/borrow_as_ptr.rs index c1ca9180eef..5eafaeb2fc3 100644 --- a/tests/ui/borrow_as_ptr.rs +++ b/tests/ui/borrow_as_ptr.rs @@ -1,9 +1,18 @@ //@run-rustfix #![warn(clippy::borrow_as_ptr)] +#![allow(clippy::useless_vec)] + +fn a() -> i32 { + 0 +} fn main() { let val = 1; let _p = &val as *const i32; + let _p = &0 as *const i32; + let _p = &a() as *const i32; + let vec = vec![1]; + let _p = &vec.len() as *const usize; let mut val_mut = 1; let _p_mut = &mut val_mut as *mut i32; diff --git a/tests/ui/borrow_as_ptr.stderr b/tests/ui/borrow_as_ptr.stderr index be1ed733056..c9990bb6f22 100644 --- a/tests/ui/borrow_as_ptr.stderr +++ b/tests/ui/borrow_as_ptr.stderr @@ -1,5 +1,5 @@ error: borrow as raw pointer - --> $DIR/borrow_as_ptr.rs:6:14 + --> $DIR/borrow_as_ptr.rs:11:14 | LL | let _p = &val as *const i32; | ^^^^^^^^^^^^^^^^^^ help: try: `std::ptr::addr_of!(val)` @@ -7,7 +7,7 @@ LL | let _p = &val as *const i32; = note: `-D clippy::borrow-as-ptr` implied by `-D warnings` error: borrow as raw pointer - --> $DIR/borrow_as_ptr.rs:9:18 + --> $DIR/borrow_as_ptr.rs:18:18 | LL | let _p_mut = &mut val_mut as *mut i32; | ^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `std::ptr::addr_of_mut!(val_mut)` From 062b2099044ed1d65f6100d0d0ca8cd76102246e Mon Sep 17 00:00:00 2001 From: Kisaragi Marine Date: Wed, 14 Jun 2023 12:23:02 +0900 Subject: [PATCH 181/310] Ignore `main()` in `no_test` code fences --- clippy_lints/src/doc.rs | 5 ++++- tests/ui/doc/needless_doctest_main.rs | 19 +++++++++++++++++++ 2 files changed, 23 insertions(+), 1 deletion(-) create mode 100644 tests/ui/doc/needless_doctest_main.rs diff --git a/clippy_lints/src/doc.rs b/clippy_lints/src/doc.rs index 384aca7fead..0617c3ea5e9 100644 --- a/clippy_lints/src/doc.rs +++ b/clippy_lints/src/doc.rs @@ -571,6 +571,7 @@ fn check_doc<'a, Events: Iterator, Range, Span)> = Vec::new(); @@ -584,6 +585,8 @@ fn check_doc<'a, Events: Iterator, Range, Range Date: Wed, 14 Jun 2023 12:36:17 +0900 Subject: [PATCH 182/310] run `cargo dev fmt` --- tests/ui/doc/needless_doctest_main.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/tests/ui/doc/needless_doctest_main.rs b/tests/ui/doc/needless_doctest_main.rs index fb32aac9449..666b7e67b42 100644 --- a/tests/ui/doc/needless_doctest_main.rs +++ b/tests/ui/doc/needless_doctest_main.rs @@ -8,7 +8,6 @@ //! m.insert(1u32, 2u32); //! } //! ``` -//! /// some description here /// ```rust,no_test From 867bd153836edd4441e4ca4481cfbe06f450d8c7 Mon Sep 17 00:00:00 2001 From: Kisaragi Marine Date: Wed, 14 Jun 2023 12:53:36 +0900 Subject: [PATCH 183/310] add main function to test itself --- tests/ui/doc/needless_doctest_main.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tests/ui/doc/needless_doctest_main.rs b/tests/ui/doc/needless_doctest_main.rs index 666b7e67b42..f1a2c0575ee 100644 --- a/tests/ui/doc/needless_doctest_main.rs +++ b/tests/ui/doc/needless_doctest_main.rs @@ -16,3 +16,5 @@ /// } /// ``` fn foo() {} + +fn main() {} From 72aa180798d9444ff3968ac51fad6da0ca28a7a0 Mon Sep 17 00:00:00 2001 From: Centri3 <114838443+Centri3@users.noreply.github.com> Date: Wed, 14 Jun 2023 06:56:38 -0500 Subject: [PATCH 184/310] use rustc's criteria for a temporary --- clippy_lints/src/casts/borrow_as_ptr.rs | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/clippy_lints/src/casts/borrow_as_ptr.rs b/clippy_lints/src/casts/borrow_as_ptr.rs index e93f2765337..b7256dd2eae 100644 --- a/clippy_lints/src/casts/borrow_as_ptr.rs +++ b/clippy_lints/src/casts/borrow_as_ptr.rs @@ -1,11 +1,10 @@ -use std::ops::ControlFlow; - +use clippy_utils::diagnostics::span_lint_and_sugg; use clippy_utils::is_no_std_crate; use clippy_utils::source::snippet_with_context; -use clippy_utils::{diagnostics::span_lint_and_sugg, visitors::for_each_unconsumed_temporary}; use rustc_errors::Applicability; use rustc_hir::{BorrowKind, Expr, ExprKind, Mutability, Ty, TyKind}; use rustc_lint::LateContext; +use rustc_middle::ty::adjustment::Adjust; use super::BORROW_AS_PTR; @@ -26,7 +25,12 @@ pub(super) fn check<'tcx>( let mut app = Applicability::MachineApplicable; let snip = snippet_with_context(cx, e.span, cast_expr.span.ctxt(), "..", &mut app).0; // Fix #9884 - if for_each_unconsumed_temporary(cx, expr, |_| ControlFlow::Break(true)).is_break() { + if !e.is_place_expr(|base| { + cx.typeck_results() + .adjustments() + .get(base.hir_id) + .is_some_and(|x| x.iter().any(|adj| matches!(adj.kind, Adjust::Deref(_)))) + }) { return; } From 79f93a655a9a3849c0653a72a5b547776a1522b3 Mon Sep 17 00:00:00 2001 From: Kisaragi Marine Date: Wed, 14 Jun 2023 22:07:31 +0900 Subject: [PATCH 185/310] missing_panics_doc: pickup expect method --- clippy_lints/src/doc.rs | 4 ++-- tests/ui/doc/missing_panics_doc.rs | 31 ++++++++++++++++++++++++++++++ 2 files changed, 33 insertions(+), 2 deletions(-) create mode 100644 tests/ui/doc/missing_panics_doc.rs diff --git a/clippy_lints/src/doc.rs b/clippy_lints/src/doc.rs index 0617c3ea5e9..11de7e60697 100644 --- a/clippy_lints/src/doc.rs +++ b/clippy_lints/src/doc.rs @@ -916,8 +916,8 @@ impl<'a, 'tcx> Visitor<'tcx> for FindPanicUnwrap<'a, 'tcx> { } } - // check for `unwrap` - if let Some(arglists) = method_chain_args(expr, &["unwrap"]) { + // check for `unwrap` and `expect` both `Option` and `Result` + if let Some(arglists) = method_chain_args(expr, &["unwrap"]).or(method_chain_args(expr, &["expect"])) { let receiver_ty = self.typeck_results.expr_ty(arglists[0].0).peel_refs(); if is_type_diagnostic_item(self.cx, receiver_ty, sym::Option) || is_type_diagnostic_item(self.cx, receiver_ty, sym::Result) diff --git a/tests/ui/doc/missing_panics_doc.rs b/tests/ui/doc/missing_panics_doc.rs new file mode 100644 index 00000000000..5cb8a9691f4 --- /dev/null +++ b/tests/ui/doc/missing_panics_doc.rs @@ -0,0 +1,31 @@ +#![warn(clippy::missing_panics_doc)] + +pub fn option_unwrap(v: &[T]) -> &T { + let o: Option<&T> = v.last(); + o.unwrap() +} + +pub fn option_expect(v: &[T]) -> &T { + let o: Option<&T> = v.last(); + o.expect("passed an empty thing") +} + +pub fn result_unwrap(v: &[T]) -> &T { + let res: Result<&T, &str> = v.last().ok_or("oh noes"); + res.unwrap() +} + +pub fn result_expect(v: &[T]) -> &T { + let res: Result<&T, &str> = v.last().ok_or("oh noes"); + res.expect("passed an empty thing") +} + +pub fn last_unwrap(v: &[u32]) -> u32 { + *v.last().unwrap() +} + +pub fn last_expect(v: &[u32]) -> u32 { + *v.last().expect("passed an empty thing") +} + +fn main() {} From 2fa72c7dfe89febb091699fe5d43fb4893d38d7f Mon Sep 17 00:00:00 2001 From: Kisaragi Marine Date: Wed, 14 Jun 2023 22:16:20 +0900 Subject: [PATCH 186/310] bless --- tests/ui/doc/missing_panics_doc.stderr | 75 ++++++++++++++++++++++++++ 1 file changed, 75 insertions(+) create mode 100644 tests/ui/doc/missing_panics_doc.stderr diff --git a/tests/ui/doc/missing_panics_doc.stderr b/tests/ui/doc/missing_panics_doc.stderr new file mode 100644 index 00000000000..f3e613bc799 --- /dev/null +++ b/tests/ui/doc/missing_panics_doc.stderr @@ -0,0 +1,75 @@ +error: docs for function which may panic missing `# Panics` section + --> $DIR/missing_panics_doc.rs:3:1 + | +LL | pub fn option_unwrap(v: &[T]) -> &T { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: first possible panic found here + --> $DIR/missing_panics_doc.rs:5:5 + | +LL | o.unwrap() + | ^^^^^^^^^^ + = note: `-D clippy::missing-panics-doc` implied by `-D warnings` + +error: docs for function which may panic missing `# Panics` section + --> $DIR/missing_panics_doc.rs:8:1 + | +LL | pub fn option_expect(v: &[T]) -> &T { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: first possible panic found here + --> $DIR/missing_panics_doc.rs:10:5 + | +LL | o.expect("passed an empty thing") + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: docs for function which may panic missing `# Panics` section + --> $DIR/missing_panics_doc.rs:13:1 + | +LL | pub fn result_unwrap(v: &[T]) -> &T { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: first possible panic found here + --> $DIR/missing_panics_doc.rs:15:5 + | +LL | res.unwrap() + | ^^^^^^^^^^^^ + +error: docs for function which may panic missing `# Panics` section + --> $DIR/missing_panics_doc.rs:18:1 + | +LL | pub fn result_expect(v: &[T]) -> &T { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: first possible panic found here + --> $DIR/missing_panics_doc.rs:20:5 + | +LL | res.expect("passed an empty thing") + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: docs for function which may panic missing `# Panics` section + --> $DIR/missing_panics_doc.rs:23:1 + | +LL | pub fn last_unwrap(v: &[u32]) -> u32 { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: first possible panic found here + --> $DIR/missing_panics_doc.rs:24:6 + | +LL | *v.last().unwrap() + | ^^^^^^^^^^^^^^^^^ + +error: docs for function which may panic missing `# Panics` section + --> $DIR/missing_panics_doc.rs:27:1 + | +LL | pub fn last_expect(v: &[u32]) -> u32 { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: first possible panic found here + --> $DIR/missing_panics_doc.rs:28:6 + | +LL | *v.last().expect("passed an empty thing") + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 6 previous errors + From aff9c01ab99dd7bb4a185df3a08e27f364fecf50 Mon Sep 17 00:00:00 2001 From: Kisaragi Marine Date: Wed, 14 Jun 2023 22:26:10 +0900 Subject: [PATCH 187/310] address or allow clippy::missing_panics_doc in clippy-dev --- clippy_dev/src/fmt.rs | 1 + clippy_dev/src/lib.rs | 6 ++++++ clippy_dev/src/new_lint.rs | 1 + 3 files changed, 8 insertions(+) diff --git a/clippy_dev/src/fmt.rs b/clippy_dev/src/fmt.rs index 25623144181..ee559d45dd1 100644 --- a/clippy_dev/src/fmt.rs +++ b/clippy_dev/src/fmt.rs @@ -35,6 +35,7 @@ struct FmtContext { } // the "main" function of cargo dev fmt +#[allow(clippy::missing_panics_doc)] pub fn run(check: bool, verbose: bool) { fn try_run(context: &FmtContext) -> Result { let mut success = true; diff --git a/clippy_dev/src/lib.rs b/clippy_dev/src/lib.rs index 56a269288c0..8aaa029f776 100644 --- a/clippy_dev/src/lib.rs +++ b/clippy_dev/src/lib.rs @@ -29,6 +29,10 @@ static CARGO_CLIPPY_EXE: &str = "cargo-clippy"; static CARGO_CLIPPY_EXE: &str = "cargo-clippy.exe"; /// Returns the path to the `cargo-clippy` binary +/// +/// # Panics +/// +/// Panics if the path of current executable could not be retrieved. #[must_use] pub fn cargo_clippy_path() -> PathBuf { let mut path = std::env::current_exe().expect("failed to get current executable name"); @@ -61,6 +65,8 @@ pub fn clippy_project_root() -> PathBuf { panic!("error: Can't determine root of project. Please run inside a Clippy working dir."); } +/// # Panics +/// Panics if given command result was failed. pub fn exit_if_err(status: io::Result) { match status.expect("failed to run command").code() { Some(0) => {}, diff --git a/clippy_dev/src/new_lint.rs b/clippy_dev/src/new_lint.rs index f970a32726b..f0ccdb0fe10 100644 --- a/clippy_dev/src/new_lint.rs +++ b/clippy_dev/src/new_lint.rs @@ -36,6 +36,7 @@ impl Context for io::Result { /// # Errors /// /// This function errors out if the files couldn't be created or written to. +#[allow(clippy::missing_panics_doc)] pub fn create( pass: &String, lint_name: Option<&String>, From 27a701a670c5e14b632e205a818d8e32ffdcda44 Mon Sep 17 00:00:00 2001 From: Centri3 <114838443+Centri3@users.noreply.github.com> Date: Tue, 13 Jun 2023 13:08:03 -0500 Subject: [PATCH 188/310] [`match_same_arms`]: don't lint if `non_exhaustive_omitted_patterns` formatting :/ --- clippy_lints/src/matches/match_same_arms.rs | 29 ++++++---- clippy_lints/src/matches/mod.rs | 3 + tests/ui/match_same_arms_non_exhaustive.rs | 58 +++++++++++++++++++ .../ui/match_same_arms_non_exhaustive.stderr | 29 ++++++++++ 4 files changed, 107 insertions(+), 12 deletions(-) create mode 100644 tests/ui/match_same_arms_non_exhaustive.rs create mode 100644 tests/ui/match_same_arms_non_exhaustive.stderr diff --git a/clippy_lints/src/matches/match_same_arms.rs b/clippy_lints/src/matches/match_same_arms.rs index ae8262ace96..3d2fbea63f5 100644 --- a/clippy_lints/src/matches/match_same_arms.rs +++ b/clippy_lints/src/matches/match_same_arms.rs @@ -1,6 +1,6 @@ use clippy_utils::diagnostics::span_lint_and_then; use clippy_utils::source::snippet; -use clippy_utils::{path_to_local, search_same, SpanlessEq, SpanlessHash}; +use clippy_utils::{is_lint_allowed, path_to_local, search_same, SpanlessEq, SpanlessHash}; use core::cmp::Ordering; use core::iter; use core::slice; @@ -9,6 +9,7 @@ use rustc_ast::ast::LitKind; use rustc_errors::Applicability; use rustc_hir::def_id::DefId; use rustc_hir::{Arm, Expr, ExprKind, HirId, HirIdMap, HirIdMapEntry, HirIdSet, Pat, PatKind, RangeEnd}; +use rustc_lint::builtin::NON_EXHAUSTIVE_OMITTED_PATTERNS; use rustc_lint::LateContext; use rustc_middle::ty; use rustc_span::Symbol; @@ -103,17 +104,21 @@ pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, arms: &'tcx [Arm<'_>]) { let indexed_arms: Vec<(usize, &Arm<'_>)> = arms.iter().enumerate().collect(); for (&(i, arm1), &(j, arm2)) in search_same(&indexed_arms, hash, eq) { if matches!(arm2.pat.kind, PatKind::Wild) { - span_lint_and_then( - cx, - MATCH_SAME_ARMS, - arm1.span, - "this match arm has an identical body to the `_` wildcard arm", - |diag| { - diag.span_suggestion(arm1.span, "try removing the arm", "", Applicability::MaybeIncorrect) - .help("or try changing either arm body") - .span_note(arm2.span, "`_` wildcard arm here"); - }, - ); + if !cx.tcx.features().non_exhaustive_omitted_patterns_lint + || is_lint_allowed(cx, NON_EXHAUSTIVE_OMITTED_PATTERNS, arm2.hir_id) + { + span_lint_and_then( + cx, + MATCH_SAME_ARMS, + arm1.span, + "this match arm has an identical body to the `_` wildcard arm", + |diag| { + diag.span_suggestion(arm1.span, "try removing the arm", "", Applicability::MaybeIncorrect) + .help("or try changing either arm body") + .span_note(arm2.span, "`_` wildcard arm here"); + }, + ); + } } else { let back_block = backwards_blocking_idxs[j]; let (keep_arm, move_arm) = if back_block < i || (back_block == 0 && forwards_blocking_idxs[i] <= j) { diff --git a/clippy_lints/src/matches/mod.rs b/clippy_lints/src/matches/mod.rs index 2d27be499f9..3fbd0867ea9 100644 --- a/clippy_lints/src/matches/mod.rs +++ b/clippy_lints/src/matches/mod.rs @@ -559,6 +559,9 @@ declare_clippy_lint! { /// ### What it does /// Checks for `match` with identical arm bodies. /// + /// Note: Does not lint on wildcards if the `non_exhaustive_omitted_patterns_lint` feature is + /// enabled and disallowed. + /// /// ### Why is this bad? /// This is probably a copy & paste error. If arm bodies /// are the same on purpose, you can factor them diff --git a/tests/ui/match_same_arms_non_exhaustive.rs b/tests/ui/match_same_arms_non_exhaustive.rs new file mode 100644 index 00000000000..07421173a33 --- /dev/null +++ b/tests/ui/match_same_arms_non_exhaustive.rs @@ -0,0 +1,58 @@ +#![feature(non_exhaustive_omitted_patterns_lint)] +#![warn(clippy::match_same_arms)] +#![no_main] + +use std::sync::atomic::Ordering; // #[non_exhaustive] enum + +pub fn f(x: Ordering) { + match x { + Ordering::Relaxed => println!("relaxed"), + Ordering::Release => println!("release"), + Ordering::Acquire => println!("acquire"), + Ordering::AcqRel | Ordering::SeqCst => panic!(), + #[deny(non_exhaustive_omitted_patterns)] + _ => panic!(), + } +} + +mod f { + #![deny(non_exhaustive_omitted_patterns)] + + use super::*; + + pub fn f(x: Ordering) { + match x { + Ordering::Relaxed => println!("relaxed"), + Ordering::Release => println!("release"), + Ordering::Acquire => println!("acquire"), + Ordering::AcqRel | Ordering::SeqCst => panic!(), + _ => panic!(), + } + } +} + +// Below should still lint + +pub fn g(x: Ordering) { + match x { + Ordering::Relaxed => println!("relaxed"), + Ordering::Release => println!("release"), + Ordering::Acquire => println!("acquire"), + Ordering::AcqRel | Ordering::SeqCst => panic!(), + _ => panic!(), + } +} + +mod g { + use super::*; + + pub fn g(x: Ordering) { + match x { + Ordering::Relaxed => println!("relaxed"), + Ordering::Release => println!("release"), + Ordering::Acquire => println!("acquire"), + Ordering::AcqRel | Ordering::SeqCst => panic!(), + _ => panic!(), + } + } +} diff --git a/tests/ui/match_same_arms_non_exhaustive.stderr b/tests/ui/match_same_arms_non_exhaustive.stderr new file mode 100644 index 00000000000..088f7d5c062 --- /dev/null +++ b/tests/ui/match_same_arms_non_exhaustive.stderr @@ -0,0 +1,29 @@ +error: this match arm has an identical body to the `_` wildcard arm + --> $DIR/match_same_arms_non_exhaustive.rs:41:9 + | +LL | Ordering::AcqRel | Ordering::SeqCst => panic!(), + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try removing the arm + | + = help: or try changing either arm body +note: `_` wildcard arm here + --> $DIR/match_same_arms_non_exhaustive.rs:42:9 + | +LL | _ => panic!(), + | ^^^^^^^^^^^^^ + = note: `-D clippy::match-same-arms` implied by `-D warnings` + +error: this match arm has an identical body to the `_` wildcard arm + --> $DIR/match_same_arms_non_exhaustive.rs:54:13 + | +LL | Ordering::AcqRel | Ordering::SeqCst => panic!(), + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try removing the arm + | + = help: or try changing either arm body +note: `_` wildcard arm here + --> $DIR/match_same_arms_non_exhaustive.rs:55:13 + | +LL | _ => panic!(), + | ^^^^^^^^^^^^^ + +error: aborting due to 2 previous errors + From 830d307d0a4b0bb584bf3552fcbf0e2dc2575aec Mon Sep 17 00:00:00 2001 From: Centri3 <114838443+Centri3@users.noreply.github.com> Date: Mon, 12 Jun 2023 12:55:31 -0500 Subject: [PATCH 189/310] refactor a bit --- clippy_lints/src/single_range_in_vec_init.rs | 38 +++++++++----------- tests/ui/single_range_in_vec_init.stderr | 20 +++++------ 2 files changed, 26 insertions(+), 32 deletions(-) diff --git a/clippy_lints/src/single_range_in_vec_init.rs b/clippy_lints/src/single_range_in_vec_init.rs index 2d3f18a62c0..dfe8be7a6a6 100644 --- a/clippy_lints/src/single_range_in_vec_init.rs +++ b/clippy_lints/src/single_range_in_vec_init.rs @@ -1,10 +1,6 @@ use clippy_utils::{ - diagnostics::span_lint_and_then, - get_trait_def_id, - higher::VecArgs, - macros::root_macro_call_first_node, - source::{snippet_opt, snippet_with_applicability}, - ty::implements_trait, + diagnostics::span_lint_and_then, get_trait_def_id, higher::VecArgs, macros::root_macro_call_first_node, + source::snippet_opt, ty::implements_trait, }; use rustc_ast::{LitIntType, LitKind, UintTy}; use rustc_errors::Applicability; @@ -18,9 +14,9 @@ declare_clippy_lint! { /// Checks for `Vec` or array initializations that contain only one range. /// /// ### Why is this bad? - /// This is almost always incorrect, as it will result in a `Vec` that has only element. Almost - /// always, the programmer intended for it to include all elements in the range or for the end - /// of the range to be the length instead. + /// This is almost always incorrect, as it will result in a `Vec` that has only one element. + /// Almost always, the programmer intended for it to include all elements in the range or for + /// the end of the range to be the length instead. /// /// ### Example /// ```rust @@ -75,8 +71,8 @@ impl LateLintPass<'_> for SingleRangeInVecInit { // ^^^^^^ ^^^^^^^ // span: `vec![0..200]` or `[0..200]` // ^^^^^^^^^^^^ ^^^^^^^^ - // kind: What to print, an array or a `Vec` - let (inner_expr, span, kind) = if let ExprKind::Array([inner_expr]) = expr.kind + // suggested_type: What to print, "an array" or "a `Vec`" + let (inner_expr, span, suggested_type) = if let ExprKind::Array([inner_expr]) = expr.kind && !expr.span.from_expansion() { (inner_expr, expr.span, SuggestedType::Array) @@ -96,13 +92,11 @@ impl LateLintPass<'_> for SingleRangeInVecInit { && let ty = cx.typeck_results().expr_ty(start.expr) && let Some(snippet) = snippet_opt(cx, span) // `is_from_proc_macro` will skip any `vec![]`. Let's not! - && snippet.starts_with(kind.starts_with()) - && snippet.ends_with(kind.ends_with()) + && snippet.starts_with(suggested_type.starts_with()) + && snippet.ends_with(suggested_type.ends_with()) + && let Some(start_snippet) = snippet_opt(cx, start.span) + && let Some(end_snippet) = snippet_opt(cx, end.span) { - let mut app = Applicability::MaybeIncorrect; - let start_snippet = snippet_with_applicability(cx, start.span, "...", &mut app); - let end_snippet = snippet_with_applicability(cx, end.span, "...", &mut app); - let should_emit_every_value = if let Some(step_def_id) = get_trait_def_id(cx, &["core", "iter", "Step"]) && implements_trait(cx, ty, step_def_id, &[]) { @@ -126,23 +120,23 @@ impl LateLintPass<'_> for SingleRangeInVecInit { cx, SINGLE_RANGE_IN_VEC_INIT, span, - &format!("{kind} of `Range` that is only one element"), + &format!("{suggested_type} of `Range` that is only one element"), |diag| { if should_emit_every_value { diag.span_suggestion( span, - "if you wanted a `Vec` that contains every value in the range, try", + "if you wanted a `Vec` that contains the entire range, try", format!("({start_snippet}..{end_snippet}).collect::>()"), - app, + Applicability::MaybeIncorrect, ); } if should_emit_of_len { diag.span_suggestion( inner_expr.span, - format!("if you wanted {kind} of len {end_snippet}, try"), + format!("if you wanted {suggested_type} of len {end_snippet}, try"), format!("{start_snippet}; {end_snippet}"), - app, + Applicability::MaybeIncorrect, ); } }, diff --git a/tests/ui/single_range_in_vec_init.stderr b/tests/ui/single_range_in_vec_init.stderr index fc03b2205e2..3e3d521f4a5 100644 --- a/tests/ui/single_range_in_vec_init.stderr +++ b/tests/ui/single_range_in_vec_init.stderr @@ -5,7 +5,7 @@ LL | [0..200]; | ^^^^^^^^ | = note: `-D clippy::single-range-in-vec-init` implied by `-D warnings` -help: if you wanted a `Vec` that contains every value in the range, try +help: if you wanted a `Vec` that contains the entire range, try | LL | (0..200).collect::>(); | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -20,7 +20,7 @@ error: a `Vec` of `Range` that is only one element LL | vec![0..200]; | ^^^^^^^^^^^^ | -help: if you wanted a `Vec` that contains every value in the range, try +help: if you wanted a `Vec` that contains the entire range, try | LL | (0..200).collect::>(); | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -35,7 +35,7 @@ error: an array of `Range` that is only one element LL | [0u8..200]; | ^^^^^^^^^^ | -help: if you wanted a `Vec` that contains every value in the range, try +help: if you wanted a `Vec` that contains the entire range, try | LL | (0u8..200).collect::>(); | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -50,7 +50,7 @@ error: an array of `Range` that is only one element LL | [0usize..200]; | ^^^^^^^^^^^^^ | -help: if you wanted a `Vec` that contains every value in the range, try +help: if you wanted a `Vec` that contains the entire range, try | LL | (0usize..200).collect::>(); | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -65,7 +65,7 @@ error: an array of `Range` that is only one element LL | [0..200usize]; | ^^^^^^^^^^^^^ | -help: if you wanted a `Vec` that contains every value in the range, try +help: if you wanted a `Vec` that contains the entire range, try | LL | (0..200usize).collect::>(); | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -80,7 +80,7 @@ error: a `Vec` of `Range` that is only one element LL | vec![0u8..200]; | ^^^^^^^^^^^^^^ | -help: if you wanted a `Vec` that contains every value in the range, try +help: if you wanted a `Vec` that contains the entire range, try | LL | (0u8..200).collect::>(); | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -95,7 +95,7 @@ error: a `Vec` of `Range` that is only one element LL | vec![0usize..200]; | ^^^^^^^^^^^^^^^^^ | -help: if you wanted a `Vec` that contains every value in the range, try +help: if you wanted a `Vec` that contains the entire range, try | LL | (0usize..200).collect::>(); | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -110,7 +110,7 @@ error: a `Vec` of `Range` that is only one element LL | vec![0..200usize]; | ^^^^^^^^^^^^^^^^^ | -help: if you wanted a `Vec` that contains every value in the range, try +help: if you wanted a `Vec` that contains the entire range, try | LL | (0..200usize).collect::>(); | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -125,7 +125,7 @@ error: an array of `Range` that is only one element LL | [0..200isize]; | ^^^^^^^^^^^^^ | -help: if you wanted a `Vec` that contains every value in the range, try +help: if you wanted a `Vec` that contains the entire range, try | LL | (0..200isize).collect::>(); | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -136,7 +136,7 @@ error: a `Vec` of `Range` that is only one element LL | vec![0..200isize]; | ^^^^^^^^^^^^^^^^^ | -help: if you wanted a `Vec` that contains every value in the range, try +help: if you wanted a `Vec` that contains the entire range, try | LL | (0..200isize).collect::>(); | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ From 2ba192695527b1633f63396b3e12bbbdf7b19fef Mon Sep 17 00:00:00 2001 From: y21 <30553356+y21@users.noreply.github.com> Date: Wed, 14 Jun 2023 16:52:02 +0200 Subject: [PATCH 190/310] [`derivable_impls`]: don't lint if expr unsize-coerces --- clippy_lints/src/derivable_impls.rs | 38 +++++++++++++++++++++++++---- tests/ui/derivable_impls.fixed | 21 ++++++++++++++++ tests/ui/derivable_impls.rs | 21 ++++++++++++++++ 3 files changed, 75 insertions(+), 5 deletions(-) diff --git a/clippy_lints/src/derivable_impls.rs b/clippy_lints/src/derivable_impls.rs index 8f68f90a2a1..618214f4aa2 100644 --- a/clippy_lints/src/derivable_impls.rs +++ b/clippy_lints/src/derivable_impls.rs @@ -8,7 +8,8 @@ use rustc_hir::{ Body, Expr, ExprKind, GenericArg, Impl, ImplItemKind, Item, ItemKind, Node, PathSegment, QPath, Ty, TyKind, }; use rustc_lint::{LateContext, LateLintPass}; -use rustc_middle::ty::{Adt, AdtDef, SubstsRef}; +use rustc_middle::ty::adjustment::{Adjust, PointerCast}; +use rustc_middle::ty::{self, Adt, AdtDef, SubstsRef, TypeckResults}; use rustc_session::{declare_tool_lint, impl_lint_pass}; use rustc_span::sym; @@ -75,6 +76,19 @@ fn is_path_self(e: &Expr<'_>) -> bool { } } +fn contains_trait_object(cx: &LateContext<'_>, ty: ty::Ty<'_>) -> bool { + match ty.kind() { + ty::TyKind::Ref(_, ty, _) => { + contains_trait_object(cx, *ty) + }, + ty::TyKind::Adt(def, substs) => { + def.is_box() && substs[0].as_type().map_or(false, |ty| contains_trait_object(cx, ty)) + } + ty::TyKind::Dynamic(..) => true, + _ => false, + } +} + fn check_struct<'tcx>( cx: &LateContext<'tcx>, item: &'tcx Item<'_>, @@ -82,6 +96,7 @@ fn check_struct<'tcx>( func_expr: &Expr<'_>, adt_def: AdtDef<'_>, substs: SubstsRef<'_>, + typeck_results: &'tcx TypeckResults<'tcx>, ) { if let TyKind::Path(QPath::Resolved(_, p)) = self_ty.kind { if let Some(PathSegment { args, .. }) = p.segments.last() { @@ -96,10 +111,23 @@ fn check_struct<'tcx>( } } } + + // the default() call might unsize coerce to a trait object (e.g. Box to Box), + // which would not be the same if derived (see #10158). + // this closure checks both if the expr is equivalent to a `default()` call and does not + // have such coercions. + let is_default_without_adjusts = |expr| { + is_default_equivalent(cx, expr) + && typeck_results.expr_adjustments(expr).iter().all(|adj| { + !matches!(adj.kind, Adjust::Pointer(PointerCast::Unsize) + if contains_trait_object(cx, adj.target)) + }) + }; + let should_emit = match peel_blocks(func_expr).kind { - ExprKind::Tup(fields) => fields.iter().all(|e| is_default_equivalent(cx, e)), - ExprKind::Call(callee, args) if is_path_self(callee) => args.iter().all(|e| is_default_equivalent(cx, e)), - ExprKind::Struct(_, fields, _) => fields.iter().all(|ef| is_default_equivalent(cx, ef.expr)), + ExprKind::Tup(fields) => fields.iter().all(|e| is_default_without_adjusts(e)), + ExprKind::Call(callee, args) if is_path_self(callee) => args.iter().all(|e| is_default_without_adjusts(e)), + ExprKind::Struct(_, fields, _) => fields.iter().all(|ef| is_default_without_adjusts(ef.expr)), _ => false, }; @@ -197,7 +225,7 @@ impl<'tcx> LateLintPass<'tcx> for DerivableImpls { then { if adt_def.is_struct() { - check_struct(cx, item, self_ty, func_expr, adt_def, substs); + check_struct(cx, item, self_ty, func_expr, adt_def, substs, cx.tcx.typeck_body(*b)); } else if adt_def.is_enum() && self.msrv.meets(msrvs::DEFAULT_ENUM_ATTRIBUTE) { check_enum(cx, item, func_expr, adt_def); } diff --git a/tests/ui/derivable_impls.fixed b/tests/ui/derivable_impls.fixed index aa0efb85c29..a10f3d01070 100644 --- a/tests/ui/derivable_impls.fixed +++ b/tests/ui/derivable_impls.fixed @@ -268,4 +268,25 @@ impl Default for OtherGenericType { } } +mod issue10158 { + pub trait T {} + + #[derive(Default)] + pub struct S {} + impl T for S {} + + pub struct Outer { + pub inner: Box, + } + + impl Default for Outer { + fn default() -> Self { + Outer { + // Box::::default() adjusts to Box + inner: Box::::default(), + } + } + } +} + fn main() {} diff --git a/tests/ui/derivable_impls.rs b/tests/ui/derivable_impls.rs index 8dc999ad586..18cef1c5be8 100644 --- a/tests/ui/derivable_impls.rs +++ b/tests/ui/derivable_impls.rs @@ -304,4 +304,25 @@ impl Default for OtherGenericType { } } +mod issue10158 { + pub trait T {} + + #[derive(Default)] + pub struct S {} + impl T for S {} + + pub struct Outer { + pub inner: Box, + } + + impl Default for Outer { + fn default() -> Self { + Outer { + // Box::::default() adjusts to Box + inner: Box::::default(), + } + } + } +} + fn main() {} From 5b6ba204a7de1d5c694a7b25269a25ee68c98830 Mon Sep 17 00:00:00 2001 From: y21 <30553356+y21@users.noreply.github.com> Date: Wed, 14 Jun 2023 17:01:57 +0200 Subject: [PATCH 191/310] fmt --- clippy_lints/src/derivable_impls.rs | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/clippy_lints/src/derivable_impls.rs b/clippy_lints/src/derivable_impls.rs index 618214f4aa2..4ea58c47709 100644 --- a/clippy_lints/src/derivable_impls.rs +++ b/clippy_lints/src/derivable_impls.rs @@ -78,12 +78,10 @@ fn is_path_self(e: &Expr<'_>) -> bool { fn contains_trait_object(cx: &LateContext<'_>, ty: ty::Ty<'_>) -> bool { match ty.kind() { - ty::TyKind::Ref(_, ty, _) => { - contains_trait_object(cx, *ty) - }, + ty::TyKind::Ref(_, ty, _) => contains_trait_object(cx, *ty), ty::TyKind::Adt(def, substs) => { def.is_box() && substs[0].as_type().map_or(false, |ty| contains_trait_object(cx, ty)) - } + }, ty::TyKind::Dynamic(..) => true, _ => false, } @@ -119,7 +117,7 @@ fn check_struct<'tcx>( let is_default_without_adjusts = |expr| { is_default_equivalent(cx, expr) && typeck_results.expr_adjustments(expr).iter().all(|adj| { - !matches!(adj.kind, Adjust::Pointer(PointerCast::Unsize) + !matches!(adj.kind, Adjust::Pointer(PointerCast::Unsize) if contains_trait_object(cx, adj.target)) }) }; From fcb9a382f70125209e3ac4b82ef0e5e67decae65 Mon Sep 17 00:00:00 2001 From: y21 <30553356+y21@users.noreply.github.com> Date: Wed, 14 Jun 2023 17:10:26 +0200 Subject: [PATCH 192/310] dogfood --- clippy_lints/src/derivable_impls.rs | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/clippy_lints/src/derivable_impls.rs b/clippy_lints/src/derivable_impls.rs index 4ea58c47709..55cfe0d6b8b 100644 --- a/clippy_lints/src/derivable_impls.rs +++ b/clippy_lints/src/derivable_impls.rs @@ -76,12 +76,10 @@ fn is_path_self(e: &Expr<'_>) -> bool { } } -fn contains_trait_object(cx: &LateContext<'_>, ty: ty::Ty<'_>) -> bool { +fn contains_trait_object(ty: ty::Ty<'_>) -> bool { match ty.kind() { - ty::TyKind::Ref(_, ty, _) => contains_trait_object(cx, *ty), - ty::TyKind::Adt(def, substs) => { - def.is_box() && substs[0].as_type().map_or(false, |ty| contains_trait_object(cx, ty)) - }, + ty::TyKind::Ref(_, ty, _) => contains_trait_object(*ty), + ty::TyKind::Adt(def, substs) => def.is_box() && substs[0].as_type().map_or(false, contains_trait_object), ty::TyKind::Dynamic(..) => true, _ => false, } @@ -118,13 +116,13 @@ fn check_struct<'tcx>( is_default_equivalent(cx, expr) && typeck_results.expr_adjustments(expr).iter().all(|adj| { !matches!(adj.kind, Adjust::Pointer(PointerCast::Unsize) - if contains_trait_object(cx, adj.target)) + if contains_trait_object(adj.target)) }) }; let should_emit = match peel_blocks(func_expr).kind { - ExprKind::Tup(fields) => fields.iter().all(|e| is_default_without_adjusts(e)), - ExprKind::Call(callee, args) if is_path_self(callee) => args.iter().all(|e| is_default_without_adjusts(e)), + ExprKind::Tup(fields) => fields.iter().all(is_default_without_adjusts), + ExprKind::Call(callee, args) if is_path_self(callee) => args.iter().all(is_default_without_adjusts), ExprKind::Struct(_, fields, _) => fields.iter().all(|ef| is_default_without_adjusts(ef.expr)), _ => false, }; From 4795c919399610d9105fae67492d3eb65c0c1c01 Mon Sep 17 00:00:00 2001 From: y21 <30553356+y21@users.noreply.github.com> Date: Wed, 14 Jun 2023 17:15:57 +0200 Subject: [PATCH 193/310] fix internal lints --- clippy_lints/src/derivable_impls.rs | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/clippy_lints/src/derivable_impls.rs b/clippy_lints/src/derivable_impls.rs index 55cfe0d6b8b..ec0ca50cfec 100644 --- a/clippy_lints/src/derivable_impls.rs +++ b/clippy_lints/src/derivable_impls.rs @@ -4,12 +4,13 @@ use clippy_utils::source::indent_of; use clippy_utils::{is_default_equivalent, peel_blocks}; use rustc_errors::Applicability; use rustc_hir::{ + self as hir, def::{CtorKind, CtorOf, DefKind, Res}, - Body, Expr, ExprKind, GenericArg, Impl, ImplItemKind, Item, ItemKind, Node, PathSegment, QPath, Ty, TyKind, + Body, Expr, ExprKind, GenericArg, Impl, ImplItemKind, Item, ItemKind, Node, PathSegment, QPath, TyKind, }; use rustc_lint::{LateContext, LateLintPass}; use rustc_middle::ty::adjustment::{Adjust, PointerCast}; -use rustc_middle::ty::{self, Adt, AdtDef, SubstsRef, TypeckResults}; +use rustc_middle::ty::{self, Adt, AdtDef, SubstsRef, Ty, TypeckResults}; use rustc_session::{declare_tool_lint, impl_lint_pass}; use rustc_span::sym; @@ -76,11 +77,11 @@ fn is_path_self(e: &Expr<'_>) -> bool { } } -fn contains_trait_object(ty: ty::Ty<'_>) -> bool { +fn contains_trait_object(ty: Ty<'_>) -> bool { match ty.kind() { - ty::TyKind::Ref(_, ty, _) => contains_trait_object(*ty), - ty::TyKind::Adt(def, substs) => def.is_box() && substs[0].as_type().map_or(false, contains_trait_object), - ty::TyKind::Dynamic(..) => true, + ty::Ref(_, ty, _) => contains_trait_object(*ty), + ty::Adt(def, substs) => def.is_box() && substs[0].as_type().map_or(false, contains_trait_object), + ty::Dynamic(..) => true, _ => false, } } @@ -88,7 +89,7 @@ fn contains_trait_object(ty: ty::Ty<'_>) -> bool { fn check_struct<'tcx>( cx: &LateContext<'tcx>, item: &'tcx Item<'_>, - self_ty: &Ty<'_>, + self_ty: &hir::Ty<'_>, func_expr: &Expr<'_>, adt_def: AdtDef<'_>, substs: SubstsRef<'_>, From 69e892e3a182bedb22e20399d6ba862572be46b2 Mon Sep 17 00:00:00 2001 From: y21 <30553356+y21@users.noreply.github.com> Date: Wed, 14 Jun 2023 22:29:57 +0200 Subject: [PATCH 194/310] get rid of unnecessary function pointer --- clippy_lints/src/methods/unnecessary_fold.rs | 59 +++++++++----------- 1 file changed, 26 insertions(+), 33 deletions(-) diff --git a/clippy_lints/src/methods/unnecessary_fold.rs b/clippy_lints/src/methods/unnecessary_fold.rs index de29d99cf8d..e545abd8ba8 100644 --- a/clippy_lints/src/methods/unnecessary_fold.rs +++ b/clippy_lints/src/methods/unnecessary_fold.rs @@ -12,14 +12,10 @@ use rustc_span::{source_map::Span, sym}; use super::UNNECESSARY_FOLD; -/// No turbofish needed in any case. -fn no_turbofish(_: &LateContext<'_>, _: &hir::Expr<'_>) -> bool { - false -} - -/// Turbofish (`::`) may be needed, but can be omitted if we are certain -/// that the type can be inferred from usage. -fn turbofish_if_not_inferred(cx: &LateContext<'_>, expr: &hir::Expr<'_>) -> bool { +/// Do we need to suggest turbofish when suggesting a replacement method? +/// Changing `fold` to `sum` needs it sometimes when the return type can't be +/// inferred. This checks for some common cases where it can be safely omitted +fn needs_turbofish(cx: &LateContext<'_>, expr: &hir::Expr<'_>) -> bool { let parent = cx.tcx.hir().get_parent(expr.hir_id); // some common cases where turbofish isn't needed: @@ -53,26 +49,7 @@ fn turbofish_if_not_inferred(cx: &LateContext<'_>, expr: &hir::Expr<'_>) -> bool struct Replacement { method_name: &'static str, has_args: bool, - requires_turbofish: fn(&LateContext<'_>, &hir::Expr<'_>) -> bool, -} -impl Replacement { - /// `any(f)`, `all(f)` - pub fn non_generic(method_name: &'static str) -> Self { - Self { - method_name, - has_args: true, - requires_turbofish: no_turbofish, - } - } - - /// `sum::()`, `product::()` - pub fn generic(method_name: &'static str) -> Self { - Self { - method_name, - has_args: false, - requires_turbofish: turbofish_if_not_inferred, - } - } + has_generic_return: bool, } pub(super) fn check( @@ -111,7 +88,7 @@ pub(super) fn check( then { let mut applicability = Applicability::MachineApplicable; - let turbofish = if (replacement.requires_turbofish)(cx, expr) { + let turbofish = if replacement.has_generic_return { format!("::<{}>", cx.typeck_results().expr_ty_adjusted(right_expr).peel_refs()) } else { String::new() @@ -159,7 +136,11 @@ pub(super) fn check( acc, fold_span, hir::BinOpKind::Or, - Replacement::non_generic("any"), + Replacement { + has_args: true, + has_generic_return: false, + method_name: "any", + }, ); }, ast::LitKind::Bool(true) => { @@ -169,7 +150,11 @@ pub(super) fn check( acc, fold_span, hir::BinOpKind::And, - Replacement::non_generic("all"), + Replacement { + has_args: true, + has_generic_return: false, + method_name: "all", + }, ); }, ast::LitKind::Int(0, _) => check_fold_with_op( @@ -178,7 +163,11 @@ pub(super) fn check( acc, fold_span, hir::BinOpKind::Add, - Replacement::generic("sum"), + Replacement { + has_args: false, + has_generic_return: needs_turbofish(cx, expr), + method_name: "sum", + }, ), ast::LitKind::Int(1, _) => { check_fold_with_op( @@ -187,7 +176,11 @@ pub(super) fn check( acc, fold_span, hir::BinOpKind::Mul, - Replacement::generic("product"), + Replacement { + has_args: false, + has_generic_return: needs_turbofish(cx, expr), + method_name: "product", + }, ); }, _ => (), From d102e2296c2a507c32f3882b296ee65926dfc32f Mon Sep 17 00:00:00 2001 From: y21 <30553356+y21@users.noreply.github.com> Date: Wed, 14 Jun 2023 22:38:06 +0200 Subject: [PATCH 195/310] move check_fold_with_op function out --- clippy_lints/src/methods/unnecessary_fold.rs | 124 +++++++++---------- 1 file changed, 62 insertions(+), 62 deletions(-) diff --git a/clippy_lints/src/methods/unnecessary_fold.rs b/clippy_lints/src/methods/unnecessary_fold.rs index e545abd8ba8..8ec15a1c1b7 100644 --- a/clippy_lints/src/methods/unnecessary_fold.rs +++ b/clippy_lints/src/methods/unnecessary_fold.rs @@ -52,6 +52,68 @@ struct Replacement { has_generic_return: bool, } +fn check_fold_with_op( + cx: &LateContext<'_>, + expr: &hir::Expr<'_>, + acc: &hir::Expr<'_>, + fold_span: Span, + op: hir::BinOpKind, + replacement: Replacement, +) { + if_chain! { + // Extract the body of the closure passed to fold + if let hir::ExprKind::Closure(&hir::Closure { body, .. }) = acc.kind; + let closure_body = cx.tcx.hir().body(body); + let closure_expr = peel_blocks(closure_body.value); + + // Check if the closure body is of the form `acc some_expr(x)` + if let hir::ExprKind::Binary(ref bin_op, left_expr, right_expr) = closure_expr.kind; + if bin_op.node == op; + + // Extract the names of the two arguments to the closure + if let [param_a, param_b] = closure_body.params; + if let PatKind::Binding(_, first_arg_id, ..) = strip_pat_refs(param_a.pat).kind; + if let PatKind::Binding(_, second_arg_id, second_arg_ident, _) = strip_pat_refs(param_b.pat).kind; + + if path_to_local_id(left_expr, first_arg_id); + if replacement.has_args || path_to_local_id(right_expr, second_arg_id); + + then { + let mut applicability = Applicability::MachineApplicable; + + let turbofish = if replacement.has_generic_return { + format!("::<{}>", cx.typeck_results().expr_ty_adjusted(right_expr).peel_refs()) + } else { + String::new() + }; + + let sugg = if replacement.has_args { + format!( + "{method}{turbofish}(|{second_arg_ident}| {r})", + method = replacement.method_name, + r = snippet_with_applicability(cx, right_expr.span, "EXPR", &mut applicability), + ) + } else { + format!( + "{method}{turbofish}()", + method = replacement.method_name, + ) + }; + + span_lint_and_sugg( + cx, + UNNECESSARY_FOLD, + fold_span.with_hi(expr.span.hi()), + // TODO #2371 don't suggest e.g., .any(|x| f(x)) if we can suggest .any(f) + "this `.fold` can be written more succinctly using another method", + "try", + sugg, + applicability, + ); + } + } +} + pub(super) fn check( cx: &LateContext<'_>, expr: &hir::Expr<'_>, @@ -59,68 +121,6 @@ pub(super) fn check( acc: &hir::Expr<'_>, fold_span: Span, ) { - fn check_fold_with_op( - cx: &LateContext<'_>, - expr: &hir::Expr<'_>, - acc: &hir::Expr<'_>, - fold_span: Span, - op: hir::BinOpKind, - replacement: Replacement, - ) { - if_chain! { - // Extract the body of the closure passed to fold - if let hir::ExprKind::Closure(&hir::Closure { body, .. }) = acc.kind; - let closure_body = cx.tcx.hir().body(body); - let closure_expr = peel_blocks(closure_body.value); - - // Check if the closure body is of the form `acc some_expr(x)` - if let hir::ExprKind::Binary(ref bin_op, left_expr, right_expr) = closure_expr.kind; - if bin_op.node == op; - - // Extract the names of the two arguments to the closure - if let [param_a, param_b] = closure_body.params; - if let PatKind::Binding(_, first_arg_id, ..) = strip_pat_refs(param_a.pat).kind; - if let PatKind::Binding(_, second_arg_id, second_arg_ident, _) = strip_pat_refs(param_b.pat).kind; - - if path_to_local_id(left_expr, first_arg_id); - if replacement.has_args || path_to_local_id(right_expr, second_arg_id); - - then { - let mut applicability = Applicability::MachineApplicable; - - let turbofish = if replacement.has_generic_return { - format!("::<{}>", cx.typeck_results().expr_ty_adjusted(right_expr).peel_refs()) - } else { - String::new() - }; - - let sugg = if replacement.has_args { - format!( - "{method}{turbofish}(|{second_arg_ident}| {r})", - method = replacement.method_name, - r = snippet_with_applicability(cx, right_expr.span, "EXPR", &mut applicability), - ) - } else { - format!( - "{method}{turbofish}()", - method = replacement.method_name, - ) - }; - - span_lint_and_sugg( - cx, - UNNECESSARY_FOLD, - fold_span.with_hi(expr.span.hi()), - // TODO #2371 don't suggest e.g., .any(|x| f(x)) if we can suggest .any(f) - "this `.fold` can be written more succinctly using another method", - "try", - sugg, - applicability, - ); - } - } - } - // Check that this is a call to Iterator::fold rather than just some function called fold if !is_trait_method(cx, expr, sym::Iterator) { return; From a35c78fa70a6107d9b0373f1c86167da5b0b7980 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=AE=B8=E6=9D=B0=E5=8F=8B=20Jieyou=20Xu=20=28Joe=29?= Date: Sun, 11 Jun 2023 23:44:28 +0800 Subject: [PATCH 196/310] Extend `unused_must_use` to cover block exprs --- tests/ui/transmute_ptr_to_ref.fixed | 3 +- tests/ui/transmute_ptr_to_ref.rs | 3 +- tests/ui/transmute_ptr_to_ref.stderr | 48 ++++++++++++++-------------- 3 files changed, 28 insertions(+), 26 deletions(-) diff --git a/tests/ui/transmute_ptr_to_ref.fixed b/tests/ui/transmute_ptr_to_ref.fixed index 575dadde906..ac55ab5a8e2 100644 --- a/tests/ui/transmute_ptr_to_ref.fixed +++ b/tests/ui/transmute_ptr_to_ref.fixed @@ -2,6 +2,7 @@ #![warn(clippy::transmute_ptr_to_ref)] #![allow(clippy::match_single_binding)] +#![allow(unused_must_use)] unsafe fn _ptr_to_ref(p: *const T, m: *mut T, o: *const U, om: *mut U) { let _: &T = &*p; @@ -38,7 +39,7 @@ fn _issue1231() { type Bar<'a> = &'a u8; let raw = 42 as *const i32; - unsafe { &*(raw as *const u8) }; + let _ = unsafe { &*(raw as *const u8) }; } unsafe fn _issue8924<'a, 'b, 'c>(x: *const &'a u32, y: *const &'b u32) -> &'c &'b u32 { diff --git a/tests/ui/transmute_ptr_to_ref.rs b/tests/ui/transmute_ptr_to_ref.rs index 4238ff80478..901a3e90dbe 100644 --- a/tests/ui/transmute_ptr_to_ref.rs +++ b/tests/ui/transmute_ptr_to_ref.rs @@ -2,6 +2,7 @@ #![warn(clippy::transmute_ptr_to_ref)] #![allow(clippy::match_single_binding)] +#![allow(unused_must_use)] unsafe fn _ptr_to_ref(p: *const T, m: *mut T, o: *const U, om: *mut U) { let _: &T = std::mem::transmute(p); @@ -38,7 +39,7 @@ fn _issue1231() { type Bar<'a> = &'a u8; let raw = 42 as *const i32; - unsafe { std::mem::transmute::<_, Bar>(raw) }; + let _ = unsafe { std::mem::transmute::<_, Bar>(raw) }; } unsafe fn _issue8924<'a, 'b, 'c>(x: *const &'a u32, y: *const &'b u32) -> &'c &'b u32 { diff --git a/tests/ui/transmute_ptr_to_ref.stderr b/tests/ui/transmute_ptr_to_ref.stderr index b3e6c09d2d7..68007edc410 100644 --- a/tests/ui/transmute_ptr_to_ref.stderr +++ b/tests/ui/transmute_ptr_to_ref.stderr @@ -1,5 +1,5 @@ error: transmute from a pointer type (`*const T`) to a reference type (`&T`) - --> $DIR/transmute_ptr_to_ref.rs:7:17 + --> $DIR/transmute_ptr_to_ref.rs:8:17 | LL | let _: &T = std::mem::transmute(p); | ^^^^^^^^^^^^^^^^^^^^^^ help: try: `&*p` @@ -7,127 +7,127 @@ LL | let _: &T = std::mem::transmute(p); = note: `-D clippy::transmute-ptr-to-ref` implied by `-D warnings` error: transmute from a pointer type (`*mut T`) to a reference type (`&mut T`) - --> $DIR/transmute_ptr_to_ref.rs:10:21 + --> $DIR/transmute_ptr_to_ref.rs:11:21 | LL | let _: &mut T = std::mem::transmute(m); | ^^^^^^^^^^^^^^^^^^^^^^ help: try: `&mut *m` error: transmute from a pointer type (`*mut T`) to a reference type (`&T`) - --> $DIR/transmute_ptr_to_ref.rs:13:17 + --> $DIR/transmute_ptr_to_ref.rs:14:17 | LL | let _: &T = std::mem::transmute(m); | ^^^^^^^^^^^^^^^^^^^^^^ help: try: `&*m` error: transmute from a pointer type (`*mut T`) to a reference type (`&mut T`) - --> $DIR/transmute_ptr_to_ref.rs:16:21 + --> $DIR/transmute_ptr_to_ref.rs:17:21 | LL | let _: &mut T = std::mem::transmute(p as *mut T); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `&mut *(p as *mut T)` error: transmute from a pointer type (`*const U`) to a reference type (`&T`) - --> $DIR/transmute_ptr_to_ref.rs:19:17 + --> $DIR/transmute_ptr_to_ref.rs:20:17 | LL | let _: &T = std::mem::transmute(o); | ^^^^^^^^^^^^^^^^^^^^^^ help: try: `&*(o as *const T)` error: transmute from a pointer type (`*mut U`) to a reference type (`&mut T`) - --> $DIR/transmute_ptr_to_ref.rs:22:21 + --> $DIR/transmute_ptr_to_ref.rs:23:21 | LL | let _: &mut T = std::mem::transmute(om); | ^^^^^^^^^^^^^^^^^^^^^^^ help: try: `&mut *(om as *mut T)` error: transmute from a pointer type (`*mut U`) to a reference type (`&T`) - --> $DIR/transmute_ptr_to_ref.rs:25:17 + --> $DIR/transmute_ptr_to_ref.rs:26:17 | LL | let _: &T = std::mem::transmute(om); | ^^^^^^^^^^^^^^^^^^^^^^^ help: try: `&*(om as *const T)` error: transmute from a pointer type (`*const i32`) to a reference type (`&_issue1231::Foo<'_, u8>`) - --> $DIR/transmute_ptr_to_ref.rs:35:32 + --> $DIR/transmute_ptr_to_ref.rs:36:32 | LL | let _: &Foo = unsafe { std::mem::transmute::<_, &Foo<_>>(raw) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `&*raw.cast::>()` error: transmute from a pointer type (`*const i32`) to a reference type (`&_issue1231::Foo<'_, &u8>`) - --> $DIR/transmute_ptr_to_ref.rs:37:33 + --> $DIR/transmute_ptr_to_ref.rs:38:33 | LL | let _: &Foo<&u8> = unsafe { std::mem::transmute::<_, &Foo<&_>>(raw) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `&*raw.cast::>()` error: transmute from a pointer type (`*const i32`) to a reference type (`&u8`) - --> $DIR/transmute_ptr_to_ref.rs:41:14 + --> $DIR/transmute_ptr_to_ref.rs:42:22 | -LL | unsafe { std::mem::transmute::<_, Bar>(raw) }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `&*(raw as *const u8)` +LL | let _ = unsafe { std::mem::transmute::<_, Bar>(raw) }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `&*(raw as *const u8)` error: transmute from a pointer type (`*const &u32`) to a reference type (`&&u32`) - --> $DIR/transmute_ptr_to_ref.rs:46:14 + --> $DIR/transmute_ptr_to_ref.rs:47:14 | LL | 0 => std::mem::transmute(x), | ^^^^^^^^^^^^^^^^^^^^^^ help: try: `&*x.cast::<&u32>()` error: transmute from a pointer type (`*const &u32`) to a reference type (`&&u32`) - --> $DIR/transmute_ptr_to_ref.rs:47:14 + --> $DIR/transmute_ptr_to_ref.rs:48:14 | LL | 1 => std::mem::transmute(y), | ^^^^^^^^^^^^^^^^^^^^^^ help: try: `&*y.cast::<&u32>()` error: transmute from a pointer type (`*const &u32`) to a reference type (`&&u32`) - --> $DIR/transmute_ptr_to_ref.rs:48:14 + --> $DIR/transmute_ptr_to_ref.rs:49:14 | LL | 2 => std::mem::transmute::<_, &&'b u32>(x), | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `&*x.cast::<&'b u32>()` error: transmute from a pointer type (`*const &u32`) to a reference type (`&&u32`) - --> $DIR/transmute_ptr_to_ref.rs:49:14 + --> $DIR/transmute_ptr_to_ref.rs:50:14 | LL | _ => std::mem::transmute::<_, &&'b u32>(y), | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `&*y.cast::<&'b u32>()` error: transmute from a pointer type (`*const u32`) to a reference type (`&u32`) - --> $DIR/transmute_ptr_to_ref.rs:57:19 + --> $DIR/transmute_ptr_to_ref.rs:58:19 | LL | let _: &u32 = std::mem::transmute(a); | ^^^^^^^^^^^^^^^^^^^^^^ help: try: `&*a` error: transmute from a pointer type (`*const u32`) to a reference type (`&u32`) - --> $DIR/transmute_ptr_to_ref.rs:58:19 + --> $DIR/transmute_ptr_to_ref.rs:59:19 | LL | let _: &u32 = std::mem::transmute::<_, &u32>(a); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `&*a.cast::()` error: transmute from a pointer type (`*const &u32`) to a reference type (`&&u32`) - --> $DIR/transmute_ptr_to_ref.rs:60:14 + --> $DIR/transmute_ptr_to_ref.rs:61:14 | LL | 0 => std::mem::transmute(x), | ^^^^^^^^^^^^^^^^^^^^^^ help: try: `&*x.cast::<&u32>()` error: transmute from a pointer type (`*const &u32`) to a reference type (`&&u32`) - --> $DIR/transmute_ptr_to_ref.rs:61:14 + --> $DIR/transmute_ptr_to_ref.rs:62:14 | LL | _ => std::mem::transmute::<_, &&'b u32>(x), | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `&*x.cast::<&'b u32>()` error: transmute from a pointer type (`*const u32`) to a reference type (`&u32`) - --> $DIR/transmute_ptr_to_ref.rs:69:19 + --> $DIR/transmute_ptr_to_ref.rs:70:19 | LL | let _: &u32 = std::mem::transmute(a); | ^^^^^^^^^^^^^^^^^^^^^^ help: try: `&*a` error: transmute from a pointer type (`*const u32`) to a reference type (`&u32`) - --> $DIR/transmute_ptr_to_ref.rs:70:19 + --> $DIR/transmute_ptr_to_ref.rs:71:19 | LL | let _: &u32 = std::mem::transmute::<_, &u32>(a); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `&*(a as *const u32)` error: transmute from a pointer type (`*const &u32`) to a reference type (`&&u32`) - --> $DIR/transmute_ptr_to_ref.rs:72:14 + --> $DIR/transmute_ptr_to_ref.rs:73:14 | LL | 0 => std::mem::transmute(x), | ^^^^^^^^^^^^^^^^^^^^^^ help: try: `&*(x as *const () as *const &u32)` error: transmute from a pointer type (`*const &u32`) to a reference type (`&&u32`) - --> $DIR/transmute_ptr_to_ref.rs:73:14 + --> $DIR/transmute_ptr_to_ref.rs:74:14 | LL | _ => std::mem::transmute::<_, &&'b u32>(x), | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `&*(x as *const () as *const &'b u32)` From a899034927da107f4c51e9055f8c0e194c776228 Mon Sep 17 00:00:00 2001 From: Centri3 <114838443+Centri3@users.noreply.github.com> Date: Wed, 14 Jun 2023 07:12:25 -0500 Subject: [PATCH 197/310] Don't lint `excessive_precision` on inf --- clippy_lints/src/float_literal.rs | 11 ++++++++--- tests/ui/excessive_precision.fixed | 15 ++++++++++++++- tests/ui/excessive_precision.rs | 15 ++++++++++++++- tests/ui/excessive_precision.stderr | 30 ++++++++++++++--------------- tests/ui/lossy_float_literal.fixed | 4 ++++ tests/ui/lossy_float_literal.rs | 4 ++++ tests/ui/lossy_float_literal.stderr | 22 ++++++++++----------- 7 files changed, 70 insertions(+), 31 deletions(-) diff --git a/clippy_lints/src/float_literal.rs b/clippy_lints/src/float_literal.rs index 93bf50fd5e7..d182bb62195 100644 --- a/clippy_lints/src/float_literal.rs +++ b/clippy_lints/src/float_literal.rs @@ -82,19 +82,24 @@ impl<'tcx> LateLintPass<'tcx> for FloatLiteral { LitFloatType::Suffixed(ast::FloatTy::F64) => Some("f64"), LitFloatType::Unsuffixed => None }; - let (is_whole, mut float_str) = match fty { + let (is_whole, is_inf, mut float_str) = match fty { FloatTy::F32 => { let value = sym_str.parse::().unwrap(); - (value.fract() == 0.0, formatter.format(value)) + (value.fract() == 0.0, value.is_infinite(), formatter.format(value)) }, FloatTy::F64 => { let value = sym_str.parse::().unwrap(); - (value.fract() == 0.0, formatter.format(value)) + + (value.fract() == 0.0, value.is_infinite(), formatter.format(value)) }, }; + if is_inf { + return; + } + if is_whole && !sym_str.contains(|c| c == 'e' || c == 'E') { // Normalize the literal by stripping the fractional portion if sym_str.split('.').next().unwrap() != float_str { diff --git a/tests/ui/excessive_precision.fixed b/tests/ui/excessive_precision.fixed index 1bcaa33a049..7bb4da453c1 100644 --- a/tests/ui/excessive_precision.fixed +++ b/tests/ui/excessive_precision.fixed @@ -1,6 +1,12 @@ //@run-rustfix #![warn(clippy::excessive_precision)] -#![allow(dead_code, unused_variables, clippy::print_literal, clippy::useless_vec)] +#![allow( + dead_code, + overflowing_literals, + unused_variables, + clippy::print_literal, + clippy::useless_vec +)] fn main() { // Consts @@ -66,4 +72,11 @@ fn main() { // issue #7745 let _ = 0_f64; + + // issue #9910 + const INF1: f32 = 1.0e+33f32; + const INF2: f64 = 1.0e+3300f64; + const NEG_INF1: f32 = -1.0e+33f32; + const NEG_INF2: f64 = -1.0e+3300f64; + const NEG_INF3: f32 = -3.40282357e+38_f32; } diff --git a/tests/ui/excessive_precision.rs b/tests/ui/excessive_precision.rs index cee937e07e1..e8d6ab6870a 100644 --- a/tests/ui/excessive_precision.rs +++ b/tests/ui/excessive_precision.rs @@ -1,6 +1,12 @@ //@run-rustfix #![warn(clippy::excessive_precision)] -#![allow(dead_code, unused_variables, clippy::print_literal, clippy::useless_vec)] +#![allow( + dead_code, + overflowing_literals, + unused_variables, + clippy::print_literal, + clippy::useless_vec +)] fn main() { // Consts @@ -66,4 +72,11 @@ fn main() { // issue #7745 let _ = 1.000_000_000_000_001e-324_f64; + + // issue #9910 + const INF1: f32 = 1.0e+33f32; + const INF2: f64 = 1.0e+3300f64; + const NEG_INF1: f32 = -1.0e+33f32; + const NEG_INF2: f64 = -1.0e+3300f64; + const NEG_INF3: f32 = -3.40282357e+38_f32; } diff --git a/tests/ui/excessive_precision.stderr b/tests/ui/excessive_precision.stderr index 42d9d4de193..348ad183d7d 100644 --- a/tests/ui/excessive_precision.stderr +++ b/tests/ui/excessive_precision.stderr @@ -1,5 +1,5 @@ error: float has excessive precision - --> $DIR/excessive_precision.rs:15:26 + --> $DIR/excessive_precision.rs:21:26 | LL | const BAD32_1: f32 = 0.123_456_789_f32; | ^^^^^^^^^^^^^^^^^ help: consider changing the type or truncating it to: `0.123_456_79_f32` @@ -7,85 +7,85 @@ LL | const BAD32_1: f32 = 0.123_456_789_f32; = note: `-D clippy::excessive-precision` implied by `-D warnings` error: float has excessive precision - --> $DIR/excessive_precision.rs:16:26 + --> $DIR/excessive_precision.rs:22:26 | LL | const BAD32_2: f32 = 0.123_456_789; | ^^^^^^^^^^^^^ help: consider changing the type or truncating it to: `0.123_456_79` error: float has excessive precision - --> $DIR/excessive_precision.rs:17:26 + --> $DIR/excessive_precision.rs:23:26 | LL | const BAD32_3: f32 = 0.100_000_000_000_1; | ^^^^^^^^^^^^^^^^^^^ help: consider changing the type or truncating it to: `0.1` error: float has excessive precision - --> $DIR/excessive_precision.rs:18:29 + --> $DIR/excessive_precision.rs:24:29 | LL | const BAD32_EDGE: f32 = 1.000_000_9; | ^^^^^^^^^^^ help: consider changing the type or truncating it to: `1.000_001` error: float has excessive precision - --> $DIR/excessive_precision.rs:22:26 + --> $DIR/excessive_precision.rs:28:26 | LL | const BAD64_3: f64 = 0.100_000_000_000_000_000_1; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider changing the type or truncating it to: `0.1` error: float has excessive precision - --> $DIR/excessive_precision.rs:25:22 + --> $DIR/excessive_precision.rs:31:22 | LL | println!("{:?}", 8.888_888_888_888_888_888_888); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider changing the type or truncating it to: `8.888_888_888_888_89` error: float has excessive precision - --> $DIR/excessive_precision.rs:36:22 + --> $DIR/excessive_precision.rs:42:22 | LL | let bad32: f32 = 1.123_456_789; | ^^^^^^^^^^^^^ help: consider changing the type or truncating it to: `1.123_456_8` error: float has excessive precision - --> $DIR/excessive_precision.rs:37:26 + --> $DIR/excessive_precision.rs:43:26 | LL | let bad32_suf: f32 = 1.123_456_789_f32; | ^^^^^^^^^^^^^^^^^ help: consider changing the type or truncating it to: `1.123_456_8_f32` error: float has excessive precision - --> $DIR/excessive_precision.rs:38:21 + --> $DIR/excessive_precision.rs:44:21 | LL | let bad32_inf = 1.123_456_789_f32; | ^^^^^^^^^^^^^^^^^ help: consider changing the type or truncating it to: `1.123_456_8_f32` error: float has excessive precision - --> $DIR/excessive_precision.rs:48:36 + --> $DIR/excessive_precision.rs:54:36 | LL | let bad_vec32: Vec = vec![0.123_456_789]; | ^^^^^^^^^^^^^ help: consider changing the type or truncating it to: `0.123_456_79` error: float has excessive precision - --> $DIR/excessive_precision.rs:49:36 + --> $DIR/excessive_precision.rs:55:36 | LL | let bad_vec64: Vec = vec![0.123_456_789_123_456_789]; | ^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider changing the type or truncating it to: `0.123_456_789_123_456_78` error: float has excessive precision - --> $DIR/excessive_precision.rs:53:24 + --> $DIR/excessive_precision.rs:59:24 | LL | let bad_e32: f32 = 1.123_456_788_888e-10; | ^^^^^^^^^^^^^^^^^^^^^ help: consider changing the type or truncating it to: `1.123_456_8e-10` error: float has excessive precision - --> $DIR/excessive_precision.rs:56:27 + --> $DIR/excessive_precision.rs:62:27 | LL | let bad_bige32: f32 = 1.123_456_788_888E-10; | ^^^^^^^^^^^^^^^^^^^^^ help: consider changing the type or truncating it to: `1.123_456_8E-10` error: float has excessive precision - --> $DIR/excessive_precision.rs:65:13 + --> $DIR/excessive_precision.rs:71:13 | LL | let _ = 2.225_073_858_507_201_1e-308_f64; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider changing the type or truncating it to: `2.225_073_858_507_201e-308_f64` error: float has excessive precision - --> $DIR/excessive_precision.rs:68:13 + --> $DIR/excessive_precision.rs:74:13 | LL | let _ = 1.000_000_000_000_001e-324_f64; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider changing the type or truncating it to: `0_f64` diff --git a/tests/ui/lossy_float_literal.fixed b/tests/ui/lossy_float_literal.fixed index a2088575610..e19f4980cd7 100644 --- a/tests/ui/lossy_float_literal.fixed +++ b/tests/ui/lossy_float_literal.fixed @@ -1,5 +1,6 @@ //@run-rustfix #![warn(clippy::lossy_float_literal)] +#![allow(overflowing_literals, unused)] fn main() { // Lossy whole-number float literals @@ -32,4 +33,7 @@ fn main() { let _: f64 = 1e99; let _: f64 = 1E99; let _: f32 = 0.1; + + const INF1: f32 = 1000000000000000000000000000000000f32; + const NEG_INF1: f32 = -340282357000000000000000000000000000001_f32; } diff --git a/tests/ui/lossy_float_literal.rs b/tests/ui/lossy_float_literal.rs index 1a75f214c85..a2a1cfb317e 100644 --- a/tests/ui/lossy_float_literal.rs +++ b/tests/ui/lossy_float_literal.rs @@ -1,5 +1,6 @@ //@run-rustfix #![warn(clippy::lossy_float_literal)] +#![allow(overflowing_literals, unused)] fn main() { // Lossy whole-number float literals @@ -32,4 +33,7 @@ fn main() { let _: f64 = 1e99; let _: f64 = 1E99; let _: f32 = 0.1; + + const INF1: f32 = 1000000000000000000000000000000000f32; + const NEG_INF1: f32 = -340282357000000000000000000000000000001_f32; } diff --git a/tests/ui/lossy_float_literal.stderr b/tests/ui/lossy_float_literal.stderr index d2193c0c819..2d72b16430c 100644 --- a/tests/ui/lossy_float_literal.stderr +++ b/tests/ui/lossy_float_literal.stderr @@ -1,5 +1,5 @@ error: literal cannot be represented as the underlying type without loss of precision - --> $DIR/lossy_float_literal.rs:6:18 + --> $DIR/lossy_float_literal.rs:7:18 | LL | let _: f32 = 16_777_217.0; | ^^^^^^^^^^^^ help: consider changing the type or replacing it with: `16_777_216.0` @@ -7,61 +7,61 @@ LL | let _: f32 = 16_777_217.0; = note: `-D clippy::lossy-float-literal` implied by `-D warnings` error: literal cannot be represented as the underlying type without loss of precision - --> $DIR/lossy_float_literal.rs:7:18 + --> $DIR/lossy_float_literal.rs:8:18 | LL | let _: f32 = 16_777_219.0; | ^^^^^^^^^^^^ help: consider changing the type or replacing it with: `16_777_220.0` error: literal cannot be represented as the underlying type without loss of precision - --> $DIR/lossy_float_literal.rs:8:18 + --> $DIR/lossy_float_literal.rs:9:18 | LL | let _: f32 = 16_777_219.; | ^^^^^^^^^^^ help: consider changing the type or replacing it with: `16_777_220.0` error: literal cannot be represented as the underlying type without loss of precision - --> $DIR/lossy_float_literal.rs:9:18 + --> $DIR/lossy_float_literal.rs:10:18 | LL | let _: f32 = 16_777_219.000; | ^^^^^^^^^^^^^^ help: consider changing the type or replacing it with: `16_777_220.0` error: literal cannot be represented as the underlying type without loss of precision - --> $DIR/lossy_float_literal.rs:10:13 + --> $DIR/lossy_float_literal.rs:11:13 | LL | let _ = 16_777_219f32; | ^^^^^^^^^^^^^ help: consider changing the type or replacing it with: `16_777_220_f32` error: literal cannot be represented as the underlying type without loss of precision - --> $DIR/lossy_float_literal.rs:11:19 + --> $DIR/lossy_float_literal.rs:12:19 | LL | let _: f32 = -16_777_219.0; | ^^^^^^^^^^^^ help: consider changing the type or replacing it with: `16_777_220.0` error: literal cannot be represented as the underlying type without loss of precision - --> $DIR/lossy_float_literal.rs:12:18 + --> $DIR/lossy_float_literal.rs:13:18 | LL | let _: f64 = 9_007_199_254_740_993.0; | ^^^^^^^^^^^^^^^^^^^^^^^ help: consider changing the type or replacing it with: `9_007_199_254_740_992.0` error: literal cannot be represented as the underlying type without loss of precision - --> $DIR/lossy_float_literal.rs:13:18 + --> $DIR/lossy_float_literal.rs:14:18 | LL | let _: f64 = 9_007_199_254_740_993.; | ^^^^^^^^^^^^^^^^^^^^^^ help: consider changing the type or replacing it with: `9_007_199_254_740_992.0` error: literal cannot be represented as the underlying type without loss of precision - --> $DIR/lossy_float_literal.rs:14:18 + --> $DIR/lossy_float_literal.rs:15:18 | LL | let _: f64 = 9_007_199_254_740_993.00; | ^^^^^^^^^^^^^^^^^^^^^^^^ help: consider changing the type or replacing it with: `9_007_199_254_740_992.0` error: literal cannot be represented as the underlying type without loss of precision - --> $DIR/lossy_float_literal.rs:15:13 + --> $DIR/lossy_float_literal.rs:16:13 | LL | let _ = 9_007_199_254_740_993f64; | ^^^^^^^^^^^^^^^^^^^^^^^^ help: consider changing the type or replacing it with: `9_007_199_254_740_992_f64` error: literal cannot be represented as the underlying type without loss of precision - --> $DIR/lossy_float_literal.rs:16:19 + --> $DIR/lossy_float_literal.rs:17:19 | LL | let _: f64 = -9_007_199_254_740_993.0; | ^^^^^^^^^^^^^^^^^^^^^^^ help: consider changing the type or replacing it with: `9_007_199_254_740_992.0` From 67d5e6ec39a38cd4f2976b7a201d142ad6a0d09e Mon Sep 17 00:00:00 2001 From: Centri3 <114838443+Centri3@users.noreply.github.com> Date: Sun, 11 Jun 2023 02:46:28 -0500 Subject: [PATCH 198/310] add lint [`needless_clone_impl`] Update needless_impls.rs --- CHANGELOG.md | 1 + clippy_lints/src/declared_lints.rs | 1 + clippy_lints/src/lib.rs | 2 + clippy_lints/src/needless_impls.rs | 109 ++++++++++++++++++ tests/ui/clone_on_copy_impl.rs | 2 + tests/ui/derive.rs | 2 +- tests/ui/needless_clone_impl.fixed | 69 +++++++++++ tests/ui/needless_clone_impl.rs | 71 ++++++++++++ tests/ui/needless_clone_impl.stderr | 13 +++ .../unnecessary_struct_initialization.fixed | 2 +- tests/ui/unnecessary_struct_initialization.rs | 2 +- 11 files changed, 271 insertions(+), 3 deletions(-) create mode 100644 clippy_lints/src/needless_impls.rs create mode 100644 tests/ui/needless_clone_impl.fixed create mode 100644 tests/ui/needless_clone_impl.rs create mode 100644 tests/ui/needless_clone_impl.stderr diff --git a/CHANGELOG.md b/CHANGELOG.md index 218bca40cb0..c0925988ca1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5005,6 +5005,7 @@ Released 2018-09-13 [`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_clone_impl`]: https://rust-lang.github.io/rust-clippy/master/index.html#needless_clone_impl [`needless_collect`]: https://rust-lang.github.io/rust-clippy/master/index.html#needless_collect [`needless_continue`]: https://rust-lang.github.io/rust-clippy/master/index.html#needless_continue [`needless_doctest_main`]: https://rust-lang.github.io/rust-clippy/master/index.html#needless_doctest_main diff --git a/clippy_lints/src/declared_lints.rs b/clippy_lints/src/declared_lints.rs index 9509e6d016a..1fd70fce14f 100644 --- a/clippy_lints/src/declared_lints.rs +++ b/clippy_lints/src/declared_lints.rs @@ -463,6 +463,7 @@ pub(crate) static LINTS: &[&crate::LintInfo] = &[ crate::needless_else::NEEDLESS_ELSE_INFO, crate::needless_for_each::NEEDLESS_FOR_EACH_INFO, crate::needless_if::NEEDLESS_IF_INFO, + crate::needless_impls::NEEDLESS_CLONE_IMPL_INFO, crate::needless_late_init::NEEDLESS_LATE_INIT_INFO, crate::needless_parens_on_range_literals::NEEDLESS_PARENS_ON_RANGE_LITERALS_INFO, crate::needless_pass_by_value::NEEDLESS_PASS_BY_VALUE_INFO, diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index cf6499b9616..e07959849a3 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -226,6 +226,7 @@ mod needless_continue; mod needless_else; mod needless_for_each; mod needless_if; +mod needless_impls; mod needless_late_init; mod needless_parens_on_range_literals; mod needless_pass_by_value; @@ -1047,6 +1048,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: let stack_size_threshold = conf.stack_size_threshold; store.register_late_pass(move |_| Box::new(large_stack_frames::LargeStackFrames::new(stack_size_threshold))); store.register_late_pass(|_| Box::new(single_range_in_vec_init::SingleRangeInVecInit)); + store.register_late_pass(|_| Box::new(needless_impls::NeedlessImpls)); // add lints here, do not remove this comment, it's used in `new_lint` } diff --git a/clippy_lints/src/needless_impls.rs b/clippy_lints/src/needless_impls.rs new file mode 100644 index 00000000000..ccfd55886ec --- /dev/null +++ b/clippy_lints/src/needless_impls.rs @@ -0,0 +1,109 @@ +use clippy_utils::{diagnostics::span_lint_and_sugg, get_parent_node, last_path_segment, ty::implements_trait}; +use rustc_errors::Applicability; +use rustc_hir::{ExprKind, ImplItem, ImplItemKind, ItemKind, Node, UnOp}; +use rustc_hir_analysis::hir_ty_to_ty; +use rustc_lint::{LateContext, LateLintPass}; +use rustc_middle::ty::EarlyBinder; +use rustc_session::{declare_lint_pass, declare_tool_lint}; +use rustc_span::{sym, symbol}; + +declare_clippy_lint! { + /// ### What it does + /// Checks for manual implementations of `Clone` when `Copy` is already implemented. + /// + /// ### Why is this bad? + /// If both `Clone` and `Copy` are implemented, they must agree. This is done by dereferencing + /// `self` in `Clone`'s implementation. Anything else is incorrect. + /// + /// ### Example + /// ```rust,ignore + /// #[derive(Eq, PartialEq)] + /// struct A(u32); + /// + /// impl Clone for A { + /// fn clone(&self) -> Self { + /// Self(self.0) + /// } + /// } + /// + /// impl Copy for A {} + /// ``` + /// Use instead: + /// ```rust,ignore + /// #[derive(Eq, PartialEq)] + /// struct A(u32); + /// + /// impl Clone for A { + /// fn clone(&self) -> Self { + /// *self + /// } + /// } + /// + /// impl Copy for A {} + /// ``` + #[clippy::version = "1.72.0"] + pub NEEDLESS_CLONE_IMPL, + correctness, + "manual implementation of `Clone` on a `Copy` type" +} +declare_lint_pass!(NeedlessImpls => [NEEDLESS_CLONE_IMPL]); + +impl LateLintPass<'_> for NeedlessImpls { + #[expect(clippy::needless_return)] + fn check_impl_item(&mut self, cx: &LateContext<'_>, impl_item: &ImplItem<'_>) { + let node = get_parent_node(cx.tcx, impl_item.hir_id()); + let Some(Node::Item(item)) = node else { + return; + }; + let ItemKind::Impl(imp) = item.kind else { + return; + }; + let Some(trait_impl) = cx.tcx.impl_trait_ref(item.owner_id).map(EarlyBinder::skip_binder) else { + return; + }; + let trait_impl_def_id = trait_impl.def_id; + if cx.tcx.is_automatically_derived(item.owner_id.to_def_id()) { + return; + } + let ImplItemKind::Fn(_, impl_item_id) = cx.tcx.hir().impl_item(impl_item.impl_item_id()).kind else { + return; + }; + let body = cx.tcx.hir().body(impl_item_id); + let ExprKind::Block(block, ..) = body.value.kind else { + return; + }; + // Above is duplicated from the `duplicate_manual_partial_ord_impl` branch. + // Remove it while solving conflicts once that PR is merged. + + // Actual implementation; remove this comment once aforementioned PR is merged + if cx.tcx.is_diagnostic_item(sym::Clone, trait_impl_def_id) + && impl_item.ident.name == sym::clone + && let Some(copy_def_id) = cx.tcx.get_diagnostic_item(sym::Copy) + && implements_trait( + cx, + hir_ty_to_ty(cx.tcx, imp.self_ty), + copy_def_id, + trait_impl.substs, + ) + { + if block.stmts.is_empty() + && let Some(expr) = block.expr + && let ExprKind::Unary(UnOp::Deref, inner) = expr.kind + && let ExprKind::Path(qpath) = inner.kind + && last_path_segment(&qpath).ident.name == symbol::kw::SelfLower + {} else { + span_lint_and_sugg( + cx, + NEEDLESS_CLONE_IMPL, + block.span, + "manual implementation of `Clone` on a `Copy` type", + "change this to", + "{ *self }".to_owned(), + Applicability::Unspecified, + ); + + return; + } + } + } +} diff --git a/tests/ui/clone_on_copy_impl.rs b/tests/ui/clone_on_copy_impl.rs index 8f9f2a0db8c..06d8ad48446 100644 --- a/tests/ui/clone_on_copy_impl.rs +++ b/tests/ui/clone_on_copy_impl.rs @@ -1,3 +1,5 @@ +#![allow(clippy::needless_clone_impl)] + use std::fmt; use std::marker::PhantomData; diff --git a/tests/ui/derive.rs b/tests/ui/derive.rs index 843e1df8bc6..857cd379fe2 100644 --- a/tests/ui/derive.rs +++ b/tests/ui/derive.rs @@ -1,4 +1,4 @@ -#![allow(dead_code)] +#![allow(clippy::needless_clone_impl, dead_code)] #![warn(clippy::expl_impl_clone_on_copy)] #[derive(Copy)] diff --git a/tests/ui/needless_clone_impl.fixed b/tests/ui/needless_clone_impl.fixed new file mode 100644 index 00000000000..05caf485db6 --- /dev/null +++ b/tests/ui/needless_clone_impl.fixed @@ -0,0 +1,69 @@ +//@run-rustfix +#![allow(unused)] +#![no_main] + +// lint + +struct A(u32); + +impl Clone for A { + fn clone(&self) -> Self { *self } +} + +impl Copy for A {} + +// do not lint + +struct B(u32); + +impl Clone for B { + fn clone(&self) -> Self { + *self + } +} + +impl Copy for B {} + +// do not lint derived (clone's implementation is `*self` here anyway) + +#[derive(Clone, Copy)] +struct C(u32); + +// do not lint derived (fr this time) + +struct D(u32); + +#[automatically_derived] +impl Clone for D { + fn clone(&self) -> Self { + Self(self.0) + } +} + +impl Copy for D {} + +// do not lint if clone is not manually implemented + +struct E(u32); + +#[automatically_derived] +impl Clone for E { + fn clone(&self) -> Self { + Self(self.0) + } +} + +impl Copy for E {} + +// do not lint since copy has more restrictive bounds + +#[derive(Eq, PartialEq)] +struct Uwu(A); + +impl Clone for Uwu { + fn clone(&self) -> Self { + Self(self.0) + } +} + +impl Copy for Uwu {} diff --git a/tests/ui/needless_clone_impl.rs b/tests/ui/needless_clone_impl.rs new file mode 100644 index 00000000000..e30469e09e8 --- /dev/null +++ b/tests/ui/needless_clone_impl.rs @@ -0,0 +1,71 @@ +//@run-rustfix +#![allow(unused)] +#![no_main] + +// lint + +struct A(u32); + +impl Clone for A { + fn clone(&self) -> Self { + Self(self.0) + } +} + +impl Copy for A {} + +// do not lint + +struct B(u32); + +impl Clone for B { + fn clone(&self) -> Self { + *self + } +} + +impl Copy for B {} + +// do not lint derived (clone's implementation is `*self` here anyway) + +#[derive(Clone, Copy)] +struct C(u32); + +// do not lint derived (fr this time) + +struct D(u32); + +#[automatically_derived] +impl Clone for D { + fn clone(&self) -> Self { + Self(self.0) + } +} + +impl Copy for D {} + +// do not lint if clone is not manually implemented + +struct E(u32); + +#[automatically_derived] +impl Clone for E { + fn clone(&self) -> Self { + Self(self.0) + } +} + +impl Copy for E {} + +// do not lint since copy has more restrictive bounds + +#[derive(Eq, PartialEq)] +struct Uwu(A); + +impl Clone for Uwu { + fn clone(&self) -> Self { + Self(self.0) + } +} + +impl Copy for Uwu {} diff --git a/tests/ui/needless_clone_impl.stderr b/tests/ui/needless_clone_impl.stderr new file mode 100644 index 00000000000..51e2ef4f741 --- /dev/null +++ b/tests/ui/needless_clone_impl.stderr @@ -0,0 +1,13 @@ +error: manual implementation of `Clone` on a `Copy` type + --> $DIR/needless_clone_impl.rs:10:29 + | +LL | fn clone(&self) -> Self { + | _____________________________^ +LL | | Self(self.0) +LL | | } + | |_____^ help: change this to: `{ *self }` + | + = note: `#[deny(clippy::needless_clone_impl)]` on by default + +error: aborting due to previous error + diff --git a/tests/ui/unnecessary_struct_initialization.fixed b/tests/ui/unnecessary_struct_initialization.fixed index bdf746cf2c4..aec9725c4b9 100644 --- a/tests/ui/unnecessary_struct_initialization.fixed +++ b/tests/ui/unnecessary_struct_initialization.fixed @@ -1,6 +1,6 @@ //@run-rustfix -#![allow(unused)] +#![allow(clippy::needless_clone_impl, unused)] #![warn(clippy::unnecessary_struct_initialization)] struct S { diff --git a/tests/ui/unnecessary_struct_initialization.rs b/tests/ui/unnecessary_struct_initialization.rs index 7271e2f957a..a3b9b88dbc2 100644 --- a/tests/ui/unnecessary_struct_initialization.rs +++ b/tests/ui/unnecessary_struct_initialization.rs @@ -1,6 +1,6 @@ //@run-rustfix -#![allow(unused)] +#![allow(clippy::needless_clone_impl, unused)] #![warn(clippy::unnecessary_struct_initialization)] struct S { From 10cc1684ceca90f84a42099f09cf0737a7aca35b Mon Sep 17 00:00:00 2001 From: Centri3 <114838443+Centri3@users.noreply.github.com> Date: Tue, 13 Jun 2023 05:25:49 -0500 Subject: [PATCH 199/310] rename lint and disallow `clone_from` --- CHANGELOG.md | 2 +- clippy_lints/src/declared_lints.rs | 2 +- .../{needless_impls.rs => incorrect_impls.rs} | 47 ++++++++++++------- clippy_lints/src/lib.rs | 4 +- tests/ui/clone_on_copy_impl.rs | 2 +- tests/ui/derive.rs | 2 +- ...> incorrect_clone_impl_on_copy_type.fixed} | 30 +++++++++++- ...s => incorrect_clone_impl_on_copy_type.rs} | 38 ++++++++++++++- .../incorrect_clone_impl_on_copy_type.stderr | 40 ++++++++++++++++ tests/ui/needless_clone_impl.stderr | 13 ----- .../unnecessary_struct_initialization.fixed | 2 +- tests/ui/unnecessary_struct_initialization.rs | 2 +- 12 files changed, 145 insertions(+), 39 deletions(-) rename clippy_lints/src/{needless_impls.rs => incorrect_impls.rs} (69%) rename tests/ui/{needless_clone_impl.fixed => incorrect_clone_impl_on_copy_type.fixed} (66%) rename tests/ui/{needless_clone_impl.rs => incorrect_clone_impl_on_copy_type.rs} (58%) create mode 100644 tests/ui/incorrect_clone_impl_on_copy_type.stderr delete mode 100644 tests/ui/needless_clone_impl.stderr diff --git a/CHANGELOG.md b/CHANGELOG.md index c0925988ca1..445e2366cc3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4833,6 +4833,7 @@ Released 2018-09-13 [`imprecise_flops`]: https://rust-lang.github.io/rust-clippy/master/index.html#imprecise_flops [`inconsistent_digit_grouping`]: https://rust-lang.github.io/rust-clippy/master/index.html#inconsistent_digit_grouping [`inconsistent_struct_constructor`]: https://rust-lang.github.io/rust-clippy/master/index.html#inconsistent_struct_constructor +[`incorrect_clone_impl_on_copy_type`]: https://rust-lang.github.io/rust-clippy/master/index.html#incorrect_clone_impl_on_copy_type [`index_refutable_slice`]: https://rust-lang.github.io/rust-clippy/master/index.html#index_refutable_slice [`indexing_slicing`]: https://rust-lang.github.io/rust-clippy/master/index.html#indexing_slicing [`ineffective_bit_mask`]: https://rust-lang.github.io/rust-clippy/master/index.html#ineffective_bit_mask @@ -5005,7 +5006,6 @@ Released 2018-09-13 [`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_clone_impl`]: https://rust-lang.github.io/rust-clippy/master/index.html#needless_clone_impl [`needless_collect`]: https://rust-lang.github.io/rust-clippy/master/index.html#needless_collect [`needless_continue`]: https://rust-lang.github.io/rust-clippy/master/index.html#needless_continue [`needless_doctest_main`]: https://rust-lang.github.io/rust-clippy/master/index.html#needless_doctest_main diff --git a/clippy_lints/src/declared_lints.rs b/clippy_lints/src/declared_lints.rs index 1fd70fce14f..2690336648d 100644 --- a/clippy_lints/src/declared_lints.rs +++ b/clippy_lints/src/declared_lints.rs @@ -206,6 +206,7 @@ pub(crate) static LINTS: &[&crate::LintInfo] = &[ crate::implicit_saturating_add::IMPLICIT_SATURATING_ADD_INFO, crate::implicit_saturating_sub::IMPLICIT_SATURATING_SUB_INFO, crate::inconsistent_struct_constructor::INCONSISTENT_STRUCT_CONSTRUCTOR_INFO, + crate::incorrect_impls::INCORRECT_CLONE_IMPL_ON_COPY_TYPE_INFO, crate::index_refutable_slice::INDEX_REFUTABLE_SLICE_INFO, crate::indexing_slicing::INDEXING_SLICING_INFO, crate::indexing_slicing::OUT_OF_BOUNDS_INDEXING_INFO, @@ -463,7 +464,6 @@ pub(crate) static LINTS: &[&crate::LintInfo] = &[ crate::needless_else::NEEDLESS_ELSE_INFO, crate::needless_for_each::NEEDLESS_FOR_EACH_INFO, crate::needless_if::NEEDLESS_IF_INFO, - crate::needless_impls::NEEDLESS_CLONE_IMPL_INFO, crate::needless_late_init::NEEDLESS_LATE_INIT_INFO, crate::needless_parens_on_range_literals::NEEDLESS_PARENS_ON_RANGE_LITERALS_INFO, crate::needless_pass_by_value::NEEDLESS_PASS_BY_VALUE_INFO, diff --git a/clippy_lints/src/needless_impls.rs b/clippy_lints/src/incorrect_impls.rs similarity index 69% rename from clippy_lints/src/needless_impls.rs rename to clippy_lints/src/incorrect_impls.rs index ccfd55886ec..13cc0b23ba3 100644 --- a/clippy_lints/src/needless_impls.rs +++ b/clippy_lints/src/incorrect_impls.rs @@ -42,13 +42,13 @@ declare_clippy_lint! { /// impl Copy for A {} /// ``` #[clippy::version = "1.72.0"] - pub NEEDLESS_CLONE_IMPL, + pub INCORRECT_CLONE_IMPL_ON_COPY_TYPE, correctness, "manual implementation of `Clone` on a `Copy` type" } -declare_lint_pass!(NeedlessImpls => [NEEDLESS_CLONE_IMPL]); +declare_lint_pass!(IncorrectImpls => [INCORRECT_CLONE_IMPL_ON_COPY_TYPE]); -impl LateLintPass<'_> for NeedlessImpls { +impl LateLintPass<'_> for IncorrectImpls { #[expect(clippy::needless_return)] fn check_impl_item(&mut self, cx: &LateContext<'_>, impl_item: &ImplItem<'_>) { let node = get_parent_node(cx.tcx, impl_item.hir_id()); @@ -77,7 +77,6 @@ impl LateLintPass<'_> for NeedlessImpls { // Actual implementation; remove this comment once aforementioned PR is merged if cx.tcx.is_diagnostic_item(sym::Clone, trait_impl_def_id) - && impl_item.ident.name == sym::clone && let Some(copy_def_id) = cx.tcx.get_diagnostic_item(sym::Copy) && implements_trait( cx, @@ -86,20 +85,36 @@ impl LateLintPass<'_> for NeedlessImpls { trait_impl.substs, ) { - if block.stmts.is_empty() - && let Some(expr) = block.expr - && let ExprKind::Unary(UnOp::Deref, inner) = expr.kind - && let ExprKind::Path(qpath) = inner.kind - && last_path_segment(&qpath).ident.name == symbol::kw::SelfLower - {} else { + if impl_item.ident.name == sym::clone { + if block.stmts.is_empty() + && let Some(expr) = block.expr + && let ExprKind::Unary(UnOp::Deref, inner) = expr.kind + && let ExprKind::Path(qpath) = inner.kind + && last_path_segment(&qpath).ident.name == symbol::kw::SelfLower + {} else { + span_lint_and_sugg( + cx, + INCORRECT_CLONE_IMPL_ON_COPY_TYPE, + block.span, + "incorrect implementation of `clone` on a `Copy` type", + "change this to", + "{ *self }".to_owned(), + Applicability::MaybeIncorrect, + ); + + return; + } + } + + if impl_item.ident.name == sym::clone_from { span_lint_and_sugg( cx, - NEEDLESS_CLONE_IMPL, - block.span, - "manual implementation of `Clone` on a `Copy` type", - "change this to", - "{ *self }".to_owned(), - Applicability::Unspecified, + INCORRECT_CLONE_IMPL_ON_COPY_TYPE, + impl_item.span, + "incorrect implementation of `clone_from` on a `Copy` type", + "remove this", + String::new(), + Applicability::MaybeIncorrect, ); return; diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index e07959849a3..b254c05d48b 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -150,6 +150,7 @@ mod implicit_return; mod implicit_saturating_add; mod implicit_saturating_sub; mod inconsistent_struct_constructor; +mod incorrect_impls; mod index_refutable_slice; mod indexing_slicing; mod infinite_iter; @@ -226,7 +227,6 @@ mod needless_continue; mod needless_else; mod needless_for_each; mod needless_if; -mod needless_impls; mod needless_late_init; mod needless_parens_on_range_literals; mod needless_pass_by_value; @@ -1048,7 +1048,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: let stack_size_threshold = conf.stack_size_threshold; store.register_late_pass(move |_| Box::new(large_stack_frames::LargeStackFrames::new(stack_size_threshold))); store.register_late_pass(|_| Box::new(single_range_in_vec_init::SingleRangeInVecInit)); - store.register_late_pass(|_| Box::new(needless_impls::NeedlessImpls)); + store.register_late_pass(|_| Box::new(incorrect_impls::IncorrectImpls)); // add lints here, do not remove this comment, it's used in `new_lint` } diff --git a/tests/ui/clone_on_copy_impl.rs b/tests/ui/clone_on_copy_impl.rs index 06d8ad48446..b7c186bef77 100644 --- a/tests/ui/clone_on_copy_impl.rs +++ b/tests/ui/clone_on_copy_impl.rs @@ -1,4 +1,4 @@ -#![allow(clippy::needless_clone_impl)] +#![allow(clippy::incorrect_clone_impl_on_copy_type)] use std::fmt; use std::marker::PhantomData; diff --git a/tests/ui/derive.rs b/tests/ui/derive.rs index 857cd379fe2..44e18bff83f 100644 --- a/tests/ui/derive.rs +++ b/tests/ui/derive.rs @@ -1,4 +1,4 @@ -#![allow(clippy::needless_clone_impl, dead_code)] +#![allow(clippy::incorrect_clone_impl_on_copy_type, dead_code)] #![warn(clippy::expl_impl_clone_on_copy)] #[derive(Copy)] diff --git a/tests/ui/needless_clone_impl.fixed b/tests/ui/incorrect_clone_impl_on_copy_type.fixed similarity index 66% rename from tests/ui/needless_clone_impl.fixed rename to tests/ui/incorrect_clone_impl_on_copy_type.fixed index 05caf485db6..ac482dcda1e 100644 --- a/tests/ui/needless_clone_impl.fixed +++ b/tests/ui/incorrect_clone_impl_on_copy_type.fixed @@ -1,5 +1,5 @@ //@run-rustfix -#![allow(unused)] +#![allow(clippy::clone_on_copy, unused)] #![no_main] // lint @@ -8,6 +8,8 @@ struct A(u32); impl Clone for A { fn clone(&self) -> Self { *self } + + } impl Copy for A {} @@ -38,6 +40,11 @@ impl Clone for D { fn clone(&self) -> Self { Self(self.0) } + + fn clone_from(&mut self, source: &Self) { + source.clone(); + *self = source.clone(); + } } impl Copy for D {} @@ -51,10 +58,26 @@ impl Clone for E { fn clone(&self) -> Self { Self(self.0) } + + fn clone_from(&mut self, source: &Self) { + source.clone(); + *self = source.clone(); + } } impl Copy for E {} +// lint since clone is not derived + +#[derive(Copy)] +struct F(u32); + +impl Clone for F { + fn clone(&self) -> Self { *self } + + +} + // do not lint since copy has more restrictive bounds #[derive(Eq, PartialEq)] @@ -64,6 +87,11 @@ impl Clone for Uwu { fn clone(&self) -> Self { Self(self.0) } + + fn clone_from(&mut self, source: &Self) { + source.clone(); + *self = source.clone(); + } } impl Copy for Uwu {} diff --git a/tests/ui/needless_clone_impl.rs b/tests/ui/incorrect_clone_impl_on_copy_type.rs similarity index 58% rename from tests/ui/needless_clone_impl.rs rename to tests/ui/incorrect_clone_impl_on_copy_type.rs index e30469e09e8..00775874ff5 100644 --- a/tests/ui/needless_clone_impl.rs +++ b/tests/ui/incorrect_clone_impl_on_copy_type.rs @@ -1,5 +1,5 @@ //@run-rustfix -#![allow(unused)] +#![allow(clippy::clone_on_copy, unused)] #![no_main] // lint @@ -10,6 +10,11 @@ impl Clone for A { fn clone(&self) -> Self { Self(self.0) } + + fn clone_from(&mut self, source: &Self) { + source.clone(); + *self = source.clone(); + } } impl Copy for A {} @@ -40,6 +45,11 @@ impl Clone for D { fn clone(&self) -> Self { Self(self.0) } + + fn clone_from(&mut self, source: &Self) { + source.clone(); + *self = source.clone(); + } } impl Copy for D {} @@ -53,10 +63,31 @@ impl Clone for E { fn clone(&self) -> Self { Self(self.0) } + + fn clone_from(&mut self, source: &Self) { + source.clone(); + *self = source.clone(); + } } impl Copy for E {} +// lint since clone is not derived + +#[derive(Copy)] +struct F(u32); + +impl Clone for F { + fn clone(&self) -> Self { + Self(self.0) + } + + fn clone_from(&mut self, source: &Self) { + source.clone(); + *self = source.clone(); + } +} + // do not lint since copy has more restrictive bounds #[derive(Eq, PartialEq)] @@ -66,6 +97,11 @@ impl Clone for Uwu { fn clone(&self) -> Self { Self(self.0) } + + fn clone_from(&mut self, source: &Self) { + source.clone(); + *self = source.clone(); + } } impl Copy for Uwu {} diff --git a/tests/ui/incorrect_clone_impl_on_copy_type.stderr b/tests/ui/incorrect_clone_impl_on_copy_type.stderr new file mode 100644 index 00000000000..0021841aa86 --- /dev/null +++ b/tests/ui/incorrect_clone_impl_on_copy_type.stderr @@ -0,0 +1,40 @@ +error: incorrect implementation of `clone` on a `Copy` type + --> $DIR/incorrect_clone_impl_on_copy_type.rs:10:29 + | +LL | fn clone(&self) -> Self { + | _____________________________^ +LL | | Self(self.0) +LL | | } + | |_____^ help: change this to: `{ *self }` + | + = note: `#[deny(clippy::incorrect_clone_impl_on_copy_type)]` on by default + +error: incorrect implementation of `clone_from` on a `Copy` type + --> $DIR/incorrect_clone_impl_on_copy_type.rs:14:5 + | +LL | / fn clone_from(&mut self, source: &Self) { +LL | | source.clone(); +LL | | *self = source.clone(); +LL | | } + | |_____^ help: remove this + +error: incorrect implementation of `clone` on a `Copy` type + --> $DIR/incorrect_clone_impl_on_copy_type.rs:81:29 + | +LL | fn clone(&self) -> Self { + | _____________________________^ +LL | | Self(self.0) +LL | | } + | |_____^ help: change this to: `{ *self }` + +error: incorrect implementation of `clone_from` on a `Copy` type + --> $DIR/incorrect_clone_impl_on_copy_type.rs:85:5 + | +LL | / fn clone_from(&mut self, source: &Self) { +LL | | source.clone(); +LL | | *self = source.clone(); +LL | | } + | |_____^ help: remove this + +error: aborting due to 4 previous errors + diff --git a/tests/ui/needless_clone_impl.stderr b/tests/ui/needless_clone_impl.stderr deleted file mode 100644 index 51e2ef4f741..00000000000 --- a/tests/ui/needless_clone_impl.stderr +++ /dev/null @@ -1,13 +0,0 @@ -error: manual implementation of `Clone` on a `Copy` type - --> $DIR/needless_clone_impl.rs:10:29 - | -LL | fn clone(&self) -> Self { - | _____________________________^ -LL | | Self(self.0) -LL | | } - | |_____^ help: change this to: `{ *self }` - | - = note: `#[deny(clippy::needless_clone_impl)]` on by default - -error: aborting due to previous error - diff --git a/tests/ui/unnecessary_struct_initialization.fixed b/tests/ui/unnecessary_struct_initialization.fixed index aec9725c4b9..eae1271d1aa 100644 --- a/tests/ui/unnecessary_struct_initialization.fixed +++ b/tests/ui/unnecessary_struct_initialization.fixed @@ -1,6 +1,6 @@ //@run-rustfix -#![allow(clippy::needless_clone_impl, unused)] +#![allow(clippy::incorrect_clone_impl_on_copy_type, unused)] #![warn(clippy::unnecessary_struct_initialization)] struct S { diff --git a/tests/ui/unnecessary_struct_initialization.rs b/tests/ui/unnecessary_struct_initialization.rs index a3b9b88dbc2..4abd560f84b 100644 --- a/tests/ui/unnecessary_struct_initialization.rs +++ b/tests/ui/unnecessary_struct_initialization.rs @@ -1,6 +1,6 @@ //@run-rustfix -#![allow(clippy::needless_clone_impl, unused)] +#![allow(clippy::incorrect_clone_impl_on_copy_type, unused)] #![warn(clippy::unnecessary_struct_initialization)] struct S { From 2748ab9565100dedfe170c899fe1f7f0791677d2 Mon Sep 17 00:00:00 2001 From: y21 <30553356+y21@users.noreply.github.com> Date: Sat, 27 May 2023 00:58:44 +0200 Subject: [PATCH 200/310] new lint: `drain_collect` --- CHANGELOG.md | 1 + clippy_lints/src/declared_lints.rs | 1 + clippy_lints/src/methods/drain_collect.rs | 77 +++++++++++++++++++++++ clippy_lints/src/methods/mod.rs | 41 ++++++++++++ tests/ui/drain_collect.rs | 65 +++++++++++++++++++ tests/ui/drain_collect.stderr | 62 ++++++++++++++++++ tests/ui/iter_with_drain.fixed | 2 +- tests/ui/iter_with_drain.rs | 2 +- 8 files changed, 249 insertions(+), 2 deletions(-) create mode 100644 clippy_lints/src/methods/drain_collect.rs create mode 100644 tests/ui/drain_collect.rs create mode 100644 tests/ui/drain_collect.stderr diff --git a/CHANGELOG.md b/CHANGELOG.md index 218bca40cb0..ad7a101d38a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4737,6 +4737,7 @@ Released 2018-09-13 [`double_must_use`]: https://rust-lang.github.io/rust-clippy/master/index.html#double_must_use [`double_neg`]: https://rust-lang.github.io/rust-clippy/master/index.html#double_neg [`double_parens`]: https://rust-lang.github.io/rust-clippy/master/index.html#double_parens +[`drain_collect`]: https://rust-lang.github.io/rust-clippy/master/index.html#drain_collect [`drop_bounds`]: https://rust-lang.github.io/rust-clippy/master/index.html#drop_bounds [`drop_copy`]: https://rust-lang.github.io/rust-clippy/master/index.html#drop_copy [`drop_non_drop`]: https://rust-lang.github.io/rust-clippy/master/index.html#drop_non_drop diff --git a/clippy_lints/src/declared_lints.rs b/clippy_lints/src/declared_lints.rs index 9509e6d016a..b726f343ffe 100644 --- a/clippy_lints/src/declared_lints.rs +++ b/clippy_lints/src/declared_lints.rs @@ -324,6 +324,7 @@ pub(crate) static LINTS: &[&crate::LintInfo] = &[ crate::methods::CLONE_ON_COPY_INFO, crate::methods::CLONE_ON_REF_PTR_INFO, crate::methods::COLLAPSIBLE_STR_REPLACE_INFO, + crate::methods::DRAIN_COLLECT_INFO, crate::methods::ERR_EXPECT_INFO, crate::methods::EXPECT_FUN_CALL_INFO, crate::methods::EXPECT_USED_INFO, diff --git a/clippy_lints/src/methods/drain_collect.rs b/clippy_lints/src/methods/drain_collect.rs new file mode 100644 index 00000000000..6d9df587518 --- /dev/null +++ b/clippy_lints/src/methods/drain_collect.rs @@ -0,0 +1,77 @@ +use crate::methods::DRAIN_COLLECT; +use clippy_utils::diagnostics::span_lint_and_sugg; +use clippy_utils::is_range_full; +use clippy_utils::source::snippet; +use clippy_utils::ty::is_type_lang_item; +use rustc_errors::Applicability; +use rustc_hir::Expr; +use rustc_hir::ExprKind; +use rustc_hir::LangItem; +use rustc_hir::Path; +use rustc_hir::QPath; +use rustc_lint::LateContext; +use rustc_middle::query::Key; +use rustc_middle::ty::Ty; +use rustc_span::sym; +use rustc_span::Symbol; + +/// Checks if both types match the given diagnostic item, e.g.: +/// +/// `vec![1,2].drain(..).collect::>()` +/// ^^^^^^^^^ ^^^^^^ true +/// `vec![1,2].drain(..).collect::>()` +/// ^^^^^^^^^ ^^^^^^^^^^ false +fn types_match_diagnostic_item(cx: &LateContext<'_>, expr: Ty<'_>, recv: Ty<'_>, sym: Symbol) -> bool { + if let Some(expr_adt_did) = expr.ty_adt_id() + && let Some(recv_adt_did) = recv.ty_adt_id() + { + cx.tcx.is_diagnostic_item(sym, expr_adt_did) && cx.tcx.is_diagnostic_item(sym, recv_adt_did) + } else { + false + } +} + +/// Checks `std::{vec::Vec, collections::VecDeque}`. +fn check_vec(cx: &LateContext<'_>, args: &[Expr<'_>], expr: Ty<'_>, recv: Ty<'_>, recv_path: &Path<'_>) -> bool { + (types_match_diagnostic_item(cx, expr, recv, sym::Vec) + || types_match_diagnostic_item(cx, expr, recv, sym::VecDeque)) + && matches!(args, [arg] if is_range_full(cx, arg, Some(recv_path))) +} + +/// Checks `std::string::String` +fn check_string(cx: &LateContext<'_>, args: &[Expr<'_>], expr: Ty<'_>, recv: Ty<'_>, recv_path: &Path<'_>) -> bool { + is_type_lang_item(cx, expr, LangItem::String) + && is_type_lang_item(cx, recv, LangItem::String) + && matches!(args, [arg] if is_range_full(cx, arg, Some(recv_path))) +} + +/// Checks `std::collections::{HashSet, HashMap, BinaryHeap}`. +fn check_collections(cx: &LateContext<'_>, expr: Ty<'_>, recv: Ty<'_>) -> Option<&'static str> { + types_match_diagnostic_item(cx, expr, recv, sym::HashSet) + .then_some("HashSet") + .or_else(|| types_match_diagnostic_item(cx, expr, recv, sym::HashMap).then_some("HashMap")) + .or_else(|| types_match_diagnostic_item(cx, expr, recv, sym::BinaryHeap).then_some("BinaryHeap")) +} + +pub(super) fn check(cx: &LateContext<'_>, args: &[Expr<'_>], expr: &Expr<'_>, recv: &Expr<'_>) { + let expr_ty = cx.typeck_results().expr_ty(expr); + let recv_ty = cx.typeck_results().expr_ty(recv).peel_refs(); + + if let ExprKind::Path(QPath::Resolved(_, recv_path)) = recv.kind + && let Some(typename) = check_vec(cx, args, expr_ty, recv_ty, recv_path) + .then_some("Vec") + .or_else(|| check_string(cx, args, expr_ty, recv_ty, recv_path).then_some("String")) + .or_else(|| check_collections(cx, expr_ty, recv_ty)) + { + let recv = snippet(cx, recv.span, ""); + span_lint_and_sugg( + cx, + DRAIN_COLLECT, + expr.span, + &format!("you seem to be trying to move all elements into a new `{typename}`"), + "consider using `mem::take`", + format!("std::mem::take(&mut {recv})"), + Applicability::MachineApplicable, + ); + } +} diff --git a/clippy_lints/src/methods/mod.rs b/clippy_lints/src/methods/mod.rs index 183bd582a48..faddb036eaa 100644 --- a/clippy_lints/src/methods/mod.rs +++ b/clippy_lints/src/methods/mod.rs @@ -14,6 +14,7 @@ mod clone_on_copy; mod clone_on_ref_ptr; mod cloned_instead_of_copied; mod collapsible_str_replace; +mod drain_collect; mod err_expect; mod expect_fun_call; mod expect_used; @@ -3247,6 +3248,42 @@ declare_clippy_lint! { "manual reverse iteration of `DoubleEndedIterator`" } +declare_clippy_lint! { + /// ### What it does + /// Checks for calls to `.drain()` that clear the collection, immediately followed by a call to `.collect()`. + /// + /// > "Collection" in this context refers to any type with a `drain` method: + /// > `Vec`, `VecDeque`, `BinaryHeap`, `HashSet`,`HashMap`, `String` + /// + /// ### Why is this bad? + /// Using `mem::take` is faster as it avoids the allocation. + /// When using `mem::take`, the old collection is replaced with an empty one and ownership of + /// the old collection is returned. + /// + /// ### Drawback + /// `mem::take(&mut vec)` is almost equivalent to `vec.drain(..).collect()`, except that + /// it also moves the **capacity**. The user might have explicitly written it this way + /// to keep the capacity on the original `Vec`. + /// + /// ### Example + /// ```rust + /// fn remove_all(v: &mut Vec) -> Vec { + /// v.drain(..).collect() + /// } + /// ``` + /// Use instead: + /// ```rust + /// use std::mem; + /// fn remove_all(v: &mut Vec) -> Vec { + /// mem::take(v) + /// } + /// ``` + #[clippy::version = "1.71.0"] + pub DRAIN_COLLECT, + perf, + "description" +} + pub struct Methods { avoid_breaking_exported_api: bool, msrv: Msrv, @@ -3377,6 +3414,7 @@ impl_lint_pass!(Methods => [ CLEAR_WITH_DRAIN, MANUAL_NEXT_BACK, UNNECESSARY_LITERAL_UNWRAP, + DRAIN_COLLECT ]); /// Extracts a method call name, args, and `Span` of the method name. @@ -3606,6 +3644,9 @@ impl Methods { manual_str_repeat::check(cx, expr, recv, take_self_arg, take_arg); } }, + Some(("drain", recv, args, ..)) => { + drain_collect::check(cx, args, expr, recv); + } _ => {}, } }, diff --git a/tests/ui/drain_collect.rs b/tests/ui/drain_collect.rs new file mode 100644 index 00000000000..1bedab75c03 --- /dev/null +++ b/tests/ui/drain_collect.rs @@ -0,0 +1,65 @@ +#![deny(clippy::drain_collect)] + +use std::collections::{BinaryHeap, HashMap, HashSet, VecDeque}; + +fn binaryheap(b: &mut BinaryHeap) -> BinaryHeap { + b.drain().collect() +} + +fn binaryheap_dont_lint(b: &mut BinaryHeap) -> HashSet { + b.drain().collect() +} + +fn hashmap(b: &mut HashMap) -> HashMap { + b.drain().collect() +} + +fn hashmap_dont_lint(b: &mut HashMap) -> Vec<(i32, i32)> { + b.drain().collect() +} + +fn hashset(b: &mut HashSet) -> HashSet { + b.drain().collect() +} + +fn hashset_dont_lint(b: &mut HashSet) -> Vec { + b.drain().collect() +} + +fn vecdeque(b: &mut VecDeque) -> VecDeque { + b.drain(..).collect() +} + +fn vecdeque_dont_lint(b: &mut VecDeque) -> HashSet { + b.drain(..).collect() +} + +fn vec(b: &mut Vec) -> Vec { + b.drain(..).collect() +} + +fn vec2(b: &mut Vec) -> Vec { + b.drain(0..).collect() +} + +fn vec3(b: &mut Vec) -> Vec { + b.drain(..b.len()).collect() +} + +fn vec4(b: &mut Vec) -> Vec { + b.drain(0..b.len()).collect() +} + +fn vec_dont_lint(b: &mut Vec) -> HashSet { + b.drain(..).collect() +} + +fn string(b: &mut String) -> String { + b.drain(..).collect() +} + +fn string_dont_lint(b: &mut String) -> HashSet { + b.drain(..).collect() +} + +fn main() {} diff --git a/tests/ui/drain_collect.stderr b/tests/ui/drain_collect.stderr new file mode 100644 index 00000000000..d4e2b4a6fa2 --- /dev/null +++ b/tests/ui/drain_collect.stderr @@ -0,0 +1,62 @@ +error: you seem to be trying to move all elements into a new `BinaryHeap` + --> $DIR/drain_collect.rs:6:5 + | +LL | b.drain().collect() + | ^^^^^^^^^^^^^^^^^^^ help: consider using `mem::take`: `std::mem::take(&mut b)` + | +note: the lint level is defined here + --> $DIR/drain_collect.rs:1:9 + | +LL | #![deny(clippy::drain_collect)] + | ^^^^^^^^^^^^^^^^^^^^^ + +error: you seem to be trying to move all elements into a new `HashMap` + --> $DIR/drain_collect.rs:14:5 + | +LL | b.drain().collect() + | ^^^^^^^^^^^^^^^^^^^ help: consider using `mem::take`: `std::mem::take(&mut b)` + +error: you seem to be trying to move all elements into a new `HashSet` + --> $DIR/drain_collect.rs:22:5 + | +LL | b.drain().collect() + | ^^^^^^^^^^^^^^^^^^^ help: consider using `mem::take`: `std::mem::take(&mut b)` + +error: you seem to be trying to move all elements into a new `Vec` + --> $DIR/drain_collect.rs:30:5 + | +LL | b.drain(..).collect() + | ^^^^^^^^^^^^^^^^^^^^^ help: consider using `mem::take`: `std::mem::take(&mut b)` + +error: you seem to be trying to move all elements into a new `Vec` + --> $DIR/drain_collect.rs:38:5 + | +LL | b.drain(..).collect() + | ^^^^^^^^^^^^^^^^^^^^^ help: consider using `mem::take`: `std::mem::take(&mut b)` + +error: you seem to be trying to move all elements into a new `Vec` + --> $DIR/drain_collect.rs:42:5 + | +LL | b.drain(0..).collect() + | ^^^^^^^^^^^^^^^^^^^^^^ help: consider using `mem::take`: `std::mem::take(&mut b)` + +error: you seem to be trying to move all elements into a new `Vec` + --> $DIR/drain_collect.rs:46:5 + | +LL | b.drain(..b.len()).collect() + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `mem::take`: `std::mem::take(&mut b)` + +error: you seem to be trying to move all elements into a new `Vec` + --> $DIR/drain_collect.rs:50:5 + | +LL | b.drain(0..b.len()).collect() + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `mem::take`: `std::mem::take(&mut b)` + +error: you seem to be trying to move all elements into a new `String` + --> $DIR/drain_collect.rs:58:5 + | +LL | b.drain(..).collect() + | ^^^^^^^^^^^^^^^^^^^^^ help: consider using `mem::take`: `std::mem::take(&mut b)` + +error: aborting due to 9 previous errors + diff --git a/tests/ui/iter_with_drain.fixed b/tests/ui/iter_with_drain.fixed index 24a95c4d0fe..7a8c6770101 100644 --- a/tests/ui/iter_with_drain.fixed +++ b/tests/ui/iter_with_drain.fixed @@ -2,7 +2,7 @@ // will emits unused mut warnings after fixing #![allow(unused_mut)] // will emits needless collect warnings after fixing -#![allow(clippy::needless_collect)] +#![allow(clippy::needless_collect, clippy::drain_collect)] #![warn(clippy::iter_with_drain)] use std::collections::{BinaryHeap, HashMap, HashSet, VecDeque}; diff --git a/tests/ui/iter_with_drain.rs b/tests/ui/iter_with_drain.rs index a118c981ee3..cf3a935c349 100644 --- a/tests/ui/iter_with_drain.rs +++ b/tests/ui/iter_with_drain.rs @@ -2,7 +2,7 @@ // will emits unused mut warnings after fixing #![allow(unused_mut)] // will emits needless collect warnings after fixing -#![allow(clippy::needless_collect)] +#![allow(clippy::needless_collect, clippy::drain_collect)] #![warn(clippy::iter_with_drain)] use std::collections::{BinaryHeap, HashMap, HashSet, VecDeque}; From d2a6ec2d4d7930401d2600edfdac1cd964ebe55c Mon Sep 17 00:00:00 2001 From: y21 <30553356+y21@users.noreply.github.com> Date: Sat, 27 May 2023 01:31:55 +0200 Subject: [PATCH 201/310] take into account reborrowing when inserting `&mut` in sugg --- clippy_lints/src/methods/drain_collect.rs | 36 +++++++---- tests/ui/drain_collect.fixed | 73 +++++++++++++++++++++++ tests/ui/drain_collect.rs | 8 +++ tests/ui/drain_collect.stderr | 44 ++++++++------ 4 files changed, 132 insertions(+), 29 deletions(-) create mode 100644 tests/ui/drain_collect.fixed diff --git a/clippy_lints/src/methods/drain_collect.rs b/clippy_lints/src/methods/drain_collect.rs index 6d9df587518..53f63266073 100644 --- a/clippy_lints/src/methods/drain_collect.rs +++ b/clippy_lints/src/methods/drain_collect.rs @@ -11,7 +11,7 @@ use rustc_hir::Path; use rustc_hir::QPath; use rustc_lint::LateContext; use rustc_middle::query::Key; -use rustc_middle::ty::Ty; +use rustc_middle::ty; use rustc_span::sym; use rustc_span::Symbol; @@ -21,7 +21,7 @@ use rustc_span::Symbol; /// ^^^^^^^^^ ^^^^^^ true /// `vec![1,2].drain(..).collect::>()` /// ^^^^^^^^^ ^^^^^^^^^^ false -fn types_match_diagnostic_item(cx: &LateContext<'_>, expr: Ty<'_>, recv: Ty<'_>, sym: Symbol) -> bool { +fn types_match_diagnostic_item(cx: &LateContext<'_>, expr: ty::Ty<'_>, recv: ty::Ty<'_>, sym: Symbol) -> bool { if let Some(expr_adt_did) = expr.ty_adt_id() && let Some(recv_adt_did) = recv.ty_adt_id() { @@ -32,21 +32,33 @@ fn types_match_diagnostic_item(cx: &LateContext<'_>, expr: Ty<'_>, recv: Ty<'_>, } /// Checks `std::{vec::Vec, collections::VecDeque}`. -fn check_vec(cx: &LateContext<'_>, args: &[Expr<'_>], expr: Ty<'_>, recv: Ty<'_>, recv_path: &Path<'_>) -> bool { +fn check_vec( + cx: &LateContext<'_>, + args: &[Expr<'_>], + expr: ty::Ty<'_>, + recv: ty::Ty<'_>, + recv_path: &Path<'_>, +) -> bool { (types_match_diagnostic_item(cx, expr, recv, sym::Vec) || types_match_diagnostic_item(cx, expr, recv, sym::VecDeque)) && matches!(args, [arg] if is_range_full(cx, arg, Some(recv_path))) } /// Checks `std::string::String` -fn check_string(cx: &LateContext<'_>, args: &[Expr<'_>], expr: Ty<'_>, recv: Ty<'_>, recv_path: &Path<'_>) -> bool { +fn check_string( + cx: &LateContext<'_>, + args: &[Expr<'_>], + expr: ty::Ty<'_>, + recv: ty::Ty<'_>, + recv_path: &Path<'_>, +) -> bool { is_type_lang_item(cx, expr, LangItem::String) && is_type_lang_item(cx, recv, LangItem::String) && matches!(args, [arg] if is_range_full(cx, arg, Some(recv_path))) } /// Checks `std::collections::{HashSet, HashMap, BinaryHeap}`. -fn check_collections(cx: &LateContext<'_>, expr: Ty<'_>, recv: Ty<'_>) -> Option<&'static str> { +fn check_collections(cx: &LateContext<'_>, expr: ty::Ty<'_>, recv: ty::Ty<'_>) -> Option<&'static str> { types_match_diagnostic_item(cx, expr, recv, sym::HashSet) .then_some("HashSet") .or_else(|| types_match_diagnostic_item(cx, expr, recv, sym::HashMap).then_some("HashMap")) @@ -55,13 +67,14 @@ fn check_collections(cx: &LateContext<'_>, expr: Ty<'_>, recv: Ty<'_>) -> Option pub(super) fn check(cx: &LateContext<'_>, args: &[Expr<'_>], expr: &Expr<'_>, recv: &Expr<'_>) { let expr_ty = cx.typeck_results().expr_ty(expr); - let recv_ty = cx.typeck_results().expr_ty(recv).peel_refs(); + let recv_ty = cx.typeck_results().expr_ty(recv); + let recv_ty_no_refs = recv_ty.peel_refs(); if let ExprKind::Path(QPath::Resolved(_, recv_path)) = recv.kind - && let Some(typename) = check_vec(cx, args, expr_ty, recv_ty, recv_path) + && let Some(typename) = check_vec(cx, args, expr_ty, recv_ty_no_refs, recv_path) .then_some("Vec") - .or_else(|| check_string(cx, args, expr_ty, recv_ty, recv_path).then_some("String")) - .or_else(|| check_collections(cx, expr_ty, recv_ty)) + .or_else(|| check_string(cx, args, expr_ty, recv_ty_no_refs, recv_path).then_some("String")) + .or_else(|| check_collections(cx, expr_ty, recv_ty_no_refs)) { let recv = snippet(cx, recv.span, ""); span_lint_and_sugg( @@ -70,7 +83,10 @@ pub(super) fn check(cx: &LateContext<'_>, args: &[Expr<'_>], expr: &Expr<'_>, re expr.span, &format!("you seem to be trying to move all elements into a new `{typename}`"), "consider using `mem::take`", - format!("std::mem::take(&mut {recv})"), + match recv_ty.kind() { + ty::Ref(..) => format!("std::mem::take({recv})"), + _ => format!("std::mem::take(&mut {recv})"), + }, Applicability::MachineApplicable, ); } diff --git a/tests/ui/drain_collect.fixed b/tests/ui/drain_collect.fixed new file mode 100644 index 00000000000..0d40a648378 --- /dev/null +++ b/tests/ui/drain_collect.fixed @@ -0,0 +1,73 @@ +//@run-rustfix + +#![deny(clippy::drain_collect)] +#![allow(dead_code)] + +use std::collections::{BinaryHeap, HashMap, HashSet, VecDeque}; + +fn binaryheap(b: &mut BinaryHeap) -> BinaryHeap { + std::mem::take(b) +} + +fn binaryheap_dont_lint(b: &mut BinaryHeap) -> HashSet { + b.drain().collect() +} + +fn hashmap(b: &mut HashMap) -> HashMap { + std::mem::take(b) +} + +fn hashmap_dont_lint(b: &mut HashMap) -> Vec<(i32, i32)> { + b.drain().collect() +} + +fn hashset(b: &mut HashSet) -> HashSet { + std::mem::take(b) +} + +fn hashset_dont_lint(b: &mut HashSet) -> Vec { + b.drain().collect() +} + +fn vecdeque(b: &mut VecDeque) -> VecDeque { + std::mem::take(b) +} + +fn vecdeque_dont_lint(b: &mut VecDeque) -> HashSet { + b.drain(..).collect() +} + +fn vec(b: &mut Vec) -> Vec { + std::mem::take(b) +} + +fn vec2(b: &mut Vec) -> Vec { + std::mem::take(b) +} + +fn vec3(b: &mut Vec) -> Vec { + std::mem::take(b) +} + +fn vec4(b: &mut Vec) -> Vec { + std::mem::take(b) +} + +fn vec_no_reborrow() -> Vec { + let mut b = vec![1, 2, 3]; + std::mem::take(&mut b) +} + +fn vec_dont_lint(b: &mut Vec) -> HashSet { + b.drain(..).collect() +} + +fn string(b: &mut String) -> String { + std::mem::take(b) +} + +fn string_dont_lint(b: &mut String) -> HashSet { + b.drain(..).collect() +} + +fn main() {} diff --git a/tests/ui/drain_collect.rs b/tests/ui/drain_collect.rs index 1bedab75c03..7144a1847ca 100644 --- a/tests/ui/drain_collect.rs +++ b/tests/ui/drain_collect.rs @@ -1,4 +1,7 @@ +//@run-rustfix + #![deny(clippy::drain_collect)] +#![allow(dead_code)] use std::collections::{BinaryHeap, HashMap, HashSet, VecDeque}; @@ -50,6 +53,11 @@ fn vec4(b: &mut Vec) -> Vec { b.drain(0..b.len()).collect() } +fn vec_no_reborrow() -> Vec { + let mut b = vec![1, 2, 3]; + b.drain(..).collect() +} + fn vec_dont_lint(b: &mut Vec) -> HashSet { b.drain(..).collect() } diff --git a/tests/ui/drain_collect.stderr b/tests/ui/drain_collect.stderr index d4e2b4a6fa2..0792f0254cb 100644 --- a/tests/ui/drain_collect.stderr +++ b/tests/ui/drain_collect.stderr @@ -1,62 +1,68 @@ error: you seem to be trying to move all elements into a new `BinaryHeap` - --> $DIR/drain_collect.rs:6:5 + --> $DIR/drain_collect.rs:9:5 | LL | b.drain().collect() - | ^^^^^^^^^^^^^^^^^^^ help: consider using `mem::take`: `std::mem::take(&mut b)` + | ^^^^^^^^^^^^^^^^^^^ help: consider using `mem::take`: `std::mem::take(b)` | note: the lint level is defined here - --> $DIR/drain_collect.rs:1:9 + --> $DIR/drain_collect.rs:3:9 | LL | #![deny(clippy::drain_collect)] | ^^^^^^^^^^^^^^^^^^^^^ error: you seem to be trying to move all elements into a new `HashMap` - --> $DIR/drain_collect.rs:14:5 + --> $DIR/drain_collect.rs:17:5 | LL | b.drain().collect() - | ^^^^^^^^^^^^^^^^^^^ help: consider using `mem::take`: `std::mem::take(&mut b)` + | ^^^^^^^^^^^^^^^^^^^ help: consider using `mem::take`: `std::mem::take(b)` error: you seem to be trying to move all elements into a new `HashSet` - --> $DIR/drain_collect.rs:22:5 + --> $DIR/drain_collect.rs:25:5 | LL | b.drain().collect() - | ^^^^^^^^^^^^^^^^^^^ help: consider using `mem::take`: `std::mem::take(&mut b)` + | ^^^^^^^^^^^^^^^^^^^ help: consider using `mem::take`: `std::mem::take(b)` error: you seem to be trying to move all elements into a new `Vec` - --> $DIR/drain_collect.rs:30:5 + --> $DIR/drain_collect.rs:33:5 | LL | b.drain(..).collect() - | ^^^^^^^^^^^^^^^^^^^^^ help: consider using `mem::take`: `std::mem::take(&mut b)` + | ^^^^^^^^^^^^^^^^^^^^^ help: consider using `mem::take`: `std::mem::take(b)` error: you seem to be trying to move all elements into a new `Vec` - --> $DIR/drain_collect.rs:38:5 + --> $DIR/drain_collect.rs:41:5 | LL | b.drain(..).collect() - | ^^^^^^^^^^^^^^^^^^^^^ help: consider using `mem::take`: `std::mem::take(&mut b)` + | ^^^^^^^^^^^^^^^^^^^^^ help: consider using `mem::take`: `std::mem::take(b)` error: you seem to be trying to move all elements into a new `Vec` - --> $DIR/drain_collect.rs:42:5 + --> $DIR/drain_collect.rs:45:5 | LL | b.drain(0..).collect() - | ^^^^^^^^^^^^^^^^^^^^^^ help: consider using `mem::take`: `std::mem::take(&mut b)` + | ^^^^^^^^^^^^^^^^^^^^^^ help: consider using `mem::take`: `std::mem::take(b)` error: you seem to be trying to move all elements into a new `Vec` - --> $DIR/drain_collect.rs:46:5 + --> $DIR/drain_collect.rs:49:5 | LL | b.drain(..b.len()).collect() - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `mem::take`: `std::mem::take(&mut b)` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `mem::take`: `std::mem::take(b)` error: you seem to be trying to move all elements into a new `Vec` - --> $DIR/drain_collect.rs:50:5 + --> $DIR/drain_collect.rs:53:5 | LL | b.drain(0..b.len()).collect() - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `mem::take`: `std::mem::take(&mut b)` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `mem::take`: `std::mem::take(b)` -error: you seem to be trying to move all elements into a new `String` +error: you seem to be trying to move all elements into a new `Vec` --> $DIR/drain_collect.rs:58:5 | LL | b.drain(..).collect() | ^^^^^^^^^^^^^^^^^^^^^ help: consider using `mem::take`: `std::mem::take(&mut b)` -error: aborting due to 9 previous errors +error: you seem to be trying to move all elements into a new `String` + --> $DIR/drain_collect.rs:66:5 + | +LL | b.drain(..).collect() + | ^^^^^^^^^^^^^^^^^^^^^ help: consider using `mem::take`: `std::mem::take(b)` + +error: aborting due to 10 previous errors From 3f3657a3e4ae745339e42e377bef57f2f56ed5ff Mon Sep 17 00:00:00 2001 From: y21 <30553356+y21@users.noreply.github.com> Date: Sat, 27 May 2023 01:50:36 +0200 Subject: [PATCH 202/310] make clippy happy --- clippy_lints/src/methods/drain_collect.rs | 28 ++++++++--------------- 1 file changed, 9 insertions(+), 19 deletions(-) diff --git a/clippy_lints/src/methods/drain_collect.rs b/clippy_lints/src/methods/drain_collect.rs index 53f63266073..8bd8f88a214 100644 --- a/clippy_lints/src/methods/drain_collect.rs +++ b/clippy_lints/src/methods/drain_collect.rs @@ -12,6 +12,7 @@ use rustc_hir::QPath; use rustc_lint::LateContext; use rustc_middle::query::Key; use rustc_middle::ty; +use rustc_middle::ty::Ty; use rustc_span::sym; use rustc_span::Symbol; @@ -21,7 +22,7 @@ use rustc_span::Symbol; /// ^^^^^^^^^ ^^^^^^ true /// `vec![1,2].drain(..).collect::>()` /// ^^^^^^^^^ ^^^^^^^^^^ false -fn types_match_diagnostic_item(cx: &LateContext<'_>, expr: ty::Ty<'_>, recv: ty::Ty<'_>, sym: Symbol) -> bool { +fn types_match_diagnostic_item(cx: &LateContext<'_>, expr: Ty<'_>, recv: Ty<'_>, sym: Symbol) -> bool { if let Some(expr_adt_did) = expr.ty_adt_id() && let Some(recv_adt_did) = recv.ty_adt_id() { @@ -32,33 +33,21 @@ fn types_match_diagnostic_item(cx: &LateContext<'_>, expr: ty::Ty<'_>, recv: ty: } /// Checks `std::{vec::Vec, collections::VecDeque}`. -fn check_vec( - cx: &LateContext<'_>, - args: &[Expr<'_>], - expr: ty::Ty<'_>, - recv: ty::Ty<'_>, - recv_path: &Path<'_>, -) -> bool { +fn check_vec(cx: &LateContext<'_>, args: &[Expr<'_>], expr: Ty<'_>, recv: Ty<'_>, recv_path: &Path<'_>) -> bool { (types_match_diagnostic_item(cx, expr, recv, sym::Vec) || types_match_diagnostic_item(cx, expr, recv, sym::VecDeque)) && matches!(args, [arg] if is_range_full(cx, arg, Some(recv_path))) } /// Checks `std::string::String` -fn check_string( - cx: &LateContext<'_>, - args: &[Expr<'_>], - expr: ty::Ty<'_>, - recv: ty::Ty<'_>, - recv_path: &Path<'_>, -) -> bool { +fn check_string(cx: &LateContext<'_>, args: &[Expr<'_>], expr: Ty<'_>, recv: Ty<'_>, recv_path: &Path<'_>) -> bool { is_type_lang_item(cx, expr, LangItem::String) && is_type_lang_item(cx, recv, LangItem::String) && matches!(args, [arg] if is_range_full(cx, arg, Some(recv_path))) } /// Checks `std::collections::{HashSet, HashMap, BinaryHeap}`. -fn check_collections(cx: &LateContext<'_>, expr: ty::Ty<'_>, recv: ty::Ty<'_>) -> Option<&'static str> { +fn check_collections(cx: &LateContext<'_>, expr: Ty<'_>, recv: Ty<'_>) -> Option<&'static str> { types_match_diagnostic_item(cx, expr, recv, sym::HashSet) .then_some("HashSet") .or_else(|| types_match_diagnostic_item(cx, expr, recv, sym::HashMap).then_some("HashMap")) @@ -83,9 +72,10 @@ pub(super) fn check(cx: &LateContext<'_>, args: &[Expr<'_>], expr: &Expr<'_>, re expr.span, &format!("you seem to be trying to move all elements into a new `{typename}`"), "consider using `mem::take`", - match recv_ty.kind() { - ty::Ref(..) => format!("std::mem::take({recv})"), - _ => format!("std::mem::take(&mut {recv})"), + if let ty::Ref(..) = recv_ty.kind() { + format!("std::mem::take({recv})") + } else { + format!("std::mem::take(&mut {recv})") }, Applicability::MachineApplicable, ); From 20ae597ec4dc593bb07bcd436b3ca42fcb64df42 Mon Sep 17 00:00:00 2001 From: y21 <30553356+y21@users.noreply.github.com> Date: Thu, 8 Jun 2023 19:54:33 +0200 Subject: [PATCH 203/310] add a description --- clippy_lints/src/methods/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clippy_lints/src/methods/mod.rs b/clippy_lints/src/methods/mod.rs index faddb036eaa..bed70207f28 100644 --- a/clippy_lints/src/methods/mod.rs +++ b/clippy_lints/src/methods/mod.rs @@ -3281,7 +3281,7 @@ declare_clippy_lint! { #[clippy::version = "1.71.0"] pub DRAIN_COLLECT, perf, - "description" + "calling `.drain(..).collect()` to move all elements into a new collection" } pub struct Methods { From 5821fbbc3072c16bc941a5e207bfd3a5e401304b Mon Sep 17 00:00:00 2001 From: y21 <30553356+y21@users.noreply.github.com> Date: Thu, 15 Jun 2023 14:16:39 +0200 Subject: [PATCH 204/310] add test case for not whole length, move sugg into variable --- clippy_lints/src/methods/drain_collect.rs | 12 +++++++----- clippy_lints/src/methods/mod.rs | 2 +- tests/ui/drain_collect.fixed | 4 ++++ tests/ui/drain_collect.rs | 4 ++++ 4 files changed, 16 insertions(+), 6 deletions(-) diff --git a/clippy_lints/src/methods/drain_collect.rs b/clippy_lints/src/methods/drain_collect.rs index 8bd8f88a214..d0c79dc11b0 100644 --- a/clippy_lints/src/methods/drain_collect.rs +++ b/clippy_lints/src/methods/drain_collect.rs @@ -66,17 +66,19 @@ pub(super) fn check(cx: &LateContext<'_>, args: &[Expr<'_>], expr: &Expr<'_>, re .or_else(|| check_collections(cx, expr_ty, recv_ty_no_refs)) { let recv = snippet(cx, recv.span, ""); + let sugg = if let ty::Ref(..) = recv_ty.kind() { + format!("std::mem::take({recv})") + } else { + format!("std::mem::take(&mut {recv})") + }; + span_lint_and_sugg( cx, DRAIN_COLLECT, expr.span, &format!("you seem to be trying to move all elements into a new `{typename}`"), "consider using `mem::take`", - if let ty::Ref(..) = recv_ty.kind() { - format!("std::mem::take({recv})") - } else { - format!("std::mem::take(&mut {recv})") - }, + sugg, Applicability::MachineApplicable, ); } diff --git a/clippy_lints/src/methods/mod.rs b/clippy_lints/src/methods/mod.rs index bed70207f28..99c984ba65a 100644 --- a/clippy_lints/src/methods/mod.rs +++ b/clippy_lints/src/methods/mod.rs @@ -3260,7 +3260,7 @@ declare_clippy_lint! { /// When using `mem::take`, the old collection is replaced with an empty one and ownership of /// the old collection is returned. /// - /// ### Drawback + /// ### Known issues /// `mem::take(&mut vec)` is almost equivalent to `vec.drain(..).collect()`, except that /// it also moves the **capacity**. The user might have explicitly written it this way /// to keep the capacity on the original `Vec`. diff --git a/tests/ui/drain_collect.fixed b/tests/ui/drain_collect.fixed index 0d40a648378..11001bd319f 100644 --- a/tests/ui/drain_collect.fixed +++ b/tests/ui/drain_collect.fixed @@ -70,4 +70,8 @@ fn string_dont_lint(b: &mut String) -> HashSet { b.drain(..).collect() } +fn not_whole_length(v: &mut Vec) -> Vec { + v.drain(1..).collect() +} + fn main() {} diff --git a/tests/ui/drain_collect.rs b/tests/ui/drain_collect.rs index 7144a1847ca..373a3ca3506 100644 --- a/tests/ui/drain_collect.rs +++ b/tests/ui/drain_collect.rs @@ -70,4 +70,8 @@ fn string_dont_lint(b: &mut String) -> HashSet { b.drain(..).collect() } +fn not_whole_length(v: &mut Vec) -> Vec { + v.drain(1..).collect() +} + fn main() {} From 3fe2478ecf19d4d62cbdfcf50d57bc00fe5bb242 Mon Sep 17 00:00:00 2001 From: y21 <30553356+y21@users.noreply.github.com> Date: Thu, 15 Jun 2023 22:04:25 +0200 Subject: [PATCH 205/310] don't unnecessarily walk more in visitor and add more tests --- clippy_lints/src/redundant_closure_call.rs | 6 +++--- tests/ui/redundant_closure_call_fixable.fixed | 7 +++++++ tests/ui/redundant_closure_call_fixable.rs | 7 +++++++ tests/ui/redundant_closure_call_fixable.stderr | 14 +++++++++++++- 4 files changed, 30 insertions(+), 4 deletions(-) diff --git a/clippy_lints/src/redundant_closure_call.rs b/clippy_lints/src/redundant_closure_call.rs index d979087a6d7..b6ce4ebc28f 100644 --- a/clippy_lints/src/redundant_closure_call.rs +++ b/clippy_lints/src/redundant_closure_call.rs @@ -55,9 +55,9 @@ impl<'tcx> Visitor<'tcx> for ReturnVisitor { fn visit_expr(&mut self, ex: &'tcx hir::Expr<'tcx>) { if let hir::ExprKind::Ret(_) | hir::ExprKind::Match(.., hir::MatchSource::TryDesugar) = ex.kind { self.found_return = true; + } else { + hir_visit::walk_expr(self, ex); } - - hir_visit::walk_expr(self, ex); } } @@ -122,7 +122,7 @@ fn get_parent_call_exprs<'tcx>( let mut depth = 1; while let Some(parent) = get_parent_expr(cx, expr) && let hir::ExprKind::Call(recv, _) = parent.kind - && let hir::ExprKind::Call(..) = recv.kind + && expr.span == recv.span { expr = parent; depth += 1; diff --git a/tests/ui/redundant_closure_call_fixable.fixed b/tests/ui/redundant_closure_call_fixable.fixed index 1a2c1e59261..f3669a669ea 100644 --- a/tests/ui/redundant_closure_call_fixable.fixed +++ b/tests/ui/redundant_closure_call_fixable.fixed @@ -78,4 +78,11 @@ fn issue9956() { || || || 42 } let _ = x()()()(); + + fn bar() -> fn(i32, i32) { + foo + } + fn foo(_: i32, _: i32) {} + bar()(42, 5); + foo(42, 5); } diff --git a/tests/ui/redundant_closure_call_fixable.rs b/tests/ui/redundant_closure_call_fixable.rs index fec46652189..db8c7f80df4 100644 --- a/tests/ui/redundant_closure_call_fixable.rs +++ b/tests/ui/redundant_closure_call_fixable.rs @@ -78,4 +78,11 @@ fn issue9956() { || || || 42 } let _ = x()()()(); + + fn bar() -> fn(i32, i32) { + foo + } + fn foo(_: i32, _: i32) {} + bar()((|| || 42)()(), 5); + foo((|| || 42)()(), 5); } diff --git a/tests/ui/redundant_closure_call_fixable.stderr b/tests/ui/redundant_closure_call_fixable.stderr index 351da54ef31..618f5e071d6 100644 --- a/tests/ui/redundant_closure_call_fixable.stderr +++ b/tests/ui/redundant_closure_call_fixable.stderr @@ -110,5 +110,17 @@ error: try not to call a closure in the expression where it is declared LL | let a = (|| echo!((|| 123)))()(); | ^^^^^^^^^^^^^^^^^^^^^^^^ help: try doing something like: `123` -error: aborting due to 12 previous errors +error: try not to call a closure in the expression where it is declared + --> $DIR/redundant_closure_call_fixable.rs:86:11 + | +LL | bar()((|| || 42)()(), 5); + | ^^^^^^^^^^^^^^ help: try doing something like: `42` + +error: try not to call a closure in the expression where it is declared + --> $DIR/redundant_closure_call_fixable.rs:87:9 + | +LL | foo((|| || 42)()(), 5); + | ^^^^^^^^^^^^^^ help: try doing something like: `42` + +error: aborting due to 14 previous errors From 73cd2cde8b96b31b423a33e06dafa0e71e9f2589 Mon Sep 17 00:00:00 2001 From: Kisaragi Marine Date: Fri, 16 Jun 2023 16:37:19 +0900 Subject: [PATCH 206/310] merge test --- tests/ui/doc/missing_panics_doc.rs | 31 ----------- tests/ui/doc/missing_panics_doc.stderr | 75 -------------------------- tests/ui/missing_panics_doc.rs | 32 +++++++++++ tests/ui/missing_panics_doc.stderr | 74 ++++++++++++++++++++++++- 4 files changed, 105 insertions(+), 107 deletions(-) delete mode 100644 tests/ui/doc/missing_panics_doc.rs delete mode 100644 tests/ui/doc/missing_panics_doc.stderr diff --git a/tests/ui/doc/missing_panics_doc.rs b/tests/ui/doc/missing_panics_doc.rs deleted file mode 100644 index 5cb8a9691f4..00000000000 --- a/tests/ui/doc/missing_panics_doc.rs +++ /dev/null @@ -1,31 +0,0 @@ -#![warn(clippy::missing_panics_doc)] - -pub fn option_unwrap(v: &[T]) -> &T { - let o: Option<&T> = v.last(); - o.unwrap() -} - -pub fn option_expect(v: &[T]) -> &T { - let o: Option<&T> = v.last(); - o.expect("passed an empty thing") -} - -pub fn result_unwrap(v: &[T]) -> &T { - let res: Result<&T, &str> = v.last().ok_or("oh noes"); - res.unwrap() -} - -pub fn result_expect(v: &[T]) -> &T { - let res: Result<&T, &str> = v.last().ok_or("oh noes"); - res.expect("passed an empty thing") -} - -pub fn last_unwrap(v: &[u32]) -> u32 { - *v.last().unwrap() -} - -pub fn last_expect(v: &[u32]) -> u32 { - *v.last().expect("passed an empty thing") -} - -fn main() {} diff --git a/tests/ui/doc/missing_panics_doc.stderr b/tests/ui/doc/missing_panics_doc.stderr deleted file mode 100644 index f3e613bc799..00000000000 --- a/tests/ui/doc/missing_panics_doc.stderr +++ /dev/null @@ -1,75 +0,0 @@ -error: docs for function which may panic missing `# Panics` section - --> $DIR/missing_panics_doc.rs:3:1 - | -LL | pub fn option_unwrap(v: &[T]) -> &T { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | -note: first possible panic found here - --> $DIR/missing_panics_doc.rs:5:5 - | -LL | o.unwrap() - | ^^^^^^^^^^ - = note: `-D clippy::missing-panics-doc` implied by `-D warnings` - -error: docs for function which may panic missing `# Panics` section - --> $DIR/missing_panics_doc.rs:8:1 - | -LL | pub fn option_expect(v: &[T]) -> &T { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | -note: first possible panic found here - --> $DIR/missing_panics_doc.rs:10:5 - | -LL | o.expect("passed an empty thing") - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: docs for function which may panic missing `# Panics` section - --> $DIR/missing_panics_doc.rs:13:1 - | -LL | pub fn result_unwrap(v: &[T]) -> &T { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | -note: first possible panic found here - --> $DIR/missing_panics_doc.rs:15:5 - | -LL | res.unwrap() - | ^^^^^^^^^^^^ - -error: docs for function which may panic missing `# Panics` section - --> $DIR/missing_panics_doc.rs:18:1 - | -LL | pub fn result_expect(v: &[T]) -> &T { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | -note: first possible panic found here - --> $DIR/missing_panics_doc.rs:20:5 - | -LL | res.expect("passed an empty thing") - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: docs for function which may panic missing `# Panics` section - --> $DIR/missing_panics_doc.rs:23:1 - | -LL | pub fn last_unwrap(v: &[u32]) -> u32 { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | -note: first possible panic found here - --> $DIR/missing_panics_doc.rs:24:6 - | -LL | *v.last().unwrap() - | ^^^^^^^^^^^^^^^^^ - -error: docs for function which may panic missing `# Panics` section - --> $DIR/missing_panics_doc.rs:27:1 - | -LL | pub fn last_expect(v: &[u32]) -> u32 { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | -note: first possible panic found here - --> $DIR/missing_panics_doc.rs:28:6 - | -LL | *v.last().expect("passed an empty thing") - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: aborting due to 6 previous errors - diff --git a/tests/ui/missing_panics_doc.rs b/tests/ui/missing_panics_doc.rs index 10aa436d6cd..d544a0b1afb 100644 --- a/tests/ui/missing_panics_doc.rs +++ b/tests/ui/missing_panics_doc.rs @@ -151,3 +151,35 @@ pub fn debug_assertions() { debug_assert_eq!(1, 2); debug_assert_ne!(1, 2); } + +// all function must be triggered the lint. +// `pub` is required, because the lint does not consider unreachable items +pub mod issue10240 { + pub fn option_unwrap(v: &[T]) -> &T { + let o: Option<&T> = v.last(); + o.unwrap() + } + + pub fn option_expect(v: &[T]) -> &T { + let o: Option<&T> = v.last(); + o.expect("passed an empty thing") + } + + pub fn result_unwrap(v: &[T]) -> &T { + let res: Result<&T, &str> = v.last().ok_or("oh noes"); + res.unwrap() + } + + pub fn result_expect(v: &[T]) -> &T { + let res: Result<&T, &str> = v.last().ok_or("oh noes"); + res.expect("passed an empty thing") + } + + pub fn last_unwrap(v: &[u32]) -> u32 { + *v.last().unwrap() + } + + pub fn last_expect(v: &[u32]) -> u32 { + *v.last().expect("passed an empty thing") + } +} diff --git a/tests/ui/missing_panics_doc.stderr b/tests/ui/missing_panics_doc.stderr index 183c262ce0b..39d97f08373 100644 --- a/tests/ui/missing_panics_doc.stderr +++ b/tests/ui/missing_panics_doc.stderr @@ -83,5 +83,77 @@ note: first possible panic found here LL | assert_ne!(x, 0); | ^^^^^^^^^^^^^^^^ -error: aborting due to 7 previous errors +error: docs for function which may panic missing `# Panics` section + --> $DIR/missing_panics_doc.rs:158:5 + | +LL | pub fn option_unwrap(v: &[T]) -> &T { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: first possible panic found here + --> $DIR/missing_panics_doc.rs:160:9 + | +LL | o.unwrap() + | ^^^^^^^^^^ + +error: docs for function which may panic missing `# Panics` section + --> $DIR/missing_panics_doc.rs:163:5 + | +LL | pub fn option_expect(v: &[T]) -> &T { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: first possible panic found here + --> $DIR/missing_panics_doc.rs:165:9 + | +LL | o.expect("passed an empty thing") + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: docs for function which may panic missing `# Panics` section + --> $DIR/missing_panics_doc.rs:168:5 + | +LL | pub fn result_unwrap(v: &[T]) -> &T { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: first possible panic found here + --> $DIR/missing_panics_doc.rs:170:9 + | +LL | res.unwrap() + | ^^^^^^^^^^^^ + +error: docs for function which may panic missing `# Panics` section + --> $DIR/missing_panics_doc.rs:173:5 + | +LL | pub fn result_expect(v: &[T]) -> &T { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: first possible panic found here + --> $DIR/missing_panics_doc.rs:175:9 + | +LL | res.expect("passed an empty thing") + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: docs for function which may panic missing `# Panics` section + --> $DIR/missing_panics_doc.rs:178:5 + | +LL | pub fn last_unwrap(v: &[u32]) -> u32 { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: first possible panic found here + --> $DIR/missing_panics_doc.rs:179:10 + | +LL | *v.last().unwrap() + | ^^^^^^^^^^^^^^^^^ + +error: docs for function which may panic missing `# Panics` section + --> $DIR/missing_panics_doc.rs:182:5 + | +LL | pub fn last_expect(v: &[u32]) -> u32 { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: first possible panic found here + --> $DIR/missing_panics_doc.rs:183:10 + | +LL | *v.last().expect("passed an empty thing") + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 13 previous errors From 73c0c145269a6226f46047c2e9cf5e5810a08dc7 Mon Sep 17 00:00:00 2001 From: Kisaragi <48310258+KisaragiEffective@users.noreply.github.com> Date: Fri, 16 Jun 2023 16:39:09 +0900 Subject: [PATCH 207/310] improve grammer in comment sentence Co-authored-by: dswij --- clippy_lints/src/doc.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clippy_lints/src/doc.rs b/clippy_lints/src/doc.rs index 11de7e60697..815495a7b7a 100644 --- a/clippy_lints/src/doc.rs +++ b/clippy_lints/src/doc.rs @@ -916,7 +916,7 @@ impl<'a, 'tcx> Visitor<'tcx> for FindPanicUnwrap<'a, 'tcx> { } } - // check for `unwrap` and `expect` both `Option` and `Result` + // check for `unwrap` and `expect` for both `Option` and `Result` if let Some(arglists) = method_chain_args(expr, &["unwrap"]).or(method_chain_args(expr, &["expect"])) { let receiver_ty = self.typeck_results.expr_ty(arglists[0].0).peel_refs(); if is_type_diagnostic_item(self.cx, receiver_ty, sym::Option) From a94aac607cbae80984db04e9e4fd1439ef0003e4 Mon Sep 17 00:00:00 2001 From: Martin Fischer Date: Fri, 16 Jun 2023 11:51:17 +0200 Subject: [PATCH 208/310] Refactor to make following commit pass single_match_else lint --- clippy_lints/src/lib.rs | 33 ++++++++++++++++----------------- 1 file changed, 16 insertions(+), 17 deletions(-) diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index b254c05d48b..cd1b63bdba2 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -497,24 +497,23 @@ pub(crate) struct LintInfo { pub fn explain(name: &str) { let target = format!("clippy::{}", name.to_ascii_uppercase()); - match declared_lints::LINTS.iter().find(|info| info.lint.name == target) { - Some(info) => { - println!("{}", info.explanation); - // Check if the lint has configuration - let mdconf = get_configuration_metadata(); - if let Some(config_vec_positions) = mdconf - .iter() - .find_all(|cconf| cconf.lints.contains(&info.lint.name_lower()[8..].to_owned())) - { - // If it has, print it - println!("### Configuration for {}:\n", info.lint.name_lower()); - for position in config_vec_positions { - let conf = &mdconf[position]; - println!(" - {}: {} (default: {})", conf.name, conf.doc, conf.default); - } + if let Some(info) = declared_lints::LINTS.iter().find(|info| info.lint.name == target) { + println!("{}", info.explanation); + // Check if the lint has configuration + let mdconf = get_configuration_metadata(); + if let Some(config_vec_positions) = mdconf + .iter() + .find_all(|cconf| cconf.lints.contains(&info.lint.name_lower()[8..].to_owned())) + { + // If it has, print it + println!("### Configuration for {}:\n", info.lint.name_lower()); + for position in config_vec_positions { + let conf = &mdconf[position]; + println!(" - {}: {} (default: {})", conf.name, conf.doc, conf.default); } - }, - None => println!("unknown lint: {name}"), + } + } else { + println!("unknown lint: {name}"); } } From 894d5dafac8cb087a353047f33b4330c2a78cf2d Mon Sep 17 00:00:00 2001 From: Martin Fischer Date: Fri, 16 Jun 2023 11:11:20 +0200 Subject: [PATCH 209/310] Make `--explain` subcommand return 1 for missing lints --- clippy_lints/src/lib.rs | 4 +++- src/main.rs | 4 +++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index cd1b63bdba2..f0a873b91eb 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -495,7 +495,7 @@ pub(crate) struct LintInfo { explanation: &'static str, } -pub fn explain(name: &str) { +pub fn explain(name: &str) -> i32 { let target = format!("clippy::{}", name.to_ascii_uppercase()); if let Some(info) = declared_lints::LINTS.iter().find(|info| info.lint.name == target) { println!("{}", info.explanation); @@ -512,8 +512,10 @@ pub fn explain(name: &str) { println!(" - {}: {} (default: {})", conf.name, conf.doc, conf.default); } } + 0 } else { println!("unknown lint: {name}"); + 1 } } diff --git a/src/main.rs b/src/main.rs index 188ff87abfc..300c84a1442 100644 --- a/src/main.rs +++ b/src/main.rs @@ -57,7 +57,9 @@ pub fn main() { if let Some(pos) = env::args().position(|a| a == "--explain") { if let Some(mut lint) = env::args().nth(pos + 1) { lint.make_ascii_lowercase(); - clippy_lints::explain(&lint.strip_prefix("clippy::").unwrap_or(&lint).replace('-', "_")); + process::exit(clippy_lints::explain( + &lint.strip_prefix("clippy::").unwrap_or(&lint).replace('-', "_"), + )); } else { show_help(); } From 5777494f990a40350944ec6e92e0be16b880a636 Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Tue, 7 Mar 2023 12:03:11 +0000 Subject: [PATCH 210/310] Add `AliasKind::Weak` for type aliases. Only use it when the type alias contains an opaque type. Also does wf-checking on such type aliases. --- clippy_lints/src/dereference.rs | 1 + tests/ui/from_over_into.fixed | 6 ----- tests/ui/from_over_into.rs | 6 ----- tests/ui/from_over_into_unfixable.rs | 6 +++++ tests/ui/from_over_into_unfixable.stderr | 33 ++++++------------------ tests/ui/new_ret_no_self.rs | 22 ---------------- tests/ui/new_ret_no_self.stderr | 18 +------------ tests/ui/new_ret_no_self_overflow.rs | 26 +++++++++++++++++++ tests/ui/new_ret_no_self_overflow.stderr | 9 +++++++ 9 files changed, 51 insertions(+), 76 deletions(-) create mode 100644 tests/ui/new_ret_no_self_overflow.rs create mode 100644 tests/ui/new_ret_no_self_overflow.stderr diff --git a/clippy_lints/src/dereference.rs b/clippy_lints/src/dereference.rs index a1d2147cb49..dbaf6aaa853 100644 --- a/clippy_lints/src/dereference.rs +++ b/clippy_lints/src/dereference.rs @@ -1424,6 +1424,7 @@ fn ty_auto_deref_stability<'tcx>( continue; }, ty::Param(_) => TyPosition::new_deref_stable_for_result(precedence, ty), + ty::Alias(ty::Weak, _) => unreachable!("should have been normalized away above"), ty::Alias(ty::Inherent, _) => unreachable!("inherent projection should have been normalized away above"), ty::Alias(ty::Projection, _) if ty.has_non_region_param() => { TyPosition::new_deref_stable_for_result(precedence, ty) diff --git a/tests/ui/from_over_into.fixed b/tests/ui/from_over_into.fixed index d18f9387565..204019130ed 100644 --- a/tests/ui/from_over_into.fixed +++ b/tests/ui/from_over_into.fixed @@ -82,10 +82,4 @@ fn msrv_1_41() { } } -type Opaque = impl Sized; -struct IntoOpaque; -impl Into for IntoOpaque { - fn into(self) -> Opaque {} -} - fn main() {} diff --git a/tests/ui/from_over_into.rs b/tests/ui/from_over_into.rs index de8ff0b06bd..46e02847e30 100644 --- a/tests/ui/from_over_into.rs +++ b/tests/ui/from_over_into.rs @@ -82,10 +82,4 @@ fn msrv_1_41() { } } -type Opaque = impl Sized; -struct IntoOpaque; -impl Into for IntoOpaque { - fn into(self) -> Opaque {} -} - fn main() {} diff --git a/tests/ui/from_over_into_unfixable.rs b/tests/ui/from_over_into_unfixable.rs index 3b280b7488a..bd62c655216 100644 --- a/tests/ui/from_over_into_unfixable.rs +++ b/tests/ui/from_over_into_unfixable.rs @@ -32,4 +32,10 @@ impl Into for ContainsVal { } } +type Opaque = impl Sized; +struct IntoOpaque; +impl Into for IntoOpaque { + fn into(self) -> Opaque {} +} + fn main() {} diff --git a/tests/ui/from_over_into_unfixable.stderr b/tests/ui/from_over_into_unfixable.stderr index 251f1d84e74..bb966af4b0f 100644 --- a/tests/ui/from_over_into_unfixable.stderr +++ b/tests/ui/from_over_into_unfixable.stderr @@ -1,29 +1,12 @@ -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:11:1 +error[E0658]: `impl Trait` in type aliases is unstable + --> $DIR/from_over_into_unfixable.rs:35:15 | -LL | impl Into for String { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | type Opaque = impl Sized; + | ^^^^^^^^^^ | - = help: replace the `Into` implementation with `From` - = note: `-D clippy::from-over-into` implied by `-D warnings` + = note: see issue #63063 for more information + = help: add `#![feature(type_alias_impl_trait)]` to the crate attributes to enable -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:19:1 - | -LL | impl Into for &'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 - | -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` implementation with `From` - -error: aborting due to 3 previous errors +error: aborting due to previous error +For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/new_ret_no_self.rs b/tests/ui/new_ret_no_self.rs index a2a30c8b931..4eff62b85ff 100644 --- a/tests/ui/new_ret_no_self.rs +++ b/tests/ui/new_ret_no_self.rs @@ -401,25 +401,3 @@ mod issue7344 { } } } - -mod issue10041 { - struct Bomb; - - impl Bomb { - // Hidden default generic parameter. - pub fn new() -> impl PartialOrd { - 0i32 - } - } - - // TAIT with self-referencing bounds - type X = impl std::ops::Add; - - struct Bomb2; - - impl Bomb2 { - pub fn new() -> X { - 0i32 - } - } -} diff --git a/tests/ui/new_ret_no_self.stderr b/tests/ui/new_ret_no_self.stderr index 2eaebfb5cac..2b053b462b1 100644 --- a/tests/ui/new_ret_no_self.stderr +++ b/tests/ui/new_ret_no_self.stderr @@ -92,21 +92,5 @@ LL | | unimplemented!() LL | | } | |_________^ -error: methods called `new` usually return `Self` - --> $DIR/new_ret_no_self.rs:410:9 - | -LL | / pub fn new() -> impl PartialOrd { -LL | | 0i32 -LL | | } - | |_________^ - -error: methods called `new` usually return `Self` - --> $DIR/new_ret_no_self.rs:421:9 - | -LL | / pub fn new() -> X { -LL | | 0i32 -LL | | } - | |_________^ - -error: aborting due to 14 previous errors +error: aborting due to 12 previous errors diff --git a/tests/ui/new_ret_no_self_overflow.rs b/tests/ui/new_ret_no_self_overflow.rs new file mode 100644 index 00000000000..7bc6fec10ba --- /dev/null +++ b/tests/ui/new_ret_no_self_overflow.rs @@ -0,0 +1,26 @@ +#![feature(type_alias_impl_trait)] +#![warn(clippy::new_ret_no_self)] + +mod issue10041 { + struct Bomb; + + impl Bomb { + // Hidden default generic parameter. + pub fn new() -> impl PartialOrd { + 0i32 + } + } + + // TAIT with self-referencing bounds + type X = impl std::ops::Add; + + struct Bomb2; + + impl Bomb2 { + pub fn new() -> X { + 0i32 + } + } +} + +fn main() {} diff --git a/tests/ui/new_ret_no_self_overflow.stderr b/tests/ui/new_ret_no_self_overflow.stderr new file mode 100644 index 00000000000..babb634fdcd --- /dev/null +++ b/tests/ui/new_ret_no_self_overflow.stderr @@ -0,0 +1,9 @@ +error[E0275]: overflow evaluating the requirement `::Output == issue10041::X` + --> $DIR/new_ret_no_self_overflow.rs:20:25 + | +LL | pub fn new() -> X { + | ^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0275`. From 60b7fde4ad0300b014fc47ca888996386bffe954 Mon Sep 17 00:00:00 2001 From: Philipp Krones Date: Fri, 2 Jun 2023 18:02:07 +0200 Subject: [PATCH 211/310] Adapt versions.html file to cleaned up gh-pages --- util/gh-pages/versions.html | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/util/gh-pages/versions.html b/util/gh-pages/versions.html index 6e810a349bf..31ce8819329 100644 --- a/util/gh-pages/versions.html +++ b/util/gh-pages/versions.html @@ -36,7 +36,7 @@ @@ -54,18 +54,15 @@ .controller('docVersions', function ($scope, $http) { $scope.loading = true; - $scope.normalizeVersionDisplay = function(v) { - return v.replace(/^v/, ''); - }; - $scope.normalizeVersion = function(v) { - return v.replace(/^v/, '').replace(/^rust-/, ''); + return v.replace(/^rust-/, ''); }; $scope.versionOrder = function(v) { if (v === 'master') { return Infinity; } if (v === 'stable') { return Number.MAX_VALUE; } if (v === 'beta') { return Number.MAX_VALUE - 1; } + if (v === 'pre-1.29.0') { return Number.MIN_VALUE; } return $scope.normalizeVersion(v) .split('.') From 445f428a654bc92f629272277b318f2a3580e357 Mon Sep 17 00:00:00 2001 From: Philipp Krones Date: Sat, 17 Jun 2023 10:05:06 +0200 Subject: [PATCH 212/310] Fix version.py after deleting v* dirs I missed updating this file. I also ran black and isort over it. --- util/versions.py | 25 ++++++++++++++++--------- 1 file changed, 16 insertions(+), 9 deletions(-) diff --git a/util/versions.py b/util/versions.py index 0cfa007d1b2..c041fc606a8 100755 --- a/util/versions.py +++ b/util/versions.py @@ -1,24 +1,27 @@ #!/usr/bin/env python import json +import logging as log import os import sys -import logging as log -log.basicConfig(level=log.INFO, format='%(levelname)s: %(message)s') + +log.basicConfig(level=log.INFO, format="%(levelname)s: %(message)s") def key(v): - if v == 'master': - return float('inf') - if v == 'stable': + if v == "master": + return float("inf") + if v == "stable": return sys.maxsize - if v == 'beta': + if v == "beta": return sys.maxsize - 1 + if v == "pre-1.29.0": + return -1 - v = v.replace('v', '').replace('rust-', '') + v = v.replace("rust-", "") s = 0 - for i, val in enumerate(v.split('.')[::-1]): + for i, val in enumerate(v.split(".")[::-1]): s += int(val) * 100**i return s @@ -31,7 +34,11 @@ def main(): outdir = sys.argv[1] versions = [ - dir for dir in os.listdir(outdir) if not dir.startswith(".") and os.path.isdir(os.path.join(outdir, dir)) + dir + for dir in os.listdir(outdir) + if not dir.startswith(".") + and not dir.startswith("v") + and os.path.isdir(os.path.join(outdir, dir)) ] versions.sort(key=key) From 520228b37741915c65aae2f2d6c0f381156c91cc Mon Sep 17 00:00:00 2001 From: Renato Lochetti Date: Sun, 4 Jun 2023 13:11:50 +0100 Subject: [PATCH 213/310] Adding configuration to allow safety comment above stmt containing unsafe block --- book/src/lint_configuration.md | 10 +++++ clippy_lints/src/lib.rs | 7 ++- .../src/undocumented_unsafe_blocks.rs | 44 ++++++++++++++++--- clippy_lints/src/utils/conf.rs | 4 ++ .../toml_unknown_key/conf_unknown_key.stderr | 2 + .../undocumented_unsafe_blocks/clippy.toml | 1 + .../undocumented_unsafe_blocks.rs | 12 +++++ tests/ui/undocumented_unsafe_blocks.rs | 10 +++++ tests/ui/undocumented_unsafe_blocks.stderr | 10 ++++- 9 files changed, 93 insertions(+), 7 deletions(-) create mode 100644 tests/ui-toml/undocumented_unsafe_blocks/clippy.toml create mode 100644 tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs diff --git a/book/src/lint_configuration.md b/book/src/lint_configuration.md index 085dff8e63b..bd44af66d42 100644 --- a/book/src/lint_configuration.md +++ b/book/src/lint_configuration.md @@ -695,3 +695,13 @@ Minimum chars an ident can have, anything below or equal to this will be linted. * [`min_ident_chars`](https://rust-lang.github.io/rust-clippy/master/index.html#min_ident_chars) +## `accept-comment-above-statement` +Whether to accept a safety comment to be placed above the statement containing the `usafe` block + +**Default Value:** `false` (`bool`) + +--- +**Affected lints:** +* [`undocumented_unsafe_blocks`](https://rust-lang.github.io/rust-clippy/master/index.html#undocumented_unsafe_blocks) + + diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index f0a873b91eb..6ea329a9542 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -929,7 +929,12 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: enable_raw_pointer_heuristic_for_send, )) }); - store.register_late_pass(move |_| Box::new(undocumented_unsafe_blocks::UndocumentedUnsafeBlocks)); + let accept_comment_above_statement = conf.accept_comment_above_statement; + store.register_late_pass(move |_| { + Box::new(undocumented_unsafe_blocks::UndocumentedUnsafeBlocks::new( + accept_comment_above_statement, + )) + }); let allow_mixed_uninlined = conf.allow_mixed_uninlined_format_args; store.register_late_pass(move |_| Box::new(format_args::FormatArgs::new(msrv(), allow_mixed_uninlined))); store.register_late_pass(|_| Box::new(trailing_empty_array::TrailingEmptyArray)); diff --git a/clippy_lints/src/undocumented_unsafe_blocks.rs b/clippy_lints/src/undocumented_unsafe_blocks.rs index 2920684ade3..bc739dca0b9 100644 --- a/clippy_lints/src/undocumented_unsafe_blocks.rs +++ b/clippy_lints/src/undocumented_unsafe_blocks.rs @@ -11,7 +11,7 @@ use rustc_hir::{Block, BlockCheckMode, ItemKind, Node, UnsafeSource}; use rustc_lexer::{tokenize, TokenKind}; use rustc_lint::{LateContext, LateLintPass, LintContext}; use rustc_middle::lint::in_external_macro; -use rustc_session::{declare_lint_pass, declare_tool_lint}; +use rustc_session::{declare_tool_lint, impl_lint_pass}; use rustc_span::{BytePos, Pos, Span, SyntaxContext}; declare_clippy_lint! { @@ -92,7 +92,20 @@ declare_clippy_lint! { "annotating safe code with a safety comment" } -declare_lint_pass!(UndocumentedUnsafeBlocks => [UNDOCUMENTED_UNSAFE_BLOCKS, UNNECESSARY_SAFETY_COMMENT]); +#[derive(Copy, Clone)] +pub struct UndocumentedUnsafeBlocks { + accept_comment_above_statement: bool, +} + +impl UndocumentedUnsafeBlocks { + pub fn new(accept_comment_above_statement: bool) -> Self { + Self { + accept_comment_above_statement, + } + } +} + +impl_lint_pass!(UndocumentedUnsafeBlocks => [UNDOCUMENTED_UNSAFE_BLOCKS, UNNECESSARY_SAFETY_COMMENT]); impl<'tcx> LateLintPass<'tcx> for UndocumentedUnsafeBlocks { fn check_block(&mut self, cx: &LateContext<'tcx>, block: &'tcx Block<'tcx>) { @@ -101,7 +114,7 @@ impl<'tcx> LateLintPass<'tcx> for UndocumentedUnsafeBlocks { && !is_lint_allowed(cx, UNDOCUMENTED_UNSAFE_BLOCKS, block.hir_id) && !is_unsafe_from_proc_macro(cx, block.span) && !block_has_safety_comment(cx, block.span) - && !block_parents_have_safety_comment(cx, block.hir_id) + && !block_parents_have_safety_comment(self.accept_comment_above_statement, cx, block.hir_id) { let source_map = cx.tcx.sess.source_map(); let span = if source_map.is_multiline(block.span) { @@ -313,10 +326,31 @@ fn is_unsafe_from_proc_macro(cx: &LateContext<'_>, span: Span) -> bool { // Checks if any parent {expression, statement, block, local, const, static} // has a safety comment -fn block_parents_have_safety_comment(cx: &LateContext<'_>, id: hir::HirId) -> bool { +fn block_parents_have_safety_comment( + accept_comment_above_statement: bool, + cx: &LateContext<'_>, + id: hir::HirId, +) -> bool { if let Some(node) = get_parent_node(cx.tcx, id) { return match node { - Node::Expr(expr) => !is_branchy(expr) && span_in_body_has_safety_comment(cx, expr.span), + Node::Expr(expr) => { + if let Some( + Node::Local(hir::Local { span, .. }) + | Node::Item(hir::Item { + kind: hir::ItemKind::Const(..) | ItemKind::Static(..), + span, + .. + }), + ) = get_parent_node(cx.tcx, expr.hir_id) + { + // if unsafe block is part of a let/const/static statement, + // and accept_comment_above_statement is set to true + // we accept the safety comment in the line the precedes this statement. + accept_comment_above_statement && span_in_body_has_safety_comment(cx, *span) + } else { + !is_branchy(expr) && span_in_body_has_safety_comment(cx, expr.span) + } + }, Node::Stmt(hir::Stmt { kind: hir::StmtKind::Local(hir::Local { span, .. }) diff --git a/clippy_lints/src/utils/conf.rs b/clippy_lints/src/utils/conf.rs index f6c7c1fa065..fccddfbdb8b 100644 --- a/clippy_lints/src/utils/conf.rs +++ b/clippy_lints/src/utils/conf.rs @@ -538,6 +538,10 @@ define_Conf! { /// /// Minimum chars an ident can have, anything below or equal to this will be linted. (min_ident_chars_threshold: u64 = 1), + /// Lint: UNDOCUMENTED_UNSAFE_BLOCKS. + /// + /// Whether to accept a safety comment to be placed above the statement containing the `usafe` block + (accept_comment_above_statement: bool = false), } /// Search for the configuration file. 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 d8ce0e2f55d..db2071ecaaf 100644 --- a/tests/ui-toml/toml_unknown_key/conf_unknown_key.stderr +++ b/tests/ui-toml/toml_unknown_key/conf_unknown_key.stderr @@ -1,4 +1,5 @@ error: error reading Clippy's configuration file: unknown field `foobar`, expected one of + accept-comment-above-statement allow-dbg-in-tests allow-expect-in-tests allow-mixed-uninlined-format-args @@ -65,6 +66,7 @@ LL | foobar = 42 | ^^^^^^ error: error reading Clippy's configuration file: unknown field `barfoo`, expected one of + accept-comment-above-statement allow-dbg-in-tests allow-expect-in-tests allow-mixed-uninlined-format-args diff --git a/tests/ui-toml/undocumented_unsafe_blocks/clippy.toml b/tests/ui-toml/undocumented_unsafe_blocks/clippy.toml new file mode 100644 index 00000000000..1c2e7aeaff9 --- /dev/null +++ b/tests/ui-toml/undocumented_unsafe_blocks/clippy.toml @@ -0,0 +1 @@ +accept-comment-above-statement = true diff --git a/tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs b/tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs new file mode 100644 index 00000000000..ef208f2c390 --- /dev/null +++ b/tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs @@ -0,0 +1,12 @@ +#![deny(clippy::undocumented_unsafe_blocks)] +#![allow(clippy::missing_safety_doc)] + +fn main() { + // Safety: A safety comment + let _some_variable_with_a_very_long_name_to_break_the_line = + unsafe { a_function_with_a_very_long_name_to_break_the_line() }; +} + +pub unsafe fn a_function_with_a_very_long_name_to_break_the_line() -> u32 { + 1 +} diff --git a/tests/ui/undocumented_unsafe_blocks.rs b/tests/ui/undocumented_unsafe_blocks.rs index 229d150851a..fa86352554b 100644 --- a/tests/ui/undocumented_unsafe_blocks.rs +++ b/tests/ui/undocumented_unsafe_blocks.rs @@ -509,4 +509,14 @@ fn issue_9142() { }; } +pub unsafe fn a_function_with_a_very_long_name_to_break_the_line() -> u32 { + 1 +} + +fn issue_10832() { + // Safety: A safety comment. But it will warn anyways + let _some_variable_with_a_very_long_name_to_break_the_line = + unsafe { a_function_with_a_very_long_name_to_break_the_line() }; +} + fn main() {} diff --git a/tests/ui/undocumented_unsafe_blocks.stderr b/tests/ui/undocumented_unsafe_blocks.stderr index d1c1bb5ffea..84a8e681f67 100644 --- a/tests/ui/undocumented_unsafe_blocks.stderr +++ b/tests/ui/undocumented_unsafe_blocks.stderr @@ -318,5 +318,13 @@ LL | let bar = unsafe {}; | = help: consider adding a safety comment on the preceding line -error: aborting due to 36 previous errors +error: unsafe block missing a safety comment + --> $DIR/undocumented_unsafe_blocks.rs:519:9 + | +LL | unsafe { a_function_with_a_very_long_name_to_break_the_line() }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: consider adding a safety comment on the preceding line + +error: aborting due to 37 previous errors From e2e6a02445980cd7eb213e87ad22e3bb9b074907 Mon Sep 17 00:00:00 2001 From: Renato Lochetti Date: Mon, 5 Jun 2023 08:55:39 +0100 Subject: [PATCH 214/310] Addressing reviewer comments --- book/src/lint_configuration.md | 2 +- .../src/undocumented_unsafe_blocks.rs | 9 ++++++++- clippy_lints/src/utils/conf.rs | 2 +- .../undocumented_unsafe_blocks.rs | 12 +++++++++++ tests/ui/undocumented_unsafe_blocks.rs | 12 +++++++++++ tests/ui/undocumented_unsafe_blocks.stderr | 20 +++++++++++++++++-- 6 files changed, 52 insertions(+), 5 deletions(-) diff --git a/book/src/lint_configuration.md b/book/src/lint_configuration.md index bd44af66d42..78a5f9da461 100644 --- a/book/src/lint_configuration.md +++ b/book/src/lint_configuration.md @@ -696,7 +696,7 @@ Minimum chars an ident can have, anything below or equal to this will be linted. ## `accept-comment-above-statement` -Whether to accept a safety comment to be placed above the statement containing the `usafe` block +Whether to accept a safety comment to be placed above the statement containing the `unsafe` block **Default Value:** `false` (`bool`) diff --git a/clippy_lints/src/undocumented_unsafe_blocks.rs b/clippy_lints/src/undocumented_unsafe_blocks.rs index bc739dca0b9..1676c767a34 100644 --- a/clippy_lints/src/undocumented_unsafe_blocks.rs +++ b/clippy_lints/src/undocumented_unsafe_blocks.rs @@ -580,7 +580,14 @@ fn get_body_search_span(cx: &LateContext<'_>) -> Option { for (_, node) in map.parent_iter(body.hir_id) { match node { Node::Expr(e) => span = e.span, - Node::Block(_) | Node::Arm(_) | Node::Stmt(_) | Node::Local(_) => (), + Node::Block(_) + | Node::Arm(_) + | Node::Stmt(_) + | Node::Local(_) + | Node::Item(hir::Item { + kind: hir::ItemKind::Const(..) | ItemKind::Static(..), + .. + }) => (), _ => break, } } diff --git a/clippy_lints/src/utils/conf.rs b/clippy_lints/src/utils/conf.rs index fccddfbdb8b..e8c8d478ffc 100644 --- a/clippy_lints/src/utils/conf.rs +++ b/clippy_lints/src/utils/conf.rs @@ -540,7 +540,7 @@ define_Conf! { (min_ident_chars_threshold: u64 = 1), /// Lint: UNDOCUMENTED_UNSAFE_BLOCKS. /// - /// Whether to accept a safety comment to be placed above the statement containing the `usafe` block + /// Whether to accept a safety comment to be placed above the statement containing the `unsafe` block (accept_comment_above_statement: bool = false), } diff --git a/tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs b/tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs index ef208f2c390..e1ba1b2f67e 100644 --- a/tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs +++ b/tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs @@ -5,8 +5,20 @@ fn main() { // Safety: A safety comment let _some_variable_with_a_very_long_name_to_break_the_line = unsafe { a_function_with_a_very_long_name_to_break_the_line() }; + + // Safety: Another safety comment + const _SOME_CONST_WITH_A_VERY_LONG_NAME_TO_BREAK_THE_LINE: u32 = + unsafe { a_const_function_with_a_very_long_name_to_break_the_line() }; + + // Safety: Yet another safety comment + static _SOME_STATIC_WITH_A_VERY_LONG_NAME_TO_BREAK_THE_LINE: u32 = + unsafe { a_const_function_with_a_very_long_name_to_break_the_line() }; } pub unsafe fn a_function_with_a_very_long_name_to_break_the_line() -> u32 { 1 } + +pub const unsafe fn a_const_function_with_a_very_long_name_to_break_the_line() -> u32 { + 2 +} diff --git a/tests/ui/undocumented_unsafe_blocks.rs b/tests/ui/undocumented_unsafe_blocks.rs index fa86352554b..f4e7f1943ae 100644 --- a/tests/ui/undocumented_unsafe_blocks.rs +++ b/tests/ui/undocumented_unsafe_blocks.rs @@ -513,10 +513,22 @@ pub unsafe fn a_function_with_a_very_long_name_to_break_the_line() -> u32 { 1 } +pub const unsafe fn a_const_function_with_a_very_long_name_to_break_the_line() -> u32 { + 2 +} + fn issue_10832() { // Safety: A safety comment. But it will warn anyways let _some_variable_with_a_very_long_name_to_break_the_line = unsafe { a_function_with_a_very_long_name_to_break_the_line() }; + + // Safety: Another safety comment. But it will warn anyways + const _SOME_CONST_WITH_A_VERY_LONG_NAME_TO_BREAK_THE_LINE: u32 = + unsafe { a_const_function_with_a_very_long_name_to_break_the_line() }; + + // Safety: Yet another safety comment. But it will warn anyways + static _SOME_STATIC_WITH_A_VERY_LONG_NAME_TO_BREAK_THE_LINE: u32 = + unsafe { a_const_function_with_a_very_long_name_to_break_the_line() }; } fn main() {} diff --git a/tests/ui/undocumented_unsafe_blocks.stderr b/tests/ui/undocumented_unsafe_blocks.stderr index 84a8e681f67..ee1d3aa285a 100644 --- a/tests/ui/undocumented_unsafe_blocks.stderr +++ b/tests/ui/undocumented_unsafe_blocks.stderr @@ -319,12 +319,28 @@ LL | let bar = unsafe {}; = help: consider adding a safety comment on the preceding line error: unsafe block missing a safety comment - --> $DIR/undocumented_unsafe_blocks.rs:519:9 + --> $DIR/undocumented_unsafe_blocks.rs:523:9 | LL | unsafe { a_function_with_a_very_long_name_to_break_the_line() }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = help: consider adding a safety comment on the preceding line -error: aborting due to 37 previous errors +error: unsafe block missing a safety comment + --> $DIR/undocumented_unsafe_blocks.rs:527:9 + | +LL | unsafe { a_const_function_with_a_very_long_name_to_break_the_line() }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: consider adding a safety comment on the preceding line + +error: unsafe block missing a safety comment + --> $DIR/undocumented_unsafe_blocks.rs:531:9 + | +LL | unsafe { a_const_function_with_a_very_long_name_to_break_the_line() }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: consider adding a safety comment on the preceding line + +error: aborting due to 39 previous errors From 8625a849d19cfc7934a3795312e6ba3b1c00a1d9 Mon Sep 17 00:00:00 2001 From: Renato Lochetti Date: Thu, 8 Jun 2023 07:29:05 +0100 Subject: [PATCH 215/310] adding all ui tests to the configuration test as well --- .../auxiliary/proc_macro_unsafe.rs | 18 + .../undocumented_unsafe_blocks.rs | 530 +++++++++++++++++- .../undocumented_unsafe_blocks.stderr | 314 +++++++++++ 3 files changed, 852 insertions(+), 10 deletions(-) create mode 100644 tests/ui-toml/undocumented_unsafe_blocks/auxiliary/proc_macro_unsafe.rs create mode 100644 tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.stderr diff --git a/tests/ui-toml/undocumented_unsafe_blocks/auxiliary/proc_macro_unsafe.rs b/tests/ui-toml/undocumented_unsafe_blocks/auxiliary/proc_macro_unsafe.rs new file mode 100644 index 00000000000..c2326678d0d --- /dev/null +++ b/tests/ui-toml/undocumented_unsafe_blocks/auxiliary/proc_macro_unsafe.rs @@ -0,0 +1,18 @@ +//@compile-flags: --emit=link +//@no-prefer-dynamic + +#![crate_type = "proc-macro"] + +extern crate proc_macro; + +use proc_macro::{Delimiter, Group, Ident, TokenStream, TokenTree}; + +#[proc_macro] +pub fn unsafe_block(input: TokenStream) -> TokenStream { + let span = input.into_iter().next().unwrap().span(); + TokenStream::from_iter([TokenTree::Ident(Ident::new("unsafe", span)), { + let mut group = Group::new(Delimiter::Brace, TokenStream::new()); + group.set_span(span); + TokenTree::Group(group) + }]) +} diff --git a/tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs b/tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs index e1ba1b2f67e..533f90483e5 100644 --- a/tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs +++ b/tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs @@ -1,7 +1,523 @@ -#![deny(clippy::undocumented_unsafe_blocks)] -#![allow(clippy::missing_safety_doc)] +//@aux-build:proc_macro_unsafe.rs -fn main() { +#![warn(clippy::undocumented_unsafe_blocks, clippy::unnecessary_safety_comment)] +#![allow(clippy::let_unit_value, clippy::missing_safety_doc)] + +extern crate proc_macro_unsafe; + +// Valid comments + +fn nested_local() { + let _ = { + let _ = { + // SAFETY: + let _ = unsafe {}; + }; + }; +} + +fn deep_nest() { + let _ = { + let _ = { + // SAFETY: + let _ = unsafe {}; + + // Safety: + unsafe {}; + + let _ = { + let _ = { + let _ = { + let _ = { + let _ = { + // Safety: + let _ = unsafe {}; + + // SAFETY: + unsafe {}; + }; + }; + }; + + // Safety: + unsafe {}; + }; + }; + }; + + // Safety: + unsafe {}; + }; + + // SAFETY: + unsafe {}; +} + +fn local_tuple_expression() { + // Safety: + let _ = (42, unsafe {}); +} + +fn line_comment() { + // Safety: + unsafe {} +} + +fn line_comment_newlines() { + // SAFETY: + + unsafe {} +} + +fn line_comment_empty() { + // Safety: + // + // + // + unsafe {} +} + +fn line_comment_with_extras() { + // This is a description + // Safety: + unsafe {} +} + +fn block_comment() { + /* Safety: */ + unsafe {} +} + +fn block_comment_newlines() { + /* SAFETY: */ + + unsafe {} +} + +fn block_comment_with_extras() { + /* This is a description + * SAFETY: + */ + unsafe {} +} + +fn block_comment_terminator_same_line() { + /* This is a description + * Safety: */ + unsafe {} +} + +fn buried_safety() { + // Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor + // incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation + // ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in + // reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint + // occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est + // laborum. Safety: + // Tellus elementum sagittis vitae et leo duis ut diam quam. Sit amet nulla facilisi + // morbi tempus iaculis urna. Amet luctus venenatis lectus magna. At quis risus sed vulputate odio + // ut. Luctus venenatis lectus magna fringilla urna. Tortor id aliquet lectus proin nibh nisl + // condimentum id venenatis. Vulputate dignissim suspendisse in est ante in nibh mauris cursus. + unsafe {} +} + +fn safety_with_prepended_text() { + // This is a test. safety: + unsafe {} +} + +fn local_line_comment() { + // Safety: + let _ = unsafe {}; +} + +fn local_block_comment() { + /* SAFETY: */ + let _ = unsafe {}; +} + +fn comment_array() { + // Safety: + let _ = [unsafe { 14 }, unsafe { 15 }, 42, unsafe { 16 }]; +} + +fn comment_tuple() { + // sAFETY: + let _ = (42, unsafe {}, "test", unsafe {}); +} + +fn comment_unary() { + // SAFETY: + let _ = *unsafe { &42 }; +} + +#[allow(clippy::match_single_binding)] +fn comment_match() { + // SAFETY: + let _ = match unsafe {} { + _ => {}, + }; +} + +fn comment_addr_of() { + // Safety: + let _ = &unsafe {}; +} + +fn comment_repeat() { + // Safety: + let _ = [unsafe {}; 5]; +} + +fn comment_macro_call() { + macro_rules! t { + ($b:expr) => { + $b + }; + } + + t!( + // SAFETY: + unsafe {} + ); +} + +fn comment_macro_def() { + macro_rules! t { + () => { + // Safety: + unsafe {} + }; + } + + t!(); +} + +fn non_ascii_comment() { + // ॐ᧻໒ SaFeTy: ௵∰ + unsafe {}; +} + +fn local_commented_block() { + let _ = + // safety: + unsafe {}; +} + +fn local_nest() { + // safety: + let _ = [(42, unsafe {}, unsafe {}), (52, unsafe {}, unsafe {})]; +} + +fn in_fn_call(x: *const u32) { + fn f(x: u32) {} + + // Safety: reason + f(unsafe { *x }); +} + +fn multi_in_fn_call(x: *const u32) { + fn f(x: u32, y: u32) {} + + // Safety: reason + f(unsafe { *x }, unsafe { *x }); +} + +fn in_multiline_fn_call(x: *const u32) { + fn f(x: u32, y: u32) {} + + f( + // Safety: reason + unsafe { *x }, + 0, + ); +} + +fn in_macro_call(x: *const u32) { + // Safety: reason + println!("{}", unsafe { *x }); +} + +fn in_multiline_macro_call(x: *const u32) { + println!( + "{}", + // Safety: reason + unsafe { *x }, + ); +} + +fn from_proc_macro() { + proc_macro_unsafe::unsafe_block!(token); +} + +fn in_closure(x: *const u32) { + // Safety: reason + let _ = || unsafe { *x }; +} + +// Invalid comments + +#[rustfmt::skip] +fn inline_block_comment() { + /* Safety: */ unsafe {} +} + +fn no_comment() { + unsafe {} +} + +fn no_comment_array() { + let _ = [unsafe { 14 }, unsafe { 15 }, 42, unsafe { 16 }]; +} + +fn no_comment_tuple() { + let _ = (42, unsafe {}, "test", unsafe {}); +} + +fn no_comment_unary() { + let _ = *unsafe { &42 }; +} + +#[allow(clippy::match_single_binding)] +fn no_comment_match() { + let _ = match unsafe {} { + _ => {}, + }; +} + +fn no_comment_addr_of() { + let _ = &unsafe {}; +} + +fn no_comment_repeat() { + let _ = [unsafe {}; 5]; +} + +fn local_no_comment() { + let _ = unsafe {}; +} + +fn no_comment_macro_call() { + macro_rules! t { + ($b:expr) => { + $b + }; + } + + t!(unsafe {}); +} + +fn no_comment_macro_def() { + macro_rules! t { + () => { + unsafe {} + }; + } + + t!(); +} + +fn trailing_comment() { + unsafe {} // SAFETY: +} + +fn internal_comment() { + unsafe { + // SAFETY: + } +} + +fn interference() { + // SAFETY + + let _ = 42; + + unsafe {}; +} + +pub fn print_binary_tree() { + println!("{}", unsafe { String::from_utf8_unchecked(vec![]) }); +} + +mod unsafe_impl_smoke_test { + unsafe trait A {} + + // error: no safety comment + unsafe impl A for () {} + + // Safety: ok + unsafe impl A for (i32) {} + + mod sub_mod { + // error: + unsafe impl B for (u32) {} + unsafe trait B {} + } + + #[rustfmt::skip] + mod sub_mod2 { + // + // SAFETY: ok + // + + unsafe impl B for (u32) {} + unsafe trait B {} + } +} + +mod unsafe_impl_from_macro { + unsafe trait T {} + + // error + macro_rules! no_safety_comment { + ($t:ty) => { + unsafe impl T for $t {} + }; + } + + // ok + no_safety_comment!(()); + + // ok + macro_rules! with_safety_comment { + ($t:ty) => { + // SAFETY: + unsafe impl T for $t {} + }; + } + + // ok + with_safety_comment!((i32)); +} + +mod unsafe_impl_macro_and_not_macro { + unsafe trait T {} + + // error + macro_rules! no_safety_comment { + ($t:ty) => { + unsafe impl T for $t {} + }; + } + + // ok + no_safety_comment!(()); + + // error + unsafe impl T for (i32) {} + + // ok + no_safety_comment!(u32); + + // error + unsafe impl T for (bool) {} +} + +#[rustfmt::skip] +mod unsafe_impl_valid_comment { + unsafe trait SaFety {} + // SaFety: + unsafe impl SaFety for () {} + + unsafe trait MultiLineComment {} + // The following impl is safe + // ... + // Safety: reason + unsafe impl MultiLineComment for () {} + + unsafe trait NoAscii {} + // 安全 SAFETY: 以下のコードは安全です + unsafe impl NoAscii for () {} + + unsafe trait InlineAndPrecedingComment {} + // SAFETY: + /* comment */ unsafe impl InlineAndPrecedingComment for () {} + + unsafe trait BuriedSafety {} + // Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor + // incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation + // ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in + // reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint + // occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est + // laborum. Safety: + // Tellus elementum sagittis vitae et leo duis ut diam quam. Sit amet nulla facilisi + // morbi tempus iaculis urna. Amet luctus venenatis lectus magna. At quis risus sed vulputate odio + // ut. Luctus venenatis lectus magna fringilla urna. Tortor id aliquet lectus proin nibh nisl + // condimentum id venenatis. Vulputate dignissim suspendisse in est ante in nibh mauris cursus. + unsafe impl BuriedSafety for () {} + + unsafe trait MultiLineBlockComment {} + /* This is a description + * Safety: */ + unsafe impl MultiLineBlockComment for () {} +} + +#[rustfmt::skip] +mod unsafe_impl_invalid_comment { + unsafe trait NoComment {} + + unsafe impl NoComment for () {} + + unsafe trait InlineComment {} + + /* SAFETY: */ unsafe impl InlineComment for () {} + + unsafe trait TrailingComment {} + + unsafe impl TrailingComment for () {} // SAFETY: + + unsafe trait Interference {} + // SAFETY: + const BIG_NUMBER: i32 = 1000000; + unsafe impl Interference for () {} +} + +unsafe trait ImplInFn {} + +fn impl_in_fn() { + // error + unsafe impl ImplInFn for () {} + + // SAFETY: ok + unsafe impl ImplInFn for (i32) {} +} + +unsafe trait CrateRoot {} + +// error +unsafe impl CrateRoot for () {} + +// SAFETY: ok +unsafe impl CrateRoot for (i32) {} + +fn issue_9142() { + // SAFETY: ok + let _ = + // we need this comment to avoid rustfmt putting + // it all on one line + unsafe {}; + + // SAFETY: this is more than one level away, so it should warn + let _ = { + if unsafe { true } { + todo!(); + } else { + let bar = unsafe {}; + todo!(); + bar + } + }; +} + +pub unsafe fn a_function_with_a_very_long_name_to_break_the_line() -> u32 { + 1 +} + +pub const unsafe fn a_const_function_with_a_very_long_name_to_break_the_line() -> u32 { + 2 +} + +fn issue_10832() { // Safety: A safety comment let _some_variable_with_a_very_long_name_to_break_the_line = unsafe { a_function_with_a_very_long_name_to_break_the_line() }; @@ -15,10 +531,4 @@ fn main() { unsafe { a_const_function_with_a_very_long_name_to_break_the_line() }; } -pub unsafe fn a_function_with_a_very_long_name_to_break_the_line() -> u32 { - 1 -} - -pub const unsafe fn a_const_function_with_a_very_long_name_to_break_the_line() -> u32 { - 2 -} +fn main() {} diff --git a/tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.stderr b/tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.stderr new file mode 100644 index 00000000000..ac987a9e995 --- /dev/null +++ b/tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.stderr @@ -0,0 +1,314 @@ +error: unsafe block missing a safety comment + --> $DIR/undocumented_unsafe_blocks.rs:262:19 + | +LL | /* Safety: */ unsafe {} + | ^^^^^^^^^ + | + = help: consider adding a safety comment on the preceding line + = note: `-D clippy::undocumented-unsafe-blocks` implied by `-D warnings` + +error: unsafe block missing a safety comment + --> $DIR/undocumented_unsafe_blocks.rs:266:5 + | +LL | unsafe {} + | ^^^^^^^^^ + | + = help: consider adding a safety comment on the preceding line + +error: unsafe block missing a safety comment + --> $DIR/undocumented_unsafe_blocks.rs:270:14 + | +LL | let _ = [unsafe { 14 }, unsafe { 15 }, 42, unsafe { 16 }]; + | ^^^^^^^^^^^^^ + | + = help: consider adding a safety comment on the preceding line + +error: unsafe block missing a safety comment + --> $DIR/undocumented_unsafe_blocks.rs:270:29 + | +LL | let _ = [unsafe { 14 }, unsafe { 15 }, 42, unsafe { 16 }]; + | ^^^^^^^^^^^^^ + | + = help: consider adding a safety comment on the preceding line + +error: unsafe block missing a safety comment + --> $DIR/undocumented_unsafe_blocks.rs:270:48 + | +LL | let _ = [unsafe { 14 }, unsafe { 15 }, 42, unsafe { 16 }]; + | ^^^^^^^^^^^^^ + | + = help: consider adding a safety comment on the preceding line + +error: unsafe block missing a safety comment + --> $DIR/undocumented_unsafe_blocks.rs:274:18 + | +LL | let _ = (42, unsafe {}, "test", unsafe {}); + | ^^^^^^^^^ + | + = help: consider adding a safety comment on the preceding line + +error: unsafe block missing a safety comment + --> $DIR/undocumented_unsafe_blocks.rs:274:37 + | +LL | let _ = (42, unsafe {}, "test", unsafe {}); + | ^^^^^^^^^ + | + = help: consider adding a safety comment on the preceding line + +error: unsafe block missing a safety comment + --> $DIR/undocumented_unsafe_blocks.rs:278:14 + | +LL | let _ = *unsafe { &42 }; + | ^^^^^^^^^^^^^^ + | + = help: consider adding a safety comment on the preceding line + +error: unsafe block missing a safety comment + --> $DIR/undocumented_unsafe_blocks.rs:283:19 + | +LL | let _ = match unsafe {} { + | ^^^^^^^^^ + | + = help: consider adding a safety comment on the preceding line + +error: unsafe block missing a safety comment + --> $DIR/undocumented_unsafe_blocks.rs:289:14 + | +LL | let _ = &unsafe {}; + | ^^^^^^^^^ + | + = help: consider adding a safety comment on the preceding line + +error: unsafe block missing a safety comment + --> $DIR/undocumented_unsafe_blocks.rs:293:14 + | +LL | let _ = [unsafe {}; 5]; + | ^^^^^^^^^ + | + = help: consider adding a safety comment on the preceding line + +error: unsafe block missing a safety comment + --> $DIR/undocumented_unsafe_blocks.rs:297:13 + | +LL | let _ = unsafe {}; + | ^^^^^^^^^ + | + = help: consider adding a safety comment on the preceding line + +error: unsafe block missing a safety comment + --> $DIR/undocumented_unsafe_blocks.rs:307:8 + | +LL | t!(unsafe {}); + | ^^^^^^^^^ + | + = help: consider adding a safety comment on the preceding line + +error: unsafe block missing a safety comment + --> $DIR/undocumented_unsafe_blocks.rs:313:13 + | +LL | unsafe {} + | ^^^^^^^^^ +... +LL | t!(); + | ---- in this macro invocation + | + = help: consider adding a safety comment on the preceding line + = note: this error originates in the macro `t` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: unsafe block missing a safety comment + --> $DIR/undocumented_unsafe_blocks.rs:321:5 + | +LL | unsafe {} // SAFETY: + | ^^^^^^^^^ + | + = help: consider adding a safety comment on the preceding line + +error: unsafe block missing a safety comment + --> $DIR/undocumented_unsafe_blocks.rs:325:5 + | +LL | unsafe { + | ^^^^^^^^ + | + = help: consider adding a safety comment on the preceding line + +error: unsafe block missing a safety comment + --> $DIR/undocumented_unsafe_blocks.rs:335:5 + | +LL | unsafe {}; + | ^^^^^^^^^ + | + = help: consider adding a safety comment on the preceding line + +error: unsafe block missing a safety comment + --> $DIR/undocumented_unsafe_blocks.rs:339:20 + | +LL | println!("{}", unsafe { String::from_utf8_unchecked(vec![]) }); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: consider adding a safety comment on the preceding line + +error: unsafe impl missing a safety comment + --> $DIR/undocumented_unsafe_blocks.rs:346:5 + | +LL | unsafe impl A for () {} + | ^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: consider adding a safety comment on the preceding line + +error: unsafe impl missing a safety comment + --> $DIR/undocumented_unsafe_blocks.rs:353:9 + | +LL | unsafe impl B for (u32) {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: consider adding a safety comment on the preceding line + +error: unsafe impl missing a safety comment + --> $DIR/undocumented_unsafe_blocks.rs:374:13 + | +LL | unsafe impl T for $t {} + | ^^^^^^^^^^^^^^^^^^^^^^^ +... +LL | no_safety_comment!(()); + | ---------------------- in this macro invocation + | + = help: consider adding a safety comment on the preceding line + = note: this error originates in the macro `no_safety_comment` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: unsafe impl missing a safety comment + --> $DIR/undocumented_unsafe_blocks.rs:399:13 + | +LL | unsafe impl T for $t {} + | ^^^^^^^^^^^^^^^^^^^^^^^ +... +LL | no_safety_comment!(()); + | ---------------------- in this macro invocation + | + = help: consider adding a safety comment on the preceding line + = note: this error originates in the macro `no_safety_comment` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: unsafe impl missing a safety comment + --> $DIR/undocumented_unsafe_blocks.rs:407:5 + | +LL | unsafe impl T for (i32) {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: consider adding a safety comment on the preceding line + +error: unsafe impl missing a safety comment + --> $DIR/undocumented_unsafe_blocks.rs:399:13 + | +LL | unsafe impl T for $t {} + | ^^^^^^^^^^^^^^^^^^^^^^^ +... +LL | no_safety_comment!(u32); + | ----------------------- in this macro invocation + | + = help: consider adding a safety comment on the preceding line + = note: this error originates in the macro `no_safety_comment` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: unsafe impl missing a safety comment + --> $DIR/undocumented_unsafe_blocks.rs:413:5 + | +LL | unsafe impl T for (bool) {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: consider adding a safety comment on the preceding line + +error: unsafe impl missing a safety comment + --> $DIR/undocumented_unsafe_blocks.rs:459:5 + | +LL | unsafe impl NoComment for () {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: consider adding a safety comment on the preceding line + +error: unsafe impl missing a safety comment + --> $DIR/undocumented_unsafe_blocks.rs:463:19 + | +LL | /* SAFETY: */ unsafe impl InlineComment for () {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: consider adding a safety comment on the preceding line + +error: unsafe impl missing a safety comment + --> $DIR/undocumented_unsafe_blocks.rs:467:5 + | +LL | unsafe impl TrailingComment for () {} // SAFETY: + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: consider adding a safety comment on the preceding line + +error: constant item has unnecessary safety comment + --> $DIR/undocumented_unsafe_blocks.rs:471:5 + | +LL | const BIG_NUMBER: i32 = 1000000; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: consider removing the safety comment + --> $DIR/undocumented_unsafe_blocks.rs:470:5 + | +LL | // SAFETY: + | ^^^^^^^^^^ + = note: `-D clippy::unnecessary-safety-comment` implied by `-D warnings` + +error: unsafe impl missing a safety comment + --> $DIR/undocumented_unsafe_blocks.rs:472:5 + | +LL | unsafe impl Interference for () {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: consider adding a safety comment on the preceding line + +error: unsafe impl missing a safety comment + --> $DIR/undocumented_unsafe_blocks.rs:479:5 + | +LL | unsafe impl ImplInFn for () {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: consider adding a safety comment on the preceding line + +error: unsafe impl missing a safety comment + --> $DIR/undocumented_unsafe_blocks.rs:488:1 + | +LL | unsafe impl CrateRoot for () {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: consider adding a safety comment on the preceding line + +error: statement has unnecessary safety comment + --> $DIR/undocumented_unsafe_blocks.rs:501:5 + | +LL | / let _ = { +LL | | if unsafe { true } { +LL | | todo!(); +LL | | } else { +... | +LL | | } +LL | | }; + | |______^ + | +help: consider removing the safety comment + --> $DIR/undocumented_unsafe_blocks.rs:500:5 + | +LL | // SAFETY: this is more than one level away, so it should warn + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: unsafe block missing a safety comment + --> $DIR/undocumented_unsafe_blocks.rs:502:12 + | +LL | if unsafe { true } { + | ^^^^^^^^^^^^^^^ + | + = help: consider adding a safety comment on the preceding line + +error: unsafe block missing a safety comment + --> $DIR/undocumented_unsafe_blocks.rs:505:23 + | +LL | let bar = unsafe {}; + | ^^^^^^^^^ + | + = help: consider adding a safety comment on the preceding line + +error: aborting due to 35 previous errors + From d6102018bf35786922996068e705bcdd463ab158 Mon Sep 17 00:00:00 2001 From: Renato Lochetti Date: Sat, 17 Jun 2023 09:40:51 -0300 Subject: [PATCH 216/310] Collecting metadata --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 269be545b0a..3eaa0d199fd 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5383,4 +5383,5 @@ Released 2018-09-13 [`allow-private-module-inception`]: https://doc.rust-lang.org/clippy/lint_configuration.html#allow-private-module-inception [`allowed-idents-below-min-chars`]: https://doc.rust-lang.org/clippy/lint_configuration.html#allowed-idents-below-min-chars [`min-ident-chars-threshold`]: https://doc.rust-lang.org/clippy/lint_configuration.html#min-ident-chars-threshold +[`accept-comment-above-statement`]: https://doc.rust-lang.org/clippy/lint_configuration.html#accept-comment-above-statement From 1f621af28cd1cca74cf32aebfc7c24a7e9693223 Mon Sep 17 00:00:00 2001 From: dswij Date: Sat, 17 Jun 2023 23:20:33 +0800 Subject: [PATCH 217/310] Exlude `todo!()` from `missing_panics_in_doc` --- clippy_lints/src/doc.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clippy_lints/src/doc.rs b/clippy_lints/src/doc.rs index 815495a7b7a..87d88f70752 100644 --- a/clippy_lints/src/doc.rs +++ b/clippy_lints/src/doc.rs @@ -909,7 +909,7 @@ impl<'a, 'tcx> Visitor<'tcx> for FindPanicUnwrap<'a, 'tcx> { if is_panic(self.cx, macro_call.def_id) || matches!( self.cx.tcx.item_name(macro_call.def_id).as_str(), - "assert" | "assert_eq" | "assert_ne" | "todo" + "assert" | "assert_eq" | "assert_ne" ) { self.panic_span = Some(macro_call.span); From a6346d7c9d4f3bbc85ee12fd0828fcfa1603cec9 Mon Sep 17 00:00:00 2001 From: dswij Date: Sat, 17 Jun 2023 23:21:09 +0800 Subject: [PATCH 218/310] `missing_panics_in_doc` bless test and add additional macro testcase --- tests/ui/auxiliary/macro_rules.rs | 7 ++++ tests/ui/missing_panics_doc.rs | 46 +++++++++++++--------- tests/ui/missing_panics_doc.stderr | 62 ++++++++++++------------------ 3 files changed, 59 insertions(+), 56 deletions(-) diff --git a/tests/ui/auxiliary/macro_rules.rs b/tests/ui/auxiliary/macro_rules.rs index d9a1e76c077..6b164967a28 100644 --- a/tests/ui/auxiliary/macro_rules.rs +++ b/tests/ui/auxiliary/macro_rules.rs @@ -43,3 +43,10 @@ macro_rules! issue_10421 { b = a; }; } + +#[macro_export] +macro_rules! macro_with_panic { + () => { + panic!() + }; +} diff --git a/tests/ui/missing_panics_doc.rs b/tests/ui/missing_panics_doc.rs index d544a0b1afb..0e1533fc1ab 100644 --- a/tests/ui/missing_panics_doc.rs +++ b/tests/ui/missing_panics_doc.rs @@ -1,5 +1,12 @@ +//@aux-build:macro_rules.rs #![warn(clippy::missing_panics_doc)] #![allow(clippy::option_map_unit_fn, clippy::unnecessary_literal_unwrap)] + +#[macro_use] +extern crate macro_rules; + +use macro_rules::macro_with_panic; + fn main() {} /// This needs to be documented @@ -13,11 +20,6 @@ pub fn panic() { panic!("This function panics") } -/// This needs to be documented -pub fn todo() { - todo!() -} - /// This needs to be documented pub fn inner_body(opt: Option) { opt.map(|x| { @@ -76,15 +78,6 @@ pub fn inner_body_documented(opt: Option) { }); } -/// This is documented -/// -/// # Panics -/// -/// We still need to do this part -pub fn todo_documented() { - todo!() -} - /// This is documented /// /// # Panics @@ -114,6 +107,11 @@ pub fn assert_ne_documented() { assert_ne!(x, 0); } +/// `todo!()` is fine +pub fn todo() { + todo!() +} + /// This is okay because it is private fn unwrap_private() { let result = Err("Hi"); @@ -125,11 +123,6 @@ fn panic_private() { panic!("This function panics") } -/// This is okay because it is private -fn todo_private() { - todo!() -} - /// This is okay because it is private fn inner_body_private(opt: Option) { opt.map(|x| { @@ -183,3 +176,18 @@ pub mod issue10240 { *v.last().expect("passed an empty thing") } } + +fn from_external_macro_should_not_lint() { + macro_with_panic!() +} + +macro_rules! some_macro_that_panics { + () => { + panic!() + }; +} + +fn from_declared_macro_should_lint_at_macrosite() { + // Not here. + some_macro_that_panics!() +} diff --git a/tests/ui/missing_panics_doc.stderr b/tests/ui/missing_panics_doc.stderr index 39d97f08373..3dbe2dfbd88 100644 --- a/tests/ui/missing_panics_doc.stderr +++ b/tests/ui/missing_panics_doc.stderr @@ -1,159 +1,147 @@ error: docs for function which may panic missing `# Panics` section - --> $DIR/missing_panics_doc.rs:6:1 + --> $DIR/missing_panics_doc.rs:13:1 | LL | pub fn unwrap() { | ^^^^^^^^^^^^^^^ | note: first possible panic found here - --> $DIR/missing_panics_doc.rs:8:5 + --> $DIR/missing_panics_doc.rs:15:5 | LL | result.unwrap() | ^^^^^^^^^^^^^^^ = note: `-D clippy::missing-panics-doc` implied by `-D warnings` error: docs for function which may panic missing `# Panics` section - --> $DIR/missing_panics_doc.rs:12:1 + --> $DIR/missing_panics_doc.rs:19:1 | LL | pub fn panic() { | ^^^^^^^^^^^^^^ | note: first possible panic found here - --> $DIR/missing_panics_doc.rs:13:5 + --> $DIR/missing_panics_doc.rs:20:5 | LL | panic!("This function panics") | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: docs for function which may panic missing `# Panics` section - --> $DIR/missing_panics_doc.rs:17:1 - | -LL | pub fn todo() { - | ^^^^^^^^^^^^^ - | -note: first possible panic found here - --> $DIR/missing_panics_doc.rs:18:5 - | -LL | todo!() - | ^^^^^^^ - -error: docs for function which may panic missing `# Panics` section - --> $DIR/missing_panics_doc.rs:22:1 + --> $DIR/missing_panics_doc.rs:24:1 | LL | pub fn inner_body(opt: Option) { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | note: first possible panic found here - --> $DIR/missing_panics_doc.rs:25:13 + --> $DIR/missing_panics_doc.rs:27:13 | LL | panic!() | ^^^^^^^^ error: docs for function which may panic missing `# Panics` section - --> $DIR/missing_panics_doc.rs:31:1 + --> $DIR/missing_panics_doc.rs:33:1 | LL | pub fn unreachable_and_panic() { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | note: first possible panic found here - --> $DIR/missing_panics_doc.rs:32:39 + --> $DIR/missing_panics_doc.rs:34:39 | LL | if true { unreachable!() } else { panic!() } | ^^^^^^^^ error: docs for function which may panic missing `# Panics` section - --> $DIR/missing_panics_doc.rs:36:1 + --> $DIR/missing_panics_doc.rs:38:1 | LL | pub fn assert_eq() { | ^^^^^^^^^^^^^^^^^^ | note: first possible panic found here - --> $DIR/missing_panics_doc.rs:38:5 + --> $DIR/missing_panics_doc.rs:40:5 | LL | assert_eq!(x, 0); | ^^^^^^^^^^^^^^^^ error: docs for function which may panic missing `# Panics` section - --> $DIR/missing_panics_doc.rs:42:1 + --> $DIR/missing_panics_doc.rs:44:1 | LL | pub fn assert_ne() { | ^^^^^^^^^^^^^^^^^^ | note: first possible panic found here - --> $DIR/missing_panics_doc.rs:44:5 + --> $DIR/missing_panics_doc.rs:46:5 | LL | assert_ne!(x, 0); | ^^^^^^^^^^^^^^^^ error: docs for function which may panic missing `# Panics` section - --> $DIR/missing_panics_doc.rs:158:5 + --> $DIR/missing_panics_doc.rs:151:5 | LL | pub fn option_unwrap(v: &[T]) -> &T { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | note: first possible panic found here - --> $DIR/missing_panics_doc.rs:160:9 + --> $DIR/missing_panics_doc.rs:153:9 | LL | o.unwrap() | ^^^^^^^^^^ error: docs for function which may panic missing `# Panics` section - --> $DIR/missing_panics_doc.rs:163:5 + --> $DIR/missing_panics_doc.rs:156:5 | LL | pub fn option_expect(v: &[T]) -> &T { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | note: first possible panic found here - --> $DIR/missing_panics_doc.rs:165:9 + --> $DIR/missing_panics_doc.rs:158:9 | LL | o.expect("passed an empty thing") | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: docs for function which may panic missing `# Panics` section - --> $DIR/missing_panics_doc.rs:168:5 + --> $DIR/missing_panics_doc.rs:161:5 | LL | pub fn result_unwrap(v: &[T]) -> &T { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | note: first possible panic found here - --> $DIR/missing_panics_doc.rs:170:9 + --> $DIR/missing_panics_doc.rs:163:9 | LL | res.unwrap() | ^^^^^^^^^^^^ error: docs for function which may panic missing `# Panics` section - --> $DIR/missing_panics_doc.rs:173:5 + --> $DIR/missing_panics_doc.rs:166:5 | LL | pub fn result_expect(v: &[T]) -> &T { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | note: first possible panic found here - --> $DIR/missing_panics_doc.rs:175:9 + --> $DIR/missing_panics_doc.rs:168:9 | LL | res.expect("passed an empty thing") | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: docs for function which may panic missing `# Panics` section - --> $DIR/missing_panics_doc.rs:178:5 + --> $DIR/missing_panics_doc.rs:171:5 | LL | pub fn last_unwrap(v: &[u32]) -> u32 { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | note: first possible panic found here - --> $DIR/missing_panics_doc.rs:179:10 + --> $DIR/missing_panics_doc.rs:172:10 | LL | *v.last().unwrap() | ^^^^^^^^^^^^^^^^^ error: docs for function which may panic missing `# Panics` section - --> $DIR/missing_panics_doc.rs:182:5 + --> $DIR/missing_panics_doc.rs:175:5 | LL | pub fn last_expect(v: &[u32]) -> u32 { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | note: first possible panic found here - --> $DIR/missing_panics_doc.rs:183:10 + --> $DIR/missing_panics_doc.rs:176:10 | LL | *v.last().expect("passed an empty thing") | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: aborting due to 13 previous errors +error: aborting due to 12 previous errors From 6331c943ff85c8d5d86f6db940fd4e9dee3da15f Mon Sep 17 00:00:00 2001 From: y21 <30553356+y21@users.noreply.github.com> Date: Sat, 17 Jun 2023 20:48:56 +0200 Subject: [PATCH 219/310] include a ref if argument is not just a numeric literal --- clippy_lints/src/methods/get_unwrap.rs | 23 +++++++++----- tests/ui/get_unwrap.fixed | 13 ++++++++ tests/ui/get_unwrap.rs | 13 ++++++++ tests/ui/get_unwrap.stderr | 44 +++++++++++++++++++++++++- 4 files changed, 84 insertions(+), 9 deletions(-) diff --git a/clippy_lints/src/methods/get_unwrap.rs b/clippy_lints/src/methods/get_unwrap.rs index ffc3a4d780e..209d42ebabd 100644 --- a/clippy_lints/src/methods/get_unwrap.rs +++ b/clippy_lints/src/methods/get_unwrap.rs @@ -25,13 +25,13 @@ pub(super) fn check<'tcx>( let get_args_str = snippet_with_applicability(cx, get_arg.span, "..", &mut applicability); let mut needs_ref; let caller_type = if derefs_to_slice(cx, recv, expr_ty).is_some() { - needs_ref = get_args_str.parse::().is_ok(); + needs_ref = true; "slice" } else if is_type_diagnostic_item(cx, expr_ty, sym::Vec) { - needs_ref = get_args_str.parse::().is_ok(); + needs_ref = true; "Vec" } else if is_type_diagnostic_item(cx, expr_ty, sym::VecDeque) { - needs_ref = get_args_str.parse::().is_ok(); + needs_ref = true; "VecDeque" } else if !is_mut && is_type_diagnostic_item(cx, expr_ty, sym::HashMap) { needs_ref = true; @@ -45,16 +45,23 @@ pub(super) fn check<'tcx>( let mut span = expr.span; - // Handle the case where the result is immediately dereferenced - // by not requiring ref and pulling the dereference into the - // suggestion. + // Handle the case where the result is immediately dereferenced, + // either directly be the user, or as a result of a method call or the like + // by not requiring an explicit reference if_chain! { if needs_ref; if let Some(parent) = get_parent_expr(cx, expr); - if let hir::ExprKind::Unary(hir::UnOp::Deref, _) = parent.kind; + if let hir::ExprKind::Unary(hir::UnOp::Deref, _) + | hir::ExprKind::MethodCall(..) + | hir::ExprKind::Field(..) + | hir::ExprKind::Index(..) = parent.kind; then { + if let hir::ExprKind::Unary(hir::UnOp::Deref, _) = parent.kind { + // if the user explicitly dereferences the result, we can adjust + // the span to also include the deref part + span = parent.span; + } needs_ref = false; - span = parent.span; } } diff --git a/tests/ui/get_unwrap.fixed b/tests/ui/get_unwrap.fixed index 9061c9aa404..3e4c2b499e4 100644 --- a/tests/ui/get_unwrap.fixed +++ b/tests/ui/get_unwrap.fixed @@ -69,4 +69,17 @@ fn main() { let _ = some_vec[0..1].to_vec(); let _ = some_vec[0..1].to_vec(); } + issue9909(); +} +fn issue9909() { + let f = &[1, 2, 3]; + + let _x: &i32 = &f[1 + 2]; + // ^ include a borrow in the suggestion, even if the argument is not just a numeric literal + + let _x = f[1 + 2].to_string(); + // ^ don't include a borrow here + + let _x = f[1 + 2].abs(); + // ^ don't include a borrow here } diff --git a/tests/ui/get_unwrap.rs b/tests/ui/get_unwrap.rs index b5e4e472037..a967971a7dc 100644 --- a/tests/ui/get_unwrap.rs +++ b/tests/ui/get_unwrap.rs @@ -69,4 +69,17 @@ fn main() { let _ = some_vec.get(0..1).unwrap().to_vec(); let _ = some_vec.get_mut(0..1).unwrap().to_vec(); } + issue9909(); +} +fn issue9909() { + let f = &[1, 2, 3]; + + let _x: &i32 = f.get(1 + 2).unwrap(); + // ^ include a borrow in the suggestion, even if the argument is not just a numeric literal + + let _x = f.get(1 + 2).unwrap().to_string(); + // ^ don't include a borrow here + + let _x = f.get(1 + 2).unwrap().abs(); + // ^ don't include a borrow here } diff --git a/tests/ui/get_unwrap.stderr b/tests/ui/get_unwrap.stderr index a6a34620e92..6221c236830 100644 --- a/tests/ui/get_unwrap.stderr +++ b/tests/ui/get_unwrap.stderr @@ -187,5 +187,47 @@ LL | let _ = some_vec.get_mut(0..1).unwrap().to_vec(); | = help: if you don't want to handle the `None` case gracefully, consider using `expect()` to provide a better panic message -error: aborting due to 26 previous errors +error: called `.get().unwrap()` on a slice. Using `[]` is more clear and more concise + --> $DIR/get_unwrap.rs:77:20 + | +LL | let _x: &i32 = f.get(1 + 2).unwrap(); + | ^^^^^^^^^^^^^^^^^^^^^ help: try this: `&f[1 + 2]` + +error: used `unwrap()` on an `Option` value + --> $DIR/get_unwrap.rs:77:20 + | +LL | let _x: &i32 = f.get(1 + 2).unwrap(); + | ^^^^^^^^^^^^^^^^^^^^^ + | + = help: if you don't want to handle the `None` case gracefully, consider using `expect()` to provide a better panic message + +error: called `.get().unwrap()` on a slice. Using `[]` is more clear and more concise + --> $DIR/get_unwrap.rs:80:14 + | +LL | let _x = f.get(1 + 2).unwrap().to_string(); + | ^^^^^^^^^^^^^^^^^^^^^ help: try this: `f[1 + 2]` + +error: used `unwrap()` on an `Option` value + --> $DIR/get_unwrap.rs:80:14 + | +LL | let _x = f.get(1 + 2).unwrap().to_string(); + | ^^^^^^^^^^^^^^^^^^^^^ + | + = help: if you don't want to handle the `None` case gracefully, consider using `expect()` to provide a better panic message + +error: called `.get().unwrap()` on a slice. Using `[]` is more clear and more concise + --> $DIR/get_unwrap.rs:83:14 + | +LL | let _x = f.get(1 + 2).unwrap().abs(); + | ^^^^^^^^^^^^^^^^^^^^^ help: try this: `f[1 + 2]` + +error: used `unwrap()` on an `Option` value + --> $DIR/get_unwrap.rs:83:14 + | +LL | let _x = f.get(1 + 2).unwrap().abs(); + | ^^^^^^^^^^^^^^^^^^^^^ + | + = help: if you don't want to handle the `None` case gracefully, consider using `expect()` to provide a better panic message + +error: aborting due to 32 previous errors From 0e1caa765e89593fc81015e2e9bfe347339ba0b7 Mon Sep 17 00:00:00 2001 From: Caio Date: Sat, 17 Jun 2023 17:03:31 -0300 Subject: [PATCH 220/310] Fix #10792 --- clippy_lints/src/enum_clike.rs | 2 +- clippy_lints/src/floating_point_arithmetic.rs | 2 +- clippy_lints/src/matches/overlapping_arms.rs | 4 +- clippy_lints/src/minmax.rs | 8 +- clippy_lints/src/operators/float_cmp.rs | 2 +- clippy_lints/src/ranges.rs | 6 +- clippy_utils/src/consts.rs | 143 +++++++++++------- clippy_utils/src/lib.rs | 4 +- tests/ui/arithmetic_side_effects.rs | 15 ++ 9 files changed, 114 insertions(+), 72 deletions(-) diff --git a/clippy_lints/src/enum_clike.rs b/clippy_lints/src/enum_clike.rs index e275efaba25..d85650712db 100644 --- a/clippy_lints/src/enum_clike.rs +++ b/clippy_lints/src/enum_clike.rs @@ -51,7 +51,7 @@ impl<'tcx> LateLintPass<'tcx> for UnportableVariant { .const_eval_poly(def_id.to_def_id()) .ok() .map(|val| rustc_middle::mir::ConstantKind::from_value(val, ty)); - if let Some(Constant::Int(val)) = constant.and_then(|c| miri_to_const(cx.tcx, c)) { + if let Some(Constant::Int(val)) = constant.and_then(|c| miri_to_const(cx, c)) { if let ty::Adt(adt, _) = ty.kind() { if adt.is_enum() { ty = adt.repr().discr_type().to_ty(cx.tcx); diff --git a/clippy_lints/src/floating_point_arithmetic.rs b/clippy_lints/src/floating_point_arithmetic.rs index 3c55a563af4..5e0fcd74339 100644 --- a/clippy_lints/src/floating_point_arithmetic.rs +++ b/clippy_lints/src/floating_point_arithmetic.rs @@ -215,7 +215,7 @@ fn check_ln1p(cx: &LateContext<'_>, expr: &Expr<'_>, receiver: &Expr<'_>) { // ranges [-16777215, 16777216) for type f32 as whole number floats outside // this range are lossy and ambiguous. #[expect(clippy::cast_possible_truncation)] -fn get_integer_from_float_constant(value: &Constant) -> Option { +fn get_integer_from_float_constant(value: &Constant<'_>) -> Option { match value { F32(num) if num.fract() == 0.0 => { if (-16_777_215.0..16_777_216.0).contains(num) { diff --git a/clippy_lints/src/matches/overlapping_arms.rs b/clippy_lints/src/matches/overlapping_arms.rs index abf2525a61c..8be3c178a29 100644 --- a/clippy_lints/src/matches/overlapping_arms.rs +++ b/clippy_lints/src/matches/overlapping_arms.rs @@ -41,7 +41,7 @@ fn all_ranges<'tcx>(cx: &LateContext<'tcx>, arms: &'tcx [Arm<'_>], ty: Ty<'tcx>) cx.tcx.valtree_to_const_val((ty, min_val_const.to_valtree())), ty, ); - miri_to_const(cx.tcx, min_constant)? + miri_to_const(cx, min_constant)? }, }; let rhs_const = match rhs { @@ -52,7 +52,7 @@ fn all_ranges<'tcx>(cx: &LateContext<'tcx>, arms: &'tcx [Arm<'_>], ty: Ty<'tcx>) cx.tcx.valtree_to_const_val((ty, max_val_const.to_valtree())), ty, ); - miri_to_const(cx.tcx, max_constant)? + miri_to_const(cx, max_constant)? }, }; let lhs_val = lhs_const.int_value(cx, ty)?; diff --git a/clippy_lints/src/minmax.rs b/clippy_lints/src/minmax.rs index 4f967755bfa..e0904f17b8d 100644 --- a/clippy_lints/src/minmax.rs +++ b/clippy_lints/src/minmax.rs @@ -66,7 +66,7 @@ enum MinMax { Max, } -fn min_max<'a>(cx: &LateContext<'_>, expr: &'a Expr<'a>) -> Option<(MinMax, Constant, &'a Expr<'a>)> { +fn min_max<'a, 'tcx>(cx: &LateContext<'tcx>, expr: &'a Expr<'a>) -> Option<(MinMax, Constant<'tcx>, &'a Expr<'a>)> { match expr.kind { ExprKind::Call(path, args) => { if let ExprKind::Path(ref qpath) = path.kind { @@ -99,12 +99,12 @@ fn min_max<'a>(cx: &LateContext<'_>, expr: &'a Expr<'a>) -> Option<(MinMax, Cons } } -fn fetch_const<'a>( - cx: &LateContext<'_>, +fn fetch_const<'a, 'tcx>( + cx: &LateContext<'tcx>, receiver: Option<&'a Expr<'a>>, args: &'a [Expr<'a>], m: MinMax, -) -> Option<(MinMax, Constant, &'a Expr<'a>)> { +) -> Option<(MinMax, Constant<'tcx>, &'a Expr<'a>)> { let mut args = receiver.into_iter().chain(args); let first_arg = args.next()?; let second_arg = args.next()?; diff --git a/clippy_lints/src/operators/float_cmp.rs b/clippy_lints/src/operators/float_cmp.rs index 15dff126be7..f3e0c58a787 100644 --- a/clippy_lints/src/operators/float_cmp.rs +++ b/clippy_lints/src/operators/float_cmp.rs @@ -85,7 +85,7 @@ fn get_lint_and_message(is_local: bool, is_comparing_arrays: bool) -> (&'static } } -fn is_allowed(val: &Constant) -> bool { +fn is_allowed(val: &Constant<'_>) -> bool { match val { &Constant::F32(f) => f == 0.0 || f.is_infinite(), &Constant::F64(f) => f == 0.0 || f.is_infinite(), diff --git a/clippy_lints/src/ranges.rs b/clippy_lints/src/ranges.rs index dd7ded491e7..d2018aba9e3 100644 --- a/clippy_lints/src/ranges.rs +++ b/clippy_lints/src/ranges.rs @@ -296,8 +296,8 @@ fn check_possible_range_contains( } } -struct RangeBounds<'a> { - val: Constant, +struct RangeBounds<'a, 'tcx> { + val: Constant<'tcx>, expr: &'a Expr<'a>, id: HirId, name_span: Span, @@ -309,7 +309,7 @@ struct RangeBounds<'a> { // Takes a binary expression such as x <= 2 as input // Breaks apart into various pieces, such as the value of the number, // hir id of the variable, and direction/inclusiveness of the operator -fn check_range_bounds<'a>(cx: &'a LateContext<'_>, ex: &'a Expr<'_>) -> Option> { +fn check_range_bounds<'a, 'tcx>(cx: &'a LateContext<'tcx>, ex: &'a Expr<'_>) -> Option> { if let ExprKind::Binary(ref op, l, r) = ex.kind { let (inclusive, ordering) = match op.node { BinOpKind::Gt => (false, Ordering::Greater), diff --git a/clippy_utils/src/consts.rs b/clippy_utils/src/consts.rs index cc3183759ae..ff01c2ef7be 100644 --- a/clippy_utils/src/consts.rs +++ b/clippy_utils/src/consts.rs @@ -14,7 +14,7 @@ use rustc_middle::mir::interpret::Scalar; use rustc_middle::ty::{self, EarlyBinder, FloatTy, ScalarInt, Ty, TyCtxt}; use rustc_middle::ty::{List, SubstsRef}; use rustc_middle::{bug, span_bug}; -use rustc_span::symbol::Symbol; +use rustc_span::symbol::{Ident, Symbol}; use rustc_span::SyntaxContext; use std::cmp::Ordering::{self, Equal}; use std::hash::{Hash, Hasher}; @@ -22,7 +22,8 @@ use std::iter; /// A `LitKind`-like enum to fold constant `Expr`s into. #[derive(Debug, Clone)] -pub enum Constant { +pub enum Constant<'tcx> { + Adt(rustc_middle::mir::ConstantKind<'tcx>), /// A `String` (e.g., "abc"). Str(String), /// A binary string (e.g., `b"abc"`). @@ -38,20 +39,20 @@ pub enum Constant { /// `true` or `false`. Bool(bool), /// An array of constants. - Vec(Vec), + Vec(Vec>), /// Also an array, but with only one constant, repeated N times. - Repeat(Box, u64), + Repeat(Box>, u64), /// A tuple of constants. - Tuple(Vec), + Tuple(Vec>), /// A raw pointer. RawPtr(u128), /// A reference - Ref(Box), + Ref(Box>), /// A literal with syntax error. Err, } -impl PartialEq for Constant { +impl<'tcx> PartialEq for Constant<'tcx> { fn eq(&self, other: &Self) -> bool { match (self, other) { (Self::Str(ls), Self::Str(rs)) => ls == rs, @@ -80,13 +81,16 @@ impl PartialEq for Constant { } } -impl Hash for Constant { +impl<'tcx> Hash for Constant<'tcx> { fn hash(&self, state: &mut H) where H: Hasher, { std::mem::discriminant(self).hash(state); match *self { + Self::Adt(ref elem) => { + elem.hash(state); + }, Self::Str(ref s) => { s.hash(state); }, @@ -126,7 +130,7 @@ impl Hash for Constant { } } -impl Constant { +impl<'tcx> Constant<'tcx> { pub fn partial_cmp(tcx: TyCtxt<'_>, cmp_type: Ty<'_>, left: &Self, right: &Self) -> Option { match (left, right) { (Self::Str(ls), Self::Str(rs)) => Some(ls.cmp(rs)), @@ -209,7 +213,7 @@ impl Constant { } /// Parses a `LitKind` to a `Constant`. -pub fn lit_to_mir_constant(lit: &LitKind, ty: Option>) -> Constant { +pub fn lit_to_mir_constant<'tcx>(lit: &LitKind, ty: Option>) -> Constant<'tcx> { match *lit { LitKind::Str(ref is, _) => Constant::Str(is.to_string()), LitKind::Byte(b) => Constant::Int(u128::from(b)), @@ -248,7 +252,7 @@ pub fn constant<'tcx>( lcx: &LateContext<'tcx>, typeck_results: &ty::TypeckResults<'tcx>, e: &Expr<'_>, -) -> Option { +) -> Option> { ConstEvalLateContext::new(lcx, typeck_results).expr(e) } @@ -257,7 +261,7 @@ pub fn constant_with_source<'tcx>( lcx: &LateContext<'tcx>, typeck_results: &ty::TypeckResults<'tcx>, e: &Expr<'_>, -) -> Option<(Constant, ConstantSource)> { +) -> Option<(Constant<'tcx>, ConstantSource)> { let mut ctxt = ConstEvalLateContext::new(lcx, typeck_results); let res = ctxt.expr(e); res.map(|x| (x, ctxt.source)) @@ -268,7 +272,7 @@ pub fn constant_simple<'tcx>( lcx: &LateContext<'tcx>, typeck_results: &ty::TypeckResults<'tcx>, e: &Expr<'_>, -) -> Option { +) -> Option> { constant_with_source(lcx, typeck_results, e).and_then(|(c, s)| s.is_local().then_some(c)) } @@ -338,7 +342,7 @@ impl<'a, 'tcx> ConstEvalLateContext<'a, 'tcx> { } /// Simple constant folding: Insert an expression, get a constant or none. - pub fn expr(&mut self, e: &Expr<'_>) -> Option { + pub fn expr(&mut self, e: &Expr<'_>) -> Option> { match e.kind { ExprKind::Path(ref qpath) => self.fetch_path(qpath, e.hir_id, self.typeck_results.expr_ty(e)), ExprKind::Block(block, _) => self.block(block), @@ -392,13 +396,25 @@ impl<'a, 'tcx> ConstEvalLateContext<'a, 'tcx> { }, ExprKind::Index(arr, index) => self.index(arr, index), ExprKind::AddrOf(_, _, inner) => self.expr(inner).map(|r| Constant::Ref(Box::new(r))), - // TODO: add other expressions. + ExprKind::Field(ref local_expr, ref field) => { + let result = self.expr(local_expr); + if let Some(Constant::Adt(constant)) = &self.expr(local_expr) + && let ty::Adt(adt_def, _) = constant.ty().kind() + && adt_def.is_struct() + && let Some(desired_field) = field_of_struct(*adt_def, self.lcx, *constant, field) + { + miri_to_const(self.lcx, desired_field) + } + else { + result + } + }, _ => None, } } #[expect(clippy::cast_possible_wrap)] - fn constant_not(&self, o: &Constant, ty: Ty<'_>) -> Option { + fn constant_not(&self, o: &Constant<'tcx>, ty: Ty<'_>) -> Option> { use self::Constant::{Bool, Int}; match *o { Bool(b) => Some(Bool(!b)), @@ -414,7 +430,7 @@ impl<'a, 'tcx> ConstEvalLateContext<'a, 'tcx> { } } - fn constant_negate(&self, o: &Constant, ty: Ty<'_>) -> Option { + fn constant_negate(&self, o: &Constant<'tcx>, ty: Ty<'_>) -> Option> { use self::Constant::{Int, F32, F64}; match *o { Int(value) => { @@ -433,28 +449,25 @@ impl<'a, 'tcx> ConstEvalLateContext<'a, 'tcx> { /// Create `Some(Vec![..])` of all constants, unless there is any /// non-constant part. - fn multi(&mut self, vec: &[Expr<'_>]) -> Option> { + fn multi(&mut self, vec: &[Expr<'_>]) -> Option>> { vec.iter().map(|elem| self.expr(elem)).collect::>() } /// Lookup a possibly constant expression from an `ExprKind::Path`. - fn fetch_path(&mut self, qpath: &QPath<'_>, id: HirId, ty: Ty<'tcx>) -> Option { + fn fetch_path(&mut self, qpath: &QPath<'_>, id: HirId, ty: Ty<'tcx>) -> Option> { let res = self.typeck_results.qpath_res(qpath, id); match res { Res::Def(DefKind::Const | DefKind::AssocConst, def_id) => { // Check if this constant is based on `cfg!(..)`, // which is NOT constant for our purposes. - if let Some(node) = self.lcx.tcx.hir().get_if_local(def_id) && - let Node::Item(&Item { - kind: ItemKind::Const(_, body_id), - .. - }) = node && - let Node::Expr(&Expr { - kind: ExprKind::Lit(_), - span, - .. - }) = self.lcx.tcx.hir().get(body_id.hir_id) && - is_direct_expn_of(span, "cfg").is_some() { + if let Some(node) = self.lcx.tcx.hir().get_if_local(def_id) + && let Node::Item(Item { kind: ItemKind::Const(_, body_id), .. }) = node + && let Node::Expr(Expr { kind: ExprKind::Lit(_), span, .. }) = self.lcx + .tcx + .hir() + .get(body_id.hir_id) + && is_direct_expn_of(*span, "cfg").is_some() + { return None; } @@ -464,23 +477,21 @@ impl<'a, 'tcx> ConstEvalLateContext<'a, 'tcx> { } else { EarlyBinder::bind(substs).subst(self.lcx.tcx, self.substs) }; - let result = self .lcx .tcx .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)?; + let result = miri_to_const(self.lcx, result)?; self.source = ConstantSource::Constant; Some(result) }, - // FIXME: cover all usable cases. _ => None, } } - fn index(&mut self, lhs: &'_ Expr<'_>, index: &'_ Expr<'_>) -> Option { + fn index(&mut self, lhs: &'_ Expr<'_>, index: &'_ Expr<'_>) -> Option> { let lhs = self.expr(lhs); let index = self.expr(index); @@ -506,7 +517,7 @@ impl<'a, 'tcx> ConstEvalLateContext<'a, 'tcx> { } /// A block can only yield a constant if it only has one constant expression. - fn block(&mut self, block: &Block<'_>) -> Option { + fn block(&mut self, block: &Block<'_>) -> Option> { if block.stmts.is_empty() && let Some(expr) = block.expr { @@ -539,7 +550,7 @@ impl<'a, 'tcx> ConstEvalLateContext<'a, 'tcx> { } } - fn ifthenelse(&mut self, cond: &Expr<'_>, then: &Expr<'_>, otherwise: Option<&Expr<'_>>) -> Option { + fn ifthenelse(&mut self, cond: &Expr<'_>, then: &Expr<'_>, otherwise: Option<&Expr<'_>>) -> Option> { if let Some(Constant::Bool(b)) = self.expr(cond) { if b { self.expr(then) @@ -551,7 +562,7 @@ impl<'a, 'tcx> ConstEvalLateContext<'a, 'tcx> { } } - fn binop(&mut self, op: BinOp, left: &Expr<'_>, right: &Expr<'_>) -> Option { + fn binop(&mut self, op: BinOp, left: &Expr<'_>, right: &Expr<'_>) -> Option> { let l = self.expr(left)?; let r = self.expr(right); match (l, r) { @@ -644,23 +655,21 @@ impl<'a, 'tcx> ConstEvalLateContext<'a, 'tcx> { } } -pub fn miri_to_const<'tcx>(tcx: TyCtxt<'tcx>, result: mir::ConstantKind<'tcx>) -> Option { +pub fn miri_to_const<'tcx>(lcx: &LateContext<'tcx>, result: mir::ConstantKind<'tcx>) -> Option> { use rustc_middle::mir::interpret::ConstValue; match result { - mir::ConstantKind::Val(ConstValue::Scalar(Scalar::Int(int)), _) => { - match result.ty().kind() { - ty::Bool => Some(Constant::Bool(int == ScalarInt::TRUE)), - ty::Uint(_) | ty::Int(_) => Some(Constant::Int(int.assert_bits(int.size()))), - ty::Float(FloatTy::F32) => Some(Constant::F32(f32::from_bits( - int.try_into().expect("invalid f32 bit representation"), - ))), - ty::Float(FloatTy::F64) => Some(Constant::F64(f64::from_bits( - int.try_into().expect("invalid f64 bit representation"), - ))), - ty::RawPtr(_) => Some(Constant::RawPtr(int.assert_bits(int.size()))), - // FIXME: implement other conversions. - _ => None, - } + mir::ConstantKind::Val(ConstValue::Scalar(Scalar::Int(int)), _) => match result.ty().kind() { + ty::Adt(adt_def, _) if adt_def.is_struct() => Some(Constant::Adt(result)), + ty::Bool => Some(Constant::Bool(int == ScalarInt::TRUE)), + ty::Uint(_) | ty::Int(_) => Some(Constant::Int(int.assert_bits(int.size()))), + ty::Float(FloatTy::F32) => Some(Constant::F32(f32::from_bits( + int.try_into().expect("invalid f32 bit representation"), + ))), + ty::Float(FloatTy::F64) => Some(Constant::F64(f64::from_bits( + int.try_into().expect("invalid f64 bit representation"), + ))), + ty::RawPtr(_) => Some(Constant::RawPtr(int.assert_bits(int.size()))), + _ => None, }, mir::ConstantKind::Val(ConstValue::Slice { data, start, end }, _) => match result.ty().kind() { ty::Ref(_, tam, _) => match tam.kind() { @@ -676,35 +685,53 @@ pub fn miri_to_const<'tcx>(tcx: TyCtxt<'tcx>, result: mir::ConstantKind<'tcx>) - _ => None, }, mir::ConstantKind::Val(ConstValue::ByRef { alloc, offset: _ }, _) => match result.ty().kind() { + ty::Adt(adt_def, _) if adt_def.is_struct() => Some(Constant::Adt(result)), ty::Array(sub_type, len) => match sub_type.kind() { - ty::Float(FloatTy::F32) => match len.kind().try_to_target_usize(tcx) { + ty::Float(FloatTy::F32) => match len.kind().try_to_target_usize(lcx.tcx) { Some(len) => alloc .inner() .inspect_with_uninit_and_ptr_outside_interpreter(0..(4 * usize::try_from(len).unwrap())) .to_owned() .array_chunks::<4>() .map(|&chunk| Some(Constant::F32(f32::from_le_bytes(chunk)))) - .collect::>>() + .collect::>>>() .map(Constant::Vec), _ => None, }, - ty::Float(FloatTy::F64) => match len.kind().try_to_target_usize(tcx) { + ty::Float(FloatTy::F64) => match len.kind().try_to_target_usize(lcx.tcx) { Some(len) => alloc .inner() .inspect_with_uninit_and_ptr_outside_interpreter(0..(8 * usize::try_from(len).unwrap())) .to_owned() .array_chunks::<8>() .map(|&chunk| Some(Constant::F64(f64::from_le_bytes(chunk)))) - .collect::>>() + .collect::>>>() .map(Constant::Vec), _ => None, }, - // FIXME: implement other array type conversions. _ => None, }, _ => None, }, - // FIXME: implement other conversions. _ => None, } } + +fn field_of_struct<'tcx>( + adt_def: ty::AdtDef<'tcx>, + lcx: &LateContext<'tcx>, + result: mir::ConstantKind<'tcx>, + field: &Ident, +) -> Option> { + let dc = lcx.tcx.destructure_mir_constant(lcx.param_env, result); + if let Some(dc_variant) = dc.variant + && let Some(variant) = adt_def.variants().get(dc_variant) + && let Some(field_idx) = variant.fields.iter().position(|el| el.name == field.name) + && let Some(dc_field) = dc.fields.get(field_idx) + { + Some(*dc_field) + } + else { + None + } +} diff --git a/clippy_utils/src/lib.rs b/clippy_utils/src/lib.rs index 311f6dbc696..5b5e9fba6af 100644 --- a/clippy_utils/src/lib.rs +++ b/clippy_utils/src/lib.rs @@ -1499,7 +1499,7 @@ pub fn is_range_full(cx: &LateContext<'_>, expr: &Expr<'_>, container_path: Opti && 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(min_const) = miri_to_const(cx, min_const_kind) && let Some(start_const) = constant(cx, cx.typeck_results(), start) { start_const == min_const @@ -1515,7 +1515,7 @@ pub fn is_range_full(cx: &LateContext<'_>, expr: &Expr<'_>, container_path: Opti && 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(max_const) = miri_to_const(cx, max_const_kind) && let Some(end_const) = constant(cx, cx.typeck_results(), end) { end_const == max_const diff --git a/tests/ui/arithmetic_side_effects.rs b/tests/ui/arithmetic_side_effects.rs index f95af1017bc..7dd14e3824d 100644 --- a/tests/ui/arithmetic_side_effects.rs +++ b/tests/ui/arithmetic_side_effects.rs @@ -466,4 +466,19 @@ pub fn issue_10767() { &3.5_f32 + &1.3_f32; } +pub fn issue_10792() { + struct One { + a: u32, + } + struct Two { + b: u32, + c: u64, + } + const ONE: One = One { a: 1 }; + const TWO: Two = Two { b: 2, c: 3 }; + let _ = 10 / ONE.a; + let _ = 10 / TWO.b; + let _ = 10 / TWO.c; +} + fn main() {} From dbe4057237ffa1594b41aa998d0958efe95780bc Mon Sep 17 00:00:00 2001 From: Caio Date: Sat, 17 Jun 2023 17:16:01 -0300 Subject: [PATCH 221/310] Dogfood --- clippy_utils/src/consts.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clippy_utils/src/consts.rs b/clippy_utils/src/consts.rs index ff01c2ef7be..72582ba7e78 100644 --- a/clippy_utils/src/consts.rs +++ b/clippy_utils/src/consts.rs @@ -396,7 +396,7 @@ impl<'a, 'tcx> ConstEvalLateContext<'a, 'tcx> { }, ExprKind::Index(arr, index) => self.index(arr, index), ExprKind::AddrOf(_, _, inner) => self.expr(inner).map(|r| Constant::Ref(Box::new(r))), - ExprKind::Field(ref local_expr, ref field) => { + ExprKind::Field(local_expr, ref field) => { let result = self.expr(local_expr); if let Some(Constant::Adt(constant)) = &self.expr(local_expr) && let ty::Adt(adt_def, _) = constant.ty().kind() From 26e78e72bc8d40a8168213620a266d803845e604 Mon Sep 17 00:00:00 2001 From: Alex Macleod Date: Sat, 17 Jun 2023 20:40:05 +0000 Subject: [PATCH 222/310] Fix `find_format_arg_expr` when incremental compilation is enabled --- clippy_utils/src/macros.rs | 14 ++++++++++++-- .../ui/to_string_in_format_args_incremental.fixed | 9 +++++++++ tests/ui/to_string_in_format_args_incremental.rs | 9 +++++++++ .../ui/to_string_in_format_args_incremental.stderr | 10 ++++++++++ 4 files changed, 40 insertions(+), 2 deletions(-) create mode 100644 tests/ui/to_string_in_format_args_incremental.fixed create mode 100644 tests/ui/to_string_in_format_args_incremental.rs create mode 100644 tests/ui/to_string_in_format_args_incremental.stderr diff --git a/clippy_utils/src/macros.rs b/clippy_utils/src/macros.rs index e4a4936ff42..00f3abaec8a 100644 --- a/clippy_utils/src/macros.rs +++ b/clippy_utils/src/macros.rs @@ -9,7 +9,7 @@ use rustc_hir::{self as hir, Expr, ExprKind, HirId, Node, QPath}; use rustc_lint::LateContext; use rustc_span::def_id::DefId; use rustc_span::hygiene::{self, MacroKind, SyntaxContext}; -use rustc_span::{sym, BytePos, ExpnData, ExpnId, ExpnKind, Span, Symbol}; +use rustc_span::{sym, BytePos, ExpnData, ExpnId, ExpnKind, Span, SpanData, Symbol}; use std::cell::RefCell; use std::ops::ControlFlow; use std::sync::atomic::{AtomicBool, Ordering}; @@ -415,8 +415,18 @@ 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> { + let SpanData { + lo, + hi, + ctxt, + parent: _, + } = target.expr.span.data(); + for_each_expr(start, |expr| { - if expr.span == target.expr.span { + // When incremental compilation is enabled spans gain a parent during AST to HIR lowering, + // since we're comparing an AST span to a HIR one we need to ignore the parent field + let data = expr.span.data(); + if data.lo == lo && data.hi == hi && data.ctxt == ctxt { ControlFlow::Break(expr) } else { ControlFlow::Continue(()) diff --git a/tests/ui/to_string_in_format_args_incremental.fixed b/tests/ui/to_string_in_format_args_incremental.fixed new file mode 100644 index 00000000000..9f75ad895cd --- /dev/null +++ b/tests/ui/to_string_in_format_args_incremental.fixed @@ -0,0 +1,9 @@ +//@run-rustfix +//@compile-flags: -C incremental=target/debug/test/incr + +// see https://github.com/rust-lang/rust-clippy/issues/10969 + +fn main() { + let s = "Hello, world!"; + println!("{}", s); +} diff --git a/tests/ui/to_string_in_format_args_incremental.rs b/tests/ui/to_string_in_format_args_incremental.rs new file mode 100644 index 00000000000..67115f7c5a7 --- /dev/null +++ b/tests/ui/to_string_in_format_args_incremental.rs @@ -0,0 +1,9 @@ +//@run-rustfix +//@compile-flags: -C incremental=target/debug/test/incr + +// see https://github.com/rust-lang/rust-clippy/issues/10969 + +fn main() { + let s = "Hello, world!"; + println!("{}", s.to_string()); +} diff --git a/tests/ui/to_string_in_format_args_incremental.stderr b/tests/ui/to_string_in_format_args_incremental.stderr new file mode 100644 index 00000000000..a992c542914 --- /dev/null +++ b/tests/ui/to_string_in_format_args_incremental.stderr @@ -0,0 +1,10 @@ +error: `to_string` applied to a type that implements `Display` in `println!` args + --> $DIR/to_string_in_format_args_incremental.rs:8:21 + | +LL | println!("{}", s.to_string()); + | ^^^^^^^^^^^^ help: remove this + | + = note: `-D clippy::to-string-in-format-args` implied by `-D warnings` + +error: aborting due to previous error + From bc41b2ca5c88035b5245dd860b619eb0bad7cc20 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Thu, 15 Jun 2023 16:59:01 +0000 Subject: [PATCH 223/310] Move WF goal to clause --- 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 c0d2c835d63..b132e69269d 100644 --- a/clippy_utils/src/qualify_min_const_fn.rs +++ b/clippy_utils/src/qualify_min_const_fn.rs @@ -33,7 +33,7 @@ pub fn is_min_const_fn<'tcx>(tcx: TyCtxt<'tcx>, body: &Body<'tcx>, msrv: &Msrv) | ty::Clause::Trait(..) | ty::Clause::ConstArgHasType(..), ) - | ty::PredicateKind::WellFormed(_) + | ty::PredicateKind::Clause(ty::Clause::WellFormed(_)) | ty::PredicateKind::ConstEvaluatable(..) | ty::PredicateKind::ConstEquate(..) | ty::PredicateKind::TypeWellFormedFromEnv(..) => continue, From f28ec85530f4002f8d9ebd492c11305fbbb7c691 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Thu, 15 Jun 2023 18:35:52 +0000 Subject: [PATCH 224/310] Move ConstEvaluatable to Clause --- 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 b132e69269d..860a489494c 100644 --- a/clippy_utils/src/qualify_min_const_fn.rs +++ b/clippy_utils/src/qualify_min_const_fn.rs @@ -34,7 +34,7 @@ pub fn is_min_const_fn<'tcx>(tcx: TyCtxt<'tcx>, body: &Body<'tcx>, msrv: &Msrv) | ty::Clause::ConstArgHasType(..), ) | ty::PredicateKind::Clause(ty::Clause::WellFormed(_)) - | ty::PredicateKind::ConstEvaluatable(..) + | ty::PredicateKind::Clause(ty::Clause::ConstEvaluatable(..)) | ty::PredicateKind::ConstEquate(..) | ty::PredicateKind::TypeWellFormedFromEnv(..) => continue, ty::PredicateKind::AliasRelate(..) => panic!("alias relate predicate on function: {predicate:#?}"), From 07dbcbda12cacb924c2d95719ad598ee9de8738d Mon Sep 17 00:00:00 2001 From: Centri3 <114838443+Centri3@users.noreply.github.com> Date: Wed, 14 Jun 2023 06:48:34 -0500 Subject: [PATCH 225/310] new lint `single_call_fn` --- CHANGELOG.md | 1 + clippy_lints/src/declared_lints.rs | 1 + clippy_lints/src/lib.rs | 7 ++ clippy_lints/src/single_call_fn.rs | 132 +++++++++++++++++++++++++++++ tests/ui/single_call_fn.rs | 49 +++++++++++ tests/ui/single_call_fn.stderr | 31 +++++++ 6 files changed, 221 insertions(+) create mode 100644 clippy_lints/src/single_call_fn.rs create mode 100644 tests/ui/single_call_fn.rs create mode 100644 tests/ui/single_call_fn.stderr diff --git a/CHANGELOG.md b/CHANGELOG.md index 3eaa0d199fd..6fb7ac740b0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5158,6 +5158,7 @@ Released 2018-09-13 [`significant_drop_in_scrutinee`]: https://rust-lang.github.io/rust-clippy/master/index.html#significant_drop_in_scrutinee [`significant_drop_tightening`]: https://rust-lang.github.io/rust-clippy/master/index.html#significant_drop_tightening [`similar_names`]: https://rust-lang.github.io/rust-clippy/master/index.html#similar_names +[`single_call_fn`]: https://rust-lang.github.io/rust-clippy/master/index.html#single_call_fn [`single_char_add_str`]: https://rust-lang.github.io/rust-clippy/master/index.html#single_char_add_str [`single_char_lifetime_names`]: https://rust-lang.github.io/rust-clippy/master/index.html#single_char_lifetime_names [`single_char_pattern`]: https://rust-lang.github.io/rust-clippy/master/index.html#single_char_pattern diff --git a/clippy_lints/src/declared_lints.rs b/clippy_lints/src/declared_lints.rs index 7690e8f7247..9c1e1f6702d 100644 --- a/clippy_lints/src/declared_lints.rs +++ b/clippy_lints/src/declared_lints.rs @@ -570,6 +570,7 @@ pub(crate) static LINTS: &[&crate::LintInfo] = &[ crate::shadow::SHADOW_SAME_INFO, crate::shadow::SHADOW_UNRELATED_INFO, crate::significant_drop_tightening::SIGNIFICANT_DROP_TIGHTENING_INFO, + crate::single_call_fn::SINGLE_CALL_FN_INFO, crate::single_char_lifetime_names::SINGLE_CHAR_LIFETIME_NAMES_INFO, crate::single_component_path_imports::SINGLE_COMPONENT_PATH_IMPORTS_INFO, crate::single_range_in_vec_init::SINGLE_RANGE_IN_VEC_INIT_INFO, diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index 6ea329a9542..939b1136b46 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -287,6 +287,7 @@ mod semicolon_if_nothing_returned; mod serde_api; mod shadow; mod significant_drop_tightening; +mod single_call_fn; mod single_char_lifetime_names; mod single_component_path_imports; mod single_range_in_vec_init; @@ -1055,6 +1056,12 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: store.register_late_pass(move |_| Box::new(large_stack_frames::LargeStackFrames::new(stack_size_threshold))); store.register_late_pass(|_| Box::new(single_range_in_vec_init::SingleRangeInVecInit)); store.register_late_pass(|_| Box::new(incorrect_impls::IncorrectImpls)); + store.register_late_pass(move |_| { + Box::new(single_call_fn::SingleCallFn { + avoid_breaking_exported_api, + def_id_to_usage: rustc_data_structures::fx::FxHashMap::default(), + }) + }); // add lints here, do not remove this comment, it's used in `new_lint` } diff --git a/clippy_lints/src/single_call_fn.rs b/clippy_lints/src/single_call_fn.rs new file mode 100644 index 00000000000..d0fbedee832 --- /dev/null +++ b/clippy_lints/src/single_call_fn.rs @@ -0,0 +1,132 @@ +use clippy_utils::diagnostics::span_lint_and_help; +use clippy_utils::is_from_proc_macro; +use rustc_data_structures::fx::FxHashMap; +use rustc_hir::def_id::LocalDefId; +use rustc_hir::intravisit::{walk_expr, Visitor}; +use rustc_hir::{intravisit::FnKind, Body, Expr, ExprKind, FnDecl}; +use rustc_lint::{LateContext, LateLintPass, LintContext}; +use rustc_middle::hir::nested_filter::OnlyBodies; +use rustc_middle::lint::in_external_macro; +use rustc_session::{declare_tool_lint, impl_lint_pass}; +use rustc_span::Span; + +declare_clippy_lint! { + /// ### What it does + /// Checks for functions that are only used once. + /// + /// ### Why is this bad? + /// It's usually not, splitting a function into multiple parts often improves readability and in + /// the case of generics, can prevent the compiler from duplicating the function dozens of + /// time; instead, only duplicating a thunk. But this can prevent segmentation across a + /// codebase, where many small functions are used only once. + /// + /// Note: If this lint is used, prepare to allow this a lot. + /// + /// ### Example + /// ```rust + /// pub fn a(t: &T) + /// where + /// T: AsRef, + /// { + /// a_inner(t.as_ref()) + /// } + /// + /// fn a_inner(t: &str) { + /// /* snip */ + /// } + /// + /// ``` + /// Use instead: + /// ```rust + /// pub fn a(t: &T) + /// where + /// T: AsRef, + /// { + /// let t = t.as_ref(); + /// /* snip */ + /// } + /// + /// ``` + #[clippy::version = "1.72.0"] + pub SINGLE_CALL_FN, + restriction, + "checks for functions that are only used once" +} +impl_lint_pass!(SingleCallFn => [SINGLE_CALL_FN]); + +#[derive(Clone)] +pub struct SingleCallFn { + pub avoid_breaking_exported_api: bool, + pub def_id_to_usage: FxHashMap)>, +} + +impl<'tcx> LateLintPass<'tcx> for SingleCallFn { + fn check_fn( + &mut self, + cx: &LateContext<'tcx>, + kind: FnKind<'tcx>, + _: &'tcx FnDecl<'_>, + body: &'tcx Body<'_>, + span: Span, + def_id: LocalDefId, + ) { + if self.avoid_breaking_exported_api && cx.effective_visibilities.is_exported(def_id) + || in_external_macro(cx.sess(), span) + || is_from_proc_macro(cx, &(&kind, body, cx.tcx.local_def_id_to_hir_id(def_id), span)) + { + return; + } + + self.def_id_to_usage.insert(def_id, (span, vec![])); + } + + fn check_crate_post(&mut self, cx: &LateContext<'tcx>) { + let mut v = FnUsageVisitor { + cx, + def_id_to_usage: &mut self.def_id_to_usage, + }; + cx.tcx.hir().visit_all_item_likes_in_crate(&mut v); + + for usage in self.def_id_to_usage.values() { + let fn_span = usage.0; + if let [usage] = *usage.1 { + span_lint_and_help( + cx, + SINGLE_CALL_FN, + fn_span, + "this function is only used once", + Some(usage), + "used here", + ); + } + } + } +} + +struct FnUsageVisitor<'a, 'tcx> { + cx: &'a LateContext<'tcx>, + def_id_to_usage: &'a mut FxHashMap)>, +} + +impl<'a, 'tcx> Visitor<'tcx> for FnUsageVisitor<'a, 'tcx> { + type NestedFilter = OnlyBodies; + + fn nested_visit_map(&mut self) -> Self::Map { + self.cx.tcx.hir() + } + + fn visit_expr(&mut self, expr: &'tcx Expr<'tcx>) { + let Self { cx, .. } = *self; + + if let ExprKind::Path(qpath) = expr.kind + && let res = cx.qpath_res(&qpath, expr.hir_id) + && let Some(call_def_id) = res.opt_def_id() + && let Some(def_id) = call_def_id.as_local() + && let Some(usage) = self.def_id_to_usage.get_mut(&def_id) + { + usage.1.push(expr.span); + } + + walk_expr(self, expr); + } +} diff --git a/tests/ui/single_call_fn.rs b/tests/ui/single_call_fn.rs new file mode 100644 index 00000000000..9806eaf3c42 --- /dev/null +++ b/tests/ui/single_call_fn.rs @@ -0,0 +1,49 @@ +//@aux-build:proc_macros.rs +#![allow(unused)] +#![warn(clippy::single_call_fn)] +#![no_main] + +#[macro_use] +extern crate proc_macros; + +// Do not lint since it's public +pub fn f() {} + +fn g() { + f(); +} + +fn c() { + println!("really"); + println!("long"); + println!("function..."); +} + +fn d() { + c(); +} + +fn a() {} + +fn b() { + a(); + + external! { + fn lol() { + lol_inner(); + } + fn lol_inner() {} + } + with_span! { + span + fn lol2() { + lol2_inner(); + } + fn lol2_inner() {} + } +} + +fn e() { + b(); + b(); +} diff --git a/tests/ui/single_call_fn.stderr b/tests/ui/single_call_fn.stderr new file mode 100644 index 00000000000..decf561eed4 --- /dev/null +++ b/tests/ui/single_call_fn.stderr @@ -0,0 +1,31 @@ +error: this function is only used once + --> $DIR/single_call_fn.rs:26:1 + | +LL | fn a() {} + | ^^^^^^^^^ + | +help: used here + --> $DIR/single_call_fn.rs:29:5 + | +LL | a(); + | ^ + = note: `-D clippy::single-call-fn` implied by `-D warnings` + +error: this function is only used once + --> $DIR/single_call_fn.rs:16:1 + | +LL | / fn c() { +LL | | println!("really"); +LL | | println!("long"); +LL | | println!("function..."); +LL | | } + | |_^ + | +help: used here + --> $DIR/single_call_fn.rs:23:5 + | +LL | c(); + | ^ + +error: aborting due to 2 previous errors + From a8605269bde2c82b5359997fc8cfdfef6a346ccf Mon Sep 17 00:00:00 2001 From: Centri3 <114838443+Centri3@users.noreply.github.com> Date: Wed, 14 Jun 2023 07:16:56 -0500 Subject: [PATCH 226/310] add test for closures --- clippy_lints/src/single_call_fn.rs | 8 ++--- clippy_lints/src/utils/conf.rs | 2 +- tests/ui/single_call_fn.rs | 19 +++++++++- tests/ui/single_call_fn.stderr | 56 +++++++++++++++++++++--------- 4 files changed, 63 insertions(+), 22 deletions(-) diff --git a/clippy_lints/src/single_call_fn.rs b/clippy_lints/src/single_call_fn.rs index d0fbedee832..55a19b813b4 100644 --- a/clippy_lints/src/single_call_fn.rs +++ b/clippy_lints/src/single_call_fn.rs @@ -88,14 +88,14 @@ impl<'tcx> LateLintPass<'tcx> for SingleCallFn { cx.tcx.hir().visit_all_item_likes_in_crate(&mut v); for usage in self.def_id_to_usage.values() { - let fn_span = usage.0; - if let [usage] = *usage.1 { + let single_call_fn_span = usage.0; + if let [caller_span] = *usage.1 { span_lint_and_help( cx, SINGLE_CALL_FN, - fn_span, + single_call_fn_span, "this function is only used once", - Some(usage), + Some(caller_span), "used here", ); } diff --git a/clippy_lints/src/utils/conf.rs b/clippy_lints/src/utils/conf.rs index e8c8d478ffc..987e2abec50 100644 --- a/clippy_lints/src/utils/conf.rs +++ b/clippy_lints/src/utils/conf.rs @@ -289,7 +289,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, UNNECESSARY_BOX_RETURNS. + /// 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, SINGLE_CALL_FN. /// /// Suppress lints whenever the suggested change would cause breakage for other crates. (avoid_breaking_exported_api: bool = true), diff --git a/tests/ui/single_call_fn.rs b/tests/ui/single_call_fn.rs index 9806eaf3c42..e7f819cc8a1 100644 --- a/tests/ui/single_call_fn.rs +++ b/tests/ui/single_call_fn.rs @@ -1,5 +1,5 @@ //@aux-build:proc_macros.rs -#![allow(unused)] +#![allow(clippy::redundant_closure_call, unused)] #![warn(clippy::single_call_fn)] #![no_main] @@ -9,6 +9,23 @@ extern crate proc_macros; // Do not lint since it's public pub fn f() {} +fn i() {} +fn j() {} + +fn h() { + // Linted + let a = i; + // Do not lint closures + let a = (|| { + // Not linted + a(); + // Imo, it's reasonable to lint this as the function is still only being used once. Just in + // a closure. + j(); + }); + a(); +} + fn g() { f(); } diff --git a/tests/ui/single_call_fn.stderr b/tests/ui/single_call_fn.stderr index decf561eed4..9ef8c487844 100644 --- a/tests/ui/single_call_fn.stderr +++ b/tests/ui/single_call_fn.stderr @@ -1,18 +1,5 @@ error: this function is only used once - --> $DIR/single_call_fn.rs:26:1 - | -LL | fn a() {} - | ^^^^^^^^^ - | -help: used here - --> $DIR/single_call_fn.rs:29:5 - | -LL | a(); - | ^ - = note: `-D clippy::single-call-fn` implied by `-D warnings` - -error: this function is only used once - --> $DIR/single_call_fn.rs:16:1 + --> $DIR/single_call_fn.rs:33:1 | LL | / fn c() { LL | | println!("really"); @@ -22,10 +9,47 @@ LL | | } | |_^ | help: used here - --> $DIR/single_call_fn.rs:23:5 + --> $DIR/single_call_fn.rs:40:5 | LL | c(); | ^ + = note: `-D clippy::single-call-fn` implied by `-D warnings` -error: aborting due to 2 previous errors +error: this function is only used once + --> $DIR/single_call_fn.rs:12:1 + | +LL | fn i() {} + | ^^^^^^^^^ + | +help: used here + --> $DIR/single_call_fn.rs:17:13 + | +LL | let a = i; + | ^ + +error: this function is only used once + --> $DIR/single_call_fn.rs:43:1 + | +LL | fn a() {} + | ^^^^^^^^^ + | +help: used here + --> $DIR/single_call_fn.rs:46:5 + | +LL | a(); + | ^ + +error: this function is only used once + --> $DIR/single_call_fn.rs:13:1 + | +LL | fn j() {} + | ^^^^^^^^^ + | +help: used here + --> $DIR/single_call_fn.rs:24:9 + | +LL | j(); + | ^ + +error: aborting due to 4 previous errors From 65b93a5b434596a545b97c0ad236e451745c87ff Mon Sep 17 00:00:00 2001 From: hehaoqian <39371646+hehaoqian@users.noreply.github.com> Date: Sun, 18 Jun 2023 00:19:35 +0800 Subject: [PATCH 227/310] Fix false positive of [self_named_module_files] and [mod_module_files] --- clippy_lints/src/module_style.rs | 8 ++++ tests/workspace.rs | 40 +++++++++++++++++++ tests/workspace_test/Cargo.toml | 2 +- .../pass_mod_with_dep_in_subdir/Cargo.toml | 10 +++++ .../dep_no_mod/Cargo.toml | 9 +++++ .../dep_no_mod/src/foo.rs | 2 + .../dep_no_mod/src/foo/hello.rs | 1 + .../dep_no_mod/src/lib.rs | 5 +++ .../src/bad/mod.rs | 1 + .../pass_mod_with_dep_in_subdir/src/main.rs | 13 ++++++ .../src/more/foo.rs | 1 + .../src/more/inner/mod.rs | 1 + .../src/more/mod.rs | 2 + .../pass_no_mod_with_dep_in_subdir/Cargo.toml | 10 +++++ .../dep_with_mod/Cargo.toml | 9 +++++ .../dep_with_mod/src/lib.rs | 7 ++++ .../dep_with_mod/src/with_mod/inner.rs | 1 + .../dep_with_mod/src/with_mod/inner/stuff.rs | 3 ++ .../src/with_mod/inner/stuff/most.rs | 1 + .../dep_with_mod/src/with_mod/mod.rs | 3 ++ .../src/good.rs | 1 + .../src/main.rs | 9 +++++ 22 files changed, 138 insertions(+), 1 deletion(-) create mode 100644 tests/workspace_test/module_style/pass_mod_with_dep_in_subdir/Cargo.toml create mode 100644 tests/workspace_test/module_style/pass_mod_with_dep_in_subdir/dep_no_mod/Cargo.toml create mode 100644 tests/workspace_test/module_style/pass_mod_with_dep_in_subdir/dep_no_mod/src/foo.rs create mode 100644 tests/workspace_test/module_style/pass_mod_with_dep_in_subdir/dep_no_mod/src/foo/hello.rs create mode 100644 tests/workspace_test/module_style/pass_mod_with_dep_in_subdir/dep_no_mod/src/lib.rs create mode 100644 tests/workspace_test/module_style/pass_mod_with_dep_in_subdir/src/bad/mod.rs create mode 100644 tests/workspace_test/module_style/pass_mod_with_dep_in_subdir/src/main.rs create mode 100644 tests/workspace_test/module_style/pass_mod_with_dep_in_subdir/src/more/foo.rs create mode 100644 tests/workspace_test/module_style/pass_mod_with_dep_in_subdir/src/more/inner/mod.rs create mode 100644 tests/workspace_test/module_style/pass_mod_with_dep_in_subdir/src/more/mod.rs create mode 100644 tests/workspace_test/module_style/pass_no_mod_with_dep_in_subdir/Cargo.toml create mode 100644 tests/workspace_test/module_style/pass_no_mod_with_dep_in_subdir/dep_with_mod/Cargo.toml create mode 100644 tests/workspace_test/module_style/pass_no_mod_with_dep_in_subdir/dep_with_mod/src/lib.rs create mode 100644 tests/workspace_test/module_style/pass_no_mod_with_dep_in_subdir/dep_with_mod/src/with_mod/inner.rs create mode 100644 tests/workspace_test/module_style/pass_no_mod_with_dep_in_subdir/dep_with_mod/src/with_mod/inner/stuff.rs create mode 100644 tests/workspace_test/module_style/pass_no_mod_with_dep_in_subdir/dep_with_mod/src/with_mod/inner/stuff/most.rs create mode 100644 tests/workspace_test/module_style/pass_no_mod_with_dep_in_subdir/dep_with_mod/src/with_mod/mod.rs create mode 100644 tests/workspace_test/module_style/pass_no_mod_with_dep_in_subdir/src/good.rs create mode 100644 tests/workspace_test/module_style/pass_no_mod_with_dep_in_subdir/src/main.rs diff --git a/clippy_lints/src/module_style.rs b/clippy_lints/src/module_style.rs index 349fcd2274d..b393db53b36 100644 --- a/clippy_lints/src/module_style.rs +++ b/clippy_lints/src/module_style.rs @@ -2,6 +2,7 @@ use rustc_ast::ast; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_lint::{EarlyContext, EarlyLintPass, Level, LintContext}; use rustc_session::{declare_tool_lint, impl_lint_pass}; +use rustc_span::def_id::LOCAL_CRATE; use rustc_span::{FileName, SourceFile, Span, SyntaxContext}; use std::ffi::OsStr; use std::path::{Component, Path}; @@ -91,6 +92,13 @@ impl EarlyLintPass for ModStyle { let mut file_map = FxHashMap::default(); for file in files.iter() { if let FileName::Real(name) = &file.name && let Some(lp) = name.local_path() { + if file.cnum != LOCAL_CRATE { + // [#8887](https://github.com/rust-lang/rust-clippy/issues/8887) + // Only check files in the current crate. + // Fix false positive that crate dependency in workspace sub directory + // is checked unintentionally. + continue; + } let path = if lp.is_relative() { lp } else if let Ok(relative) = lp.strip_prefix(trim_to_src) { diff --git a/tests/workspace.rs b/tests/workspace.rs index c9cbc50546c..699ab2be199 100644 --- a/tests/workspace.rs +++ b/tests/workspace.rs @@ -6,6 +6,46 @@ use test_utils::{CARGO_CLIPPY_PATH, IS_RUSTC_TEST_SUITE}; mod test_utils; +#[test] +fn test_module_style_with_dep_in_subdir() { + if IS_RUSTC_TEST_SUITE { + return; + } + let root = PathBuf::from(env!("CARGO_MANIFEST_DIR")); + let target_dir = root.join("target").join("workspace_test"); + let cwd = root.join("tests/workspace_test"); + + // Make sure we start with a clean state + Command::new("cargo") + .current_dir(&cwd) + .env("CARGO_TARGET_DIR", &target_dir) + .arg("clean") + .args(["-p", "pass-no-mod-with-dep-in-subdir"]) + .args(["-p", "pass-mod-with-dep-in-subdir"]) + .output() + .unwrap(); + + // [#8887](https://github.com/rust-lang/rust-clippy/issues/8887) + // `mod.rs` checks should not be applied to crate dependencies + // located in the subdirectory of workspace + let output = Command::new(&*CARGO_CLIPPY_PATH) + .current_dir(&cwd) + .env("CARGO_INCREMENTAL", "0") + .env("CARGO_TARGET_DIR", &target_dir) + .arg("clippy") + .args(["-p", "pass-no-mod-with-dep-in-subdir"]) + .args(["-p", "pass-mod-with-dep-in-subdir"]) + .arg("--") + .arg("-Cdebuginfo=0") // disable debuginfo to generate less data in the target dir + .output() + .unwrap(); + + println!("status: {}", output.status); + println!("stdout: {}", String::from_utf8_lossy(&output.stdout)); + println!("stderr: {}", String::from_utf8_lossy(&output.stderr)); + assert!(output.status.success()); +} + #[test] fn test_no_deps_ignores_path_deps_in_workspaces() { if IS_RUSTC_TEST_SUITE { diff --git a/tests/workspace_test/Cargo.toml b/tests/workspace_test/Cargo.toml index bf5b4ca5288..d24b278ccc2 100644 --- a/tests/workspace_test/Cargo.toml +++ b/tests/workspace_test/Cargo.toml @@ -4,4 +4,4 @@ version = "0.1.0" edition = "2018" [workspace] -members = ["subcrate"] +members = ["subcrate", "module_style/pass_no_mod_with_dep_in_subdir", "module_style/pass_mod_with_dep_in_subdir"] diff --git a/tests/workspace_test/module_style/pass_mod_with_dep_in_subdir/Cargo.toml b/tests/workspace_test/module_style/pass_mod_with_dep_in_subdir/Cargo.toml new file mode 100644 index 00000000000..15dcde4e30a --- /dev/null +++ b/tests/workspace_test/module_style/pass_mod_with_dep_in_subdir/Cargo.toml @@ -0,0 +1,10 @@ +[package] +name = "pass-mod-with-dep-in-subdir" +version = "0.1.0" +edition = "2018" +publish = false + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +dep-no-mod = { path = "dep_no_mod"} diff --git a/tests/workspace_test/module_style/pass_mod_with_dep_in_subdir/dep_no_mod/Cargo.toml b/tests/workspace_test/module_style/pass_mod_with_dep_in_subdir/dep_no_mod/Cargo.toml new file mode 100644 index 00000000000..55569bc25ed --- /dev/null +++ b/tests/workspace_test/module_style/pass_mod_with_dep_in_subdir/dep_no_mod/Cargo.toml @@ -0,0 +1,9 @@ +[package] +name = "dep-no-mod" +version = "0.1.0" +edition = "2018" +publish = false + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] diff --git a/tests/workspace_test/module_style/pass_mod_with_dep_in_subdir/dep_no_mod/src/foo.rs b/tests/workspace_test/module_style/pass_mod_with_dep_in_subdir/dep_no_mod/src/foo.rs new file mode 100644 index 00000000000..7b0966a4586 --- /dev/null +++ b/tests/workspace_test/module_style/pass_mod_with_dep_in_subdir/dep_no_mod/src/foo.rs @@ -0,0 +1,2 @@ +pub mod hello; +pub struct Thing; diff --git a/tests/workspace_test/module_style/pass_mod_with_dep_in_subdir/dep_no_mod/src/foo/hello.rs b/tests/workspace_test/module_style/pass_mod_with_dep_in_subdir/dep_no_mod/src/foo/hello.rs new file mode 100644 index 00000000000..99940dce528 --- /dev/null +++ b/tests/workspace_test/module_style/pass_mod_with_dep_in_subdir/dep_no_mod/src/foo/hello.rs @@ -0,0 +1 @@ +pub struct Hello; diff --git a/tests/workspace_test/module_style/pass_mod_with_dep_in_subdir/dep_no_mod/src/lib.rs b/tests/workspace_test/module_style/pass_mod_with_dep_in_subdir/dep_no_mod/src/lib.rs new file mode 100644 index 00000000000..c62f9acbf2c --- /dev/null +++ b/tests/workspace_test/module_style/pass_mod_with_dep_in_subdir/dep_no_mod/src/lib.rs @@ -0,0 +1,5 @@ +pub mod foo; + +pub fn foo() { + let _ = foo::Thing; +} diff --git a/tests/workspace_test/module_style/pass_mod_with_dep_in_subdir/src/bad/mod.rs b/tests/workspace_test/module_style/pass_mod_with_dep_in_subdir/src/bad/mod.rs new file mode 100644 index 00000000000..f19ab10d5fb --- /dev/null +++ b/tests/workspace_test/module_style/pass_mod_with_dep_in_subdir/src/bad/mod.rs @@ -0,0 +1 @@ +pub struct Thing; diff --git a/tests/workspace_test/module_style/pass_mod_with_dep_in_subdir/src/main.rs b/tests/workspace_test/module_style/pass_mod_with_dep_in_subdir/src/main.rs new file mode 100644 index 00000000000..5cb4795e945 --- /dev/null +++ b/tests/workspace_test/module_style/pass_mod_with_dep_in_subdir/src/main.rs @@ -0,0 +1,13 @@ +#![deny(clippy::self_named_module_files)] + +mod bad; +mod more; +extern crate dep_no_mod; + +fn main() { + let _ = bad::Thing; + let _ = more::foo::Foo; + let _ = more::inner::Inner; + let _ = dep_no_mod::foo::Thing; + let _ = dep_no_mod::foo::hello::Hello; +} diff --git a/tests/workspace_test/module_style/pass_mod_with_dep_in_subdir/src/more/foo.rs b/tests/workspace_test/module_style/pass_mod_with_dep_in_subdir/src/more/foo.rs new file mode 100644 index 00000000000..4a835673a59 --- /dev/null +++ b/tests/workspace_test/module_style/pass_mod_with_dep_in_subdir/src/more/foo.rs @@ -0,0 +1 @@ +pub struct Foo; diff --git a/tests/workspace_test/module_style/pass_mod_with_dep_in_subdir/src/more/inner/mod.rs b/tests/workspace_test/module_style/pass_mod_with_dep_in_subdir/src/more/inner/mod.rs new file mode 100644 index 00000000000..aa84f78cc2c --- /dev/null +++ b/tests/workspace_test/module_style/pass_mod_with_dep_in_subdir/src/more/inner/mod.rs @@ -0,0 +1 @@ +pub struct Inner; diff --git a/tests/workspace_test/module_style/pass_mod_with_dep_in_subdir/src/more/mod.rs b/tests/workspace_test/module_style/pass_mod_with_dep_in_subdir/src/more/mod.rs new file mode 100644 index 00000000000..d79569f78ff --- /dev/null +++ b/tests/workspace_test/module_style/pass_mod_with_dep_in_subdir/src/more/mod.rs @@ -0,0 +1,2 @@ +pub mod foo; +pub mod inner; diff --git a/tests/workspace_test/module_style/pass_no_mod_with_dep_in_subdir/Cargo.toml b/tests/workspace_test/module_style/pass_no_mod_with_dep_in_subdir/Cargo.toml new file mode 100644 index 00000000000..060cb18dc9f --- /dev/null +++ b/tests/workspace_test/module_style/pass_no_mod_with_dep_in_subdir/Cargo.toml @@ -0,0 +1,10 @@ +[package] +name = "pass-no-mod-with-dep-in-subdir" +version = "0.1.0" +edition = "2018" +publish = false + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +dep-with-mod = { path = "dep_with_mod"} diff --git a/tests/workspace_test/module_style/pass_no_mod_with_dep_in_subdir/dep_with_mod/Cargo.toml b/tests/workspace_test/module_style/pass_no_mod_with_dep_in_subdir/dep_with_mod/Cargo.toml new file mode 100644 index 00000000000..b25725cd561 --- /dev/null +++ b/tests/workspace_test/module_style/pass_no_mod_with_dep_in_subdir/dep_with_mod/Cargo.toml @@ -0,0 +1,9 @@ +[package] +name = "dep-with-mod" +version = "0.1.0" +edition = "2018" +publish = false + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] diff --git a/tests/workspace_test/module_style/pass_no_mod_with_dep_in_subdir/dep_with_mod/src/lib.rs b/tests/workspace_test/module_style/pass_no_mod_with_dep_in_subdir/dep_with_mod/src/lib.rs new file mode 100644 index 00000000000..4647424f2c2 --- /dev/null +++ b/tests/workspace_test/module_style/pass_no_mod_with_dep_in_subdir/dep_with_mod/src/lib.rs @@ -0,0 +1,7 @@ +pub mod with_mod; + +pub fn foo() { + let _ = with_mod::Thing; + let _ = with_mod::inner::stuff::Inner; + let _ = with_mod::inner::stuff::most::Snarks; +} diff --git a/tests/workspace_test/module_style/pass_no_mod_with_dep_in_subdir/dep_with_mod/src/with_mod/inner.rs b/tests/workspace_test/module_style/pass_no_mod_with_dep_in_subdir/dep_with_mod/src/with_mod/inner.rs new file mode 100644 index 00000000000..91cd540a28f --- /dev/null +++ b/tests/workspace_test/module_style/pass_no_mod_with_dep_in_subdir/dep_with_mod/src/with_mod/inner.rs @@ -0,0 +1 @@ +pub mod stuff; diff --git a/tests/workspace_test/module_style/pass_no_mod_with_dep_in_subdir/dep_with_mod/src/with_mod/inner/stuff.rs b/tests/workspace_test/module_style/pass_no_mod_with_dep_in_subdir/dep_with_mod/src/with_mod/inner/stuff.rs new file mode 100644 index 00000000000..7713fa9d35c --- /dev/null +++ b/tests/workspace_test/module_style/pass_no_mod_with_dep_in_subdir/dep_with_mod/src/with_mod/inner/stuff.rs @@ -0,0 +1,3 @@ +pub mod most; + +pub struct Inner; diff --git a/tests/workspace_test/module_style/pass_no_mod_with_dep_in_subdir/dep_with_mod/src/with_mod/inner/stuff/most.rs b/tests/workspace_test/module_style/pass_no_mod_with_dep_in_subdir/dep_with_mod/src/with_mod/inner/stuff/most.rs new file mode 100644 index 00000000000..5a5eaf9670f --- /dev/null +++ b/tests/workspace_test/module_style/pass_no_mod_with_dep_in_subdir/dep_with_mod/src/with_mod/inner/stuff/most.rs @@ -0,0 +1 @@ +pub struct Snarks; diff --git a/tests/workspace_test/module_style/pass_no_mod_with_dep_in_subdir/dep_with_mod/src/with_mod/mod.rs b/tests/workspace_test/module_style/pass_no_mod_with_dep_in_subdir/dep_with_mod/src/with_mod/mod.rs new file mode 100644 index 00000000000..a12734db7cb --- /dev/null +++ b/tests/workspace_test/module_style/pass_no_mod_with_dep_in_subdir/dep_with_mod/src/with_mod/mod.rs @@ -0,0 +1,3 @@ +pub mod inner; + +pub struct Thing; diff --git a/tests/workspace_test/module_style/pass_no_mod_with_dep_in_subdir/src/good.rs b/tests/workspace_test/module_style/pass_no_mod_with_dep_in_subdir/src/good.rs new file mode 100644 index 00000000000..f19ab10d5fb --- /dev/null +++ b/tests/workspace_test/module_style/pass_no_mod_with_dep_in_subdir/src/good.rs @@ -0,0 +1 @@ +pub struct Thing; diff --git a/tests/workspace_test/module_style/pass_no_mod_with_dep_in_subdir/src/main.rs b/tests/workspace_test/module_style/pass_no_mod_with_dep_in_subdir/src/main.rs new file mode 100644 index 00000000000..42eb99cd7a3 --- /dev/null +++ b/tests/workspace_test/module_style/pass_no_mod_with_dep_in_subdir/src/main.rs @@ -0,0 +1,9 @@ +#![deny(clippy::mod_module_files)] + +mod good; +pub use dep_with_mod::with_mod::Thing; + +fn main() { + let _ = good::Thing; + let _ = dep_with_mod::with_mod::Thing; +} From 45a685e3a95126a6560fd2658c8d1af371441e47 Mon Sep 17 00:00:00 2001 From: Deadbeef Date: Sun, 18 Jun 2023 05:24:38 +0000 Subject: [PATCH 228/310] Better error for non const `PartialEq` call generated by `match` --- 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 c0d2c835d63..566eecf36a7 100644 --- a/clippy_utils/src/qualify_min_const_fn.rs +++ b/clippy_utils/src/qualify_min_const_fn.rs @@ -317,7 +317,7 @@ fn check_terminator<'tcx>( TerminatorKind::Call { func, args, - from_hir_call: _, + call_source: _, destination: _, target: _, unwind: _, From f711c7e1f6b8253ab8cea13beac69927824259c9 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Sun, 18 Jun 2023 22:10:07 +0000 Subject: [PATCH 229/310] Treat TAIT equation as always ambiguous in coherence --- tests/ui/from_over_into_unfixable.rs | 6 ----- tests/ui/from_over_into_unfixable.stderr | 33 ++++++++++++++++++------ 2 files changed, 25 insertions(+), 14 deletions(-) diff --git a/tests/ui/from_over_into_unfixable.rs b/tests/ui/from_over_into_unfixable.rs index bd62c655216..3b280b7488a 100644 --- a/tests/ui/from_over_into_unfixable.rs +++ b/tests/ui/from_over_into_unfixable.rs @@ -32,10 +32,4 @@ impl Into for ContainsVal { } } -type Opaque = impl Sized; -struct IntoOpaque; -impl Into for IntoOpaque { - fn into(self) -> Opaque {} -} - fn main() {} diff --git a/tests/ui/from_over_into_unfixable.stderr b/tests/ui/from_over_into_unfixable.stderr index bb966af4b0f..251f1d84e74 100644 --- a/tests/ui/from_over_into_unfixable.stderr +++ b/tests/ui/from_over_into_unfixable.stderr @@ -1,12 +1,29 @@ -error[E0658]: `impl Trait` in type aliases is unstable - --> $DIR/from_over_into_unfixable.rs:35:15 +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:11:1 | -LL | type Opaque = impl Sized; - | ^^^^^^^^^^ +LL | impl Into for String { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | - = note: see issue #63063 for more information - = help: add `#![feature(type_alias_impl_trait)]` to the crate attributes to enable + = help: replace the `Into` implementation with `From` + = note: `-D clippy::from-over-into` implied by `-D warnings` -error: aborting due to previous error +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:19:1 + | +LL | impl Into for &'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 + | +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` implementation with `From` + +error: aborting due to 3 previous errors -For more information about this error, try `rustc --explain E0658`. From 2cd4a9182a4b4a1030594866414a3100b594343e Mon Sep 17 00:00:00 2001 From: Centri3 <114838443+Centri3@users.noreply.github.com> Date: Sat, 17 Jun 2023 20:00:36 -0500 Subject: [PATCH 230/310] Ignore functions annotated with `#[test]` --- book/src/lint_configuration.md | 1 + clippy_lints/src/single_call_fn.rs | 5 +++-- tests/ui/single_call_fn.rs | 9 +++++++++ tests/ui/single_call_fn.stderr | 16 ++++++++-------- 4 files changed, 21 insertions(+), 10 deletions(-) diff --git a/book/src/lint_configuration.md b/book/src/lint_configuration.md index 78a5f9da461..cc4caae566f 100644 --- a/book/src/lint_configuration.md +++ b/book/src/lint_configuration.md @@ -94,6 +94,7 @@ Suppress lints whenever the suggested change would cause breakage for other crat * [`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) +* [`single_call_fn`](https://rust-lang.github.io/rust-clippy/master/index.html#single_call_fn) ## `msrv` diff --git a/clippy_lints/src/single_call_fn.rs b/clippy_lints/src/single_call_fn.rs index 55a19b813b4..42753d2e951 100644 --- a/clippy_lints/src/single_call_fn.rs +++ b/clippy_lints/src/single_call_fn.rs @@ -1,5 +1,5 @@ use clippy_utils::diagnostics::span_lint_and_help; -use clippy_utils::is_from_proc_macro; +use clippy_utils::{is_from_proc_macro, is_in_test_function}; use rustc_data_structures::fx::FxHashMap; use rustc_hir::def_id::LocalDefId; use rustc_hir::intravisit::{walk_expr, Visitor}; @@ -12,7 +12,7 @@ use rustc_span::Span; declare_clippy_lint! { /// ### What it does - /// Checks for functions that are only used once. + /// Checks for functions that are only used once. Does not lint tests. /// /// ### Why is this bad? /// It's usually not, splitting a function into multiple parts often improves readability and in @@ -73,6 +73,7 @@ impl<'tcx> LateLintPass<'tcx> for SingleCallFn { if self.avoid_breaking_exported_api && cx.effective_visibilities.is_exported(def_id) || in_external_macro(cx.sess(), span) || is_from_proc_macro(cx, &(&kind, body, cx.tcx.local_def_id_to_hir_id(def_id), span)) + || is_in_test_function(cx.tcx, body.value.hir_id) { return; } diff --git a/tests/ui/single_call_fn.rs b/tests/ui/single_call_fn.rs index e7f819cc8a1..bfb773187fb 100644 --- a/tests/ui/single_call_fn.rs +++ b/tests/ui/single_call_fn.rs @@ -1,4 +1,5 @@ //@aux-build:proc_macros.rs +//@compile-flags: --test #![allow(clippy::redundant_closure_call, unused)] #![warn(clippy::single_call_fn)] #![no_main] @@ -64,3 +65,11 @@ fn e() { b(); b(); } + +#[test] +fn k() {} + +#[test] +fn l() { + k(); +} diff --git a/tests/ui/single_call_fn.stderr b/tests/ui/single_call_fn.stderr index 9ef8c487844..bb92e3cf71a 100644 --- a/tests/ui/single_call_fn.stderr +++ b/tests/ui/single_call_fn.stderr @@ -1,5 +1,5 @@ error: this function is only used once - --> $DIR/single_call_fn.rs:33:1 + --> $DIR/single_call_fn.rs:34:1 | LL | / fn c() { LL | | println!("really"); @@ -9,44 +9,44 @@ LL | | } | |_^ | help: used here - --> $DIR/single_call_fn.rs:40:5 + --> $DIR/single_call_fn.rs:41:5 | LL | c(); | ^ = note: `-D clippy::single-call-fn` implied by `-D warnings` error: this function is only used once - --> $DIR/single_call_fn.rs:12:1 + --> $DIR/single_call_fn.rs:13:1 | LL | fn i() {} | ^^^^^^^^^ | help: used here - --> $DIR/single_call_fn.rs:17:13 + --> $DIR/single_call_fn.rs:18:13 | LL | let a = i; | ^ error: this function is only used once - --> $DIR/single_call_fn.rs:43:1 + --> $DIR/single_call_fn.rs:44:1 | LL | fn a() {} | ^^^^^^^^^ | help: used here - --> $DIR/single_call_fn.rs:46:5 + --> $DIR/single_call_fn.rs:47:5 | LL | a(); | ^ error: this function is only used once - --> $DIR/single_call_fn.rs:13:1 + --> $DIR/single_call_fn.rs:14:1 | LL | fn j() {} | ^^^^^^^^^ | help: used here - --> $DIR/single_call_fn.rs:24:9 + --> $DIR/single_call_fn.rs:25:9 | LL | j(); | ^ From e11ebbd5e77d8faa6c1cbd11be6f050199382845 Mon Sep 17 00:00:00 2001 From: hehaoqian Date: Mon, 19 Jun 2023 08:19:06 +0800 Subject: [PATCH 231/310] Move continue into if statement Co-authored-by: Catherine <114838443+Centri3@users.noreply.github.com> --- clippy_lints/src/module_style.rs | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/clippy_lints/src/module_style.rs b/clippy_lints/src/module_style.rs index b393db53b36..439cae812b7 100644 --- a/clippy_lints/src/module_style.rs +++ b/clippy_lints/src/module_style.rs @@ -91,14 +91,14 @@ impl EarlyLintPass for ModStyle { // `{ foo => path/to/foo.rs, .. } let mut file_map = FxHashMap::default(); for file in files.iter() { - if let FileName::Real(name) = &file.name && let Some(lp) = name.local_path() { - if file.cnum != LOCAL_CRATE { - // [#8887](https://github.com/rust-lang/rust-clippy/issues/8887) - // Only check files in the current crate. - // Fix false positive that crate dependency in workspace sub directory - // is checked unintentionally. - continue; - } + if let FileName::Real(name) = &file.name + && let Some(lp) = name.local_path() + && file.cnum == LOCAL_CRATE + { + // [#8887](https://github.com/rust-lang/rust-clippy/issues/8887) + // Only check files in the current crate. + // Fix false positive that crate dependency in workspace sub directory + // is checked unintentionally. let path = if lp.is_relative() { lp } else if let Ok(relative) = lp.strip_prefix(trim_to_src) { From 66590ba41b21d38aa28e659e282afcbeb0fdbd13 Mon Sep 17 00:00:00 2001 From: Eric Mark Martin Date: Mon, 19 Jun 2023 03:44:04 -0400 Subject: [PATCH 232/310] use PlaceRef abstractions --- clippy_lints/src/redundant_clone.rs | 15 +++++---------- clippy_utils/src/qualify_min_const_fn.rs | 7 ++----- 2 files changed, 7 insertions(+), 15 deletions(-) diff --git a/clippy_lints/src/redundant_clone.rs b/clippy_lints/src/redundant_clone.rs index 685d738cbb7..e36adef555e 100644 --- a/clippy_lints/src/redundant_clone.rs +++ b/clippy_lints/src/redundant_clone.rs @@ -320,8 +320,6 @@ fn base_local_and_movability<'tcx>( mir: &mir::Body<'tcx>, place: mir::Place<'tcx>, ) -> (mir::Local, CannotMoveOut) { - use rustc_middle::mir::PlaceRef; - // Dereference. You cannot move things out from a borrowed value. let mut deref = false; // Accessing a field of an ADT that has `Drop`. Moving the field out will cause E0509. @@ -330,17 +328,14 @@ fn base_local_and_movability<'tcx>( // underlying type implements Copy let mut slice = false; - let PlaceRef { local, mut projection } = place.as_ref(); - while let [base @ .., elem] = projection { - projection = base; + for (base, elem) in place.as_ref().iter_projections() { + let base_ty = base.ty(&mir.local_decls, cx.tcx).ty; deref |= matches!(elem, mir::ProjectionElem::Deref); - field |= matches!(elem, mir::ProjectionElem::Field(..)) - && has_drop(cx, mir::Place::ty_from(local, projection, &mir.local_decls, cx.tcx).ty); - slice |= matches!(elem, mir::ProjectionElem::Index(..)) - && !is_copy(cx, mir::Place::ty_from(local, projection, &mir.local_decls, cx.tcx).ty); + field |= matches!(elem, mir::ProjectionElem::Field(..)) && has_drop(cx, base_ty); + slice |= matches!(elem, mir::ProjectionElem::Index(..)) && !is_copy(cx, base_ty); } - (local, deref || field || slice) + (place.local, deref || field || slice) } #[derive(Default)] diff --git a/clippy_utils/src/qualify_min_const_fn.rs b/clippy_utils/src/qualify_min_const_fn.rs index dcd372f689d..3e261b20465 100644 --- a/clippy_utils/src/qualify_min_const_fn.rs +++ b/clippy_utils/src/qualify_min_const_fn.rs @@ -284,13 +284,10 @@ fn check_operand<'tcx>(tcx: TyCtxt<'tcx>, operand: &Operand<'tcx>, span: Span, b } fn check_place<'tcx>(tcx: TyCtxt<'tcx>, place: Place<'tcx>, span: Span, body: &Body<'tcx>) -> McfResult { - let mut cursor = place.projection.as_ref(); - - while let [ref proj_base @ .., elem] = *cursor { - cursor = proj_base; + for (base, elem) in place.as_ref().iter_projections() { match elem { ProjectionElem::Field(..) => { - let base_ty = Place::ty_from(place.local, proj_base, body, tcx).ty; + let base_ty = base.ty(body, tcx).ty; if let Some(def) = base_ty.ty_adt_def() { // No union field accesses in `const fn` if def.is_union() { From 9bc6e114e0f8f775869bc6d23b4cb9207941b5b0 Mon Sep 17 00:00:00 2001 From: Eric Mark Martin Date: Mon, 19 Jun 2023 03:44:34 -0400 Subject: [PATCH 233/310] add non-test-case for suggesting const on functions accessing union fields --- tests/ui/missing_const_for_fn/cant_be_const.rs | 9 +++++++++ 1 file changed, 9 insertions(+) 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 286d208b25b..abadf82fe4b 100644 --- a/tests/ui/missing_const_for_fn/cant_be_const.rs +++ b/tests/ui/missing_const_for_fn/cant_be_const.rs @@ -157,3 +157,12 @@ impl Issue10617 { self.0 } } + +union U { + f: u32, +} + +// Do not lint because accessing union fields from const functions is unstable +fn h(u: U) -> u32 { + unsafe { u.f } +} From efec6d61b5f6927b900793f45c9f09b6ccc73bd4 Mon Sep 17 00:00:00 2001 From: Maybe Waffle Date: Mon, 19 Jun 2023 12:22:02 +0000 Subject: [PATCH 234/310] Support `ast::ExprKind::Become` in clippy --- clippy_utils/src/sugg.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/clippy_utils/src/sugg.rs b/clippy_utils/src/sugg.rs index f477524eec5..a87d58110b0 100644 --- a/clippy_utils/src/sugg.rs +++ b/clippy_utils/src/sugg.rs @@ -211,6 +211,7 @@ impl<'a> Sugg<'a> { | ast::ExprKind::Path(..) | ast::ExprKind::Repeat(..) | ast::ExprKind::Ret(..) + | ast::ExprKind::Become(..) | ast::ExprKind::Yeet(..) | ast::ExprKind::FormatArgs(..) | ast::ExprKind::Struct(..) From b2c7ce89089437a004682cede27aa59a8726eeeb Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Fri, 16 Jun 2023 05:59:42 +0000 Subject: [PATCH 235/310] s/Clause/ClauseKind --- clippy_lints/src/dereference.rs | 8 ++++---- clippy_lints/src/derive.rs | 6 +++--- clippy_lints/src/future_not_send.rs | 4 ++-- clippy_lints/src/methods/needless_collect.rs | 4 ++-- clippy_lints/src/methods/unnecessary_to_owned.rs | 8 ++++---- clippy_lints/src/needless_pass_by_value.rs | 2 +- clippy_lints/src/ptr.rs | 4 ++-- clippy_lints/src/unit_return_expecting_ord.rs | 6 +++--- clippy_utils/src/eager_or_lazy.rs | 2 +- clippy_utils/src/qualify_min_const_fn.rs | 14 +++++++------- clippy_utils/src/ty.rs | 16 ++++++++-------- 11 files changed, 37 insertions(+), 37 deletions(-) diff --git a/clippy_lints/src/dereference.rs b/clippy_lints/src/dereference.rs index dbaf6aaa853..ee6aef71980 100644 --- a/clippy_lints/src/dereference.rs +++ b/clippy_lints/src/dereference.rs @@ -26,7 +26,7 @@ use rustc_lint::{LateContext, LateLintPass}; use rustc_middle::mir::{Rvalue, StatementKind}; use rustc_middle::ty::adjustment::{Adjust, Adjustment, AutoBorrow, AutoBorrowMutability}; use rustc_middle::ty::{ - self, Binder, BoundVariableKind, Clause, EarlyBinder, FnSig, GenericArgKind, List, ParamEnv, ParamTy, + self, Binder, BoundVariableKind, ClauseKind, EarlyBinder, FnSig, GenericArgKind, List, ParamEnv, ParamTy, PredicateKind, ProjectionPredicate, Ty, TyCtxt, TypeVisitableExt, TypeckResults, }; use rustc_session::{declare_tool_lint, impl_lint_pass}; @@ -1133,7 +1133,7 @@ fn needless_borrow_impl_arg_position<'tcx>( let projection_predicates = predicates .iter() .filter_map(|predicate| { - if let PredicateKind::Clause(Clause::Projection(projection_predicate)) = predicate.kind().skip_binder() { + if let PredicateKind::Clause(ClauseKind::Projection(projection_predicate)) = predicate.kind().skip_binder() { Some(projection_predicate) } else { None @@ -1147,7 +1147,7 @@ fn needless_borrow_impl_arg_position<'tcx>( if predicates .iter() .filter_map(|predicate| { - if let PredicateKind::Clause(Clause::Trait(trait_predicate)) = predicate.kind().skip_binder() + if let PredicateKind::Clause(ClauseKind::Trait(trait_predicate)) = predicate.kind().skip_binder() && trait_predicate.trait_ref.self_ty() == param_ty.to_ty(cx.tcx) { Some(trait_predicate.trait_ref.def_id) @@ -1209,7 +1209,7 @@ fn needless_borrow_impl_arg_position<'tcx>( } predicates.iter().all(|predicate| { - if let PredicateKind::Clause(Clause::Trait(trait_predicate)) = predicate.kind().skip_binder() + if let PredicateKind::Clause(ClauseKind::Trait(trait_predicate)) = predicate.kind().skip_binder() && cx.tcx.is_diagnostic_item(sym::IntoIterator, trait_predicate.trait_ref.def_id) && let ty::Param(param_ty) = trait_predicate.self_ty().kind() && let GenericArgKind::Type(ty) = substs_with_referent_ty[param_ty.index as usize].unpack() diff --git a/clippy_lints/src/derive.rs b/clippy_lints/src/derive.rs index 8f5d319cd4f..8d84e756ff8 100644 --- a/clippy_lints/src/derive.rs +++ b/clippy_lints/src/derive.rs @@ -14,7 +14,7 @@ use rustc_lint::{LateContext, LateLintPass}; use rustc_middle::hir::nested_filter; use rustc_middle::traits::Reveal; use rustc_middle::ty::{ - self, Binder, BoundConstness, Clause, GenericArgKind, GenericParamDefKind, ImplPolarity, ParamEnv, PredicateKind, + self, Binder, BoundConstness, ClauseKind, GenericArgKind, GenericParamDefKind, ImplPolarity, ParamEnv, PredicateKind, TraitPredicate, Ty, TyCtxt, }; use rustc_session::{declare_lint_pass, declare_tool_lint}; @@ -503,7 +503,7 @@ fn param_env_for_derived_eq(tcx: TyCtxt<'_>, did: DefId, eq_trait_id: DefId) -> let ty_predicates = tcx.predicates_of(did).predicates; for (p, _) in ty_predicates { - if let PredicateKind::Clause(Clause::Trait(p)) = p.kind().skip_binder() + if let PredicateKind::Clause(ClauseKind::Trait(p)) = p.kind().skip_binder() && p.trait_ref.def_id == eq_trait_id && let ty::Param(self_ty) = p.trait_ref.self_ty().kind() && p.constness == BoundConstness::NotConst @@ -516,7 +516,7 @@ fn param_env_for_derived_eq(tcx: TyCtxt<'_>, did: DefId, eq_trait_id: DefId) -> ParamEnv::new( 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 { + tcx.mk_predicate(Binder::dummy(PredicateKind::Clause(ClauseKind::Trait(TraitPredicate { trait_ref: ty::TraitRef::new(tcx, eq_trait_id, [tcx.mk_param_from_def(param)]), constness: BoundConstness::NotConst, polarity: ImplPolarity::Positive, diff --git a/clippy_lints/src/future_not_send.rs b/clippy_lints/src/future_not_send.rs index d1314795f58..a391b76910a 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, PredicateKind}; +use rustc_middle::ty::{self, AliasTy, ClauseKind, PredicateKind}; use rustc_session::{declare_lint_pass, declare_tool_lint}; use rustc_span::def_id::LocalDefId; use rustc_span::{sym, Span}; @@ -93,7 +93,7 @@ impl<'tcx> LateLintPass<'tcx> for FutureNotSend { infcx .err_ctxt() .maybe_note_obligation_cause_for_async_await(db, &obligation); - if let PredicateKind::Clause(Clause::Trait(trait_pred)) = + if let PredicateKind::Clause(ClauseKind::Trait(trait_pred)) = obligation.predicate.kind().skip_binder() { db.note(format!( diff --git a/clippy_lints/src/methods/needless_collect.rs b/clippy_lints/src/methods/needless_collect.rs index 99f810c27cf..cf85d3174db 100644 --- a/clippy_lints/src/methods/needless_collect.rs +++ b/clippy_lints/src/methods/needless_collect.rs @@ -16,7 +16,7 @@ use rustc_hir::{ }; use rustc_lint::LateContext; use rustc_middle::hir::nested_filter; -use rustc_middle::ty::{self, AssocKind, Clause, EarlyBinder, GenericArg, GenericArgKind, PredicateKind, Ty}; +use rustc_middle::ty::{self, AssocKind, ClauseKind, EarlyBinder, GenericArg, GenericArgKind, PredicateKind, Ty}; use rustc_span::symbol::Ident; use rustc_span::{sym, Span, Symbol}; @@ -175,7 +175,7 @@ fn check_collect_into_intoiterator<'tcx>( .caller_bounds() .into_iter() .filter_map(|p| { - if let PredicateKind::Clause(Clause::Trait(t)) = p.kind().skip_binder() + if let PredicateKind::Clause(ClauseKind::Trait(t)) = p.kind().skip_binder() && cx.tcx.is_diagnostic_item(sym::IntoIterator,t.trait_ref.def_id) { Some(t.self_ty()) } else { diff --git a/clippy_lints/src/methods/unnecessary_to_owned.rs b/clippy_lints/src/methods/unnecessary_to_owned.rs index 309d2157b76..06fa95cd657 100644 --- a/clippy_lints/src/methods/unnecessary_to_owned.rs +++ b/clippy_lints/src/methods/unnecessary_to_owned.rs @@ -14,7 +14,7 @@ use rustc_lint::LateContext; use rustc_middle::mir::Mutability; use rustc_middle::ty::adjustment::{Adjust, Adjustment, OverloadedDeref}; use rustc_middle::ty::subst::{GenericArg, GenericArgKind, SubstsRef}; -use rustc_middle::ty::{self, Clause, EarlyBinder, ParamTy, PredicateKind, ProjectionPredicate, TraitPredicate, Ty}; +use rustc_middle::ty::{self, ClauseKind, EarlyBinder, ParamTy, PredicateKind, ProjectionPredicate, TraitPredicate, Ty}; use rustc_span::{sym, Symbol}; use rustc_trait_selection::traits::{query::evaluate_obligation::InferCtxtExt as _, Obligation, ObligationCause}; @@ -345,12 +345,12 @@ fn get_input_traits_and_projections<'tcx>( let mut projection_predicates = Vec::new(); for predicate in cx.tcx.param_env(callee_def_id).caller_bounds() { match predicate.kind().skip_binder() { - PredicateKind::Clause(Clause::Trait(trait_predicate)) => { + PredicateKind::Clause(ClauseKind::Trait(trait_predicate)) => { if trait_predicate.trait_ref.self_ty() == input { trait_predicates.push(trait_predicate); } }, - PredicateKind::Clause(Clause::Projection(projection_predicate)) => { + PredicateKind::Clause(ClauseKind::Projection(projection_predicate)) => { if projection_predicate.projection_ty.self_ty() == input { projection_predicates.push(projection_predicate); } @@ -407,7 +407,7 @@ fn can_change_type<'a>(cx: &LateContext<'a>, mut expr: &'a Expr<'a>, mut ty: Ty< let mut trait_predicates = cx.tcx.param_env(callee_def_id) .caller_bounds().iter().filter(|predicate| { - if let PredicateKind::Clause(Clause::Trait(trait_predicate)) + if let PredicateKind::Clause(ClauseKind::Trait(trait_predicate)) = predicate.kind().skip_binder() && trait_predicate.trait_ref.self_ty() == *param_ty { diff --git a/clippy_lints/src/needless_pass_by_value.rs b/clippy_lints/src/needless_pass_by_value.rs index 7d53fe65658..3773975e955 100644 --- a/clippy_lints/src/needless_pass_by_value.rs +++ b/clippy_lints/src/needless_pass_by_value.rs @@ -126,7 +126,7 @@ impl<'tcx> LateLintPass<'tcx> for NeedlessPassByValue { .filter_map(|pred| { // Note that we do not want to deal with qualified predicates here. match pred.kind().no_bound_vars() { - Some(ty::PredicateKind::Clause(ty::Clause::Trait(pred))) if pred.def_id() != sized_trait => { + Some(ty::PredicateKind::Clause(ty::ClauseKind::Trait(pred))) if pred.def_id() != sized_trait => { Some(pred) }, _ => None, diff --git a/clippy_lints/src/ptr.rs b/clippy_lints/src/ptr.rs index fc550936165..b8911f10907 100644 --- a/clippy_lints/src/ptr.rs +++ b/clippy_lints/src/ptr.rs @@ -19,7 +19,7 @@ use rustc_infer::infer::TyCtxtInferExt; use rustc_infer::traits::{Obligation, ObligationCause}; use rustc_lint::{LateContext, LateLintPass}; use rustc_middle::hir::nested_filter; -use rustc_middle::ty::{self, Binder, Clause, ExistentialPredicate, List, PredicateKind, Ty}; +use rustc_middle::ty::{self, Binder, ClauseKind, ExistentialPredicate, List, PredicateKind, Ty}; use rustc_session::{declare_lint_pass, declare_tool_lint}; use rustc_span::source_map::Span; use rustc_span::sym; @@ -697,7 +697,7 @@ fn matches_preds<'tcx>( ObligationCause::dummy(), cx.param_env, cx.tcx - .mk_predicate(Binder::dummy(PredicateKind::Clause(Clause::Projection( + .mk_predicate(Binder::dummy(PredicateKind::Clause(ClauseKind::Projection( p.with_self_ty(cx.tcx, ty), )))), )), diff --git a/clippy_lints/src/unit_return_expecting_ord.rs b/clippy_lints/src/unit_return_expecting_ord.rs index 289ca4e9bed..a375e5d5b4c 100644 --- a/clippy_lints/src/unit_return_expecting_ord.rs +++ b/clippy_lints/src/unit_return_expecting_ord.rs @@ -4,7 +4,7 @@ use rustc_hir::def_id::DefId; use rustc_hir::{Closure, Expr, ExprKind, StmtKind}; use rustc_lint::{LateContext, LateLintPass}; use rustc_middle::ty; -use rustc_middle::ty::{Clause, GenericPredicates, PredicateKind, ProjectionPredicate, TraitPredicate}; +use rustc_middle::ty::{ClauseKind, GenericPredicates, PredicateKind, ProjectionPredicate, TraitPredicate}; use rustc_session::{declare_lint_pass, declare_tool_lint}; use rustc_span::{sym, BytePos, Span}; @@ -45,7 +45,7 @@ fn get_trait_predicates_for_trait_id<'tcx>( let mut preds = Vec::new(); for (pred, _) in generics.predicates { if_chain! { - if let PredicateKind::Clause(Clause::Trait(poly_trait_pred)) = pred.kind().skip_binder(); + if let PredicateKind::Clause(ClauseKind::Trait(poly_trait_pred)) = pred.kind().skip_binder(); let trait_pred = cx.tcx.erase_late_bound_regions(pred.kind().rebind(poly_trait_pred)); if let Some(trait_def_id) = trait_id; if trait_def_id == trait_pred.trait_ref.def_id; @@ -63,7 +63,7 @@ fn get_projection_pred<'tcx>( trait_pred: TraitPredicate<'tcx>, ) -> Option> { generics.predicates.iter().find_map(|(proj_pred, _)| { - if let ty::PredicateKind::Clause(Clause::Projection(pred)) = proj_pred.kind().skip_binder() { + if let ty::PredicateKind::Clause(ClauseKind::Projection(pred)) = proj_pred.kind().skip_binder() { let projection_pred = cx.tcx.erase_late_bound_regions(proj_pred.kind().rebind(pred)); if projection_pred.projection_ty.substs == trait_pred.trait_ref.substs { return Some(projection_pred); diff --git a/clippy_utils/src/eager_or_lazy.rs b/clippy_utils/src/eager_or_lazy.rs index 3df40942e7b..941df3318ae 100644 --- a/clippy_utils/src/eager_or_lazy.rs +++ b/clippy_utils/src/eager_or_lazy.rs @@ -73,7 +73,7 @@ fn fn_eagerness(cx: &LateContext<'_>, fn_id: DefId, name: Symbol, have_one_arg: .flat_map(|v| v.fields.iter()) .any(|x| matches!(cx.tcx.type_of(x.did).subst_identity().peel_refs().kind(), ty::Param(_))) && all_predicates_of(cx.tcx, fn_id).all(|(pred, _)| match pred.kind().skip_binder() { - PredicateKind::Clause(ty::Clause::Trait(pred)) => cx.tcx.trait_def(pred.trait_ref.def_id).is_marker, + PredicateKind::Clause(ty::ClauseKind::Trait(pred)) => cx.tcx.trait_def(pred.trait_ref.def_id).is_marker, _ => true, }) && subs.types().all(|x| matches!(x.peel_refs().kind(), ty::Param(_))) diff --git a/clippy_utils/src/qualify_min_const_fn.rs b/clippy_utils/src/qualify_min_const_fn.rs index 860a489494c..aea79984c7a 100644 --- a/clippy_utils/src/qualify_min_const_fn.rs +++ b/clippy_utils/src/qualify_min_const_fn.rs @@ -27,14 +27,14 @@ pub fn is_min_const_fn<'tcx>(tcx: TyCtxt<'tcx>, body: &Body<'tcx>, msrv: &Msrv) for (predicate, _) in predicates.predicates { match predicate.kind().skip_binder() { ty::PredicateKind::Clause( - ty::Clause::RegionOutlives(_) - | ty::Clause::TypeOutlives(_) - | ty::Clause::Projection(_) - | ty::Clause::Trait(..) - | ty::Clause::ConstArgHasType(..), + ty::ClauseKind::RegionOutlives(_) + | ty::ClauseKind::TypeOutlives(_) + | ty::ClauseKind::Projection(_) + | ty::ClauseKind::Trait(..) + | ty::ClauseKind::ConstArgHasType(..), ) - | ty::PredicateKind::Clause(ty::Clause::WellFormed(_)) - | ty::PredicateKind::Clause(ty::Clause::ConstEvaluatable(..)) + | ty::PredicateKind::Clause(ty::ClauseKind::WellFormed(_)) + | ty::PredicateKind::Clause(ty::ClauseKind::ConstEvaluatable(..)) | ty::PredicateKind::ConstEquate(..) | ty::PredicateKind::TypeWellFormedFromEnv(..) => continue, ty::PredicateKind::AliasRelate(..) => panic!("alias relate predicate on function: {predicate:#?}"), diff --git a/clippy_utils/src/ty.rs b/clippy_utils/src/ty.rs index 7b4ed77e8ed..12f18614d71 100644 --- a/clippy_utils/src/ty.rs +++ b/clippy_utils/src/ty.rs @@ -94,7 +94,7 @@ pub fn contains_ty_adt_constructor_opaque<'tcx>(cx: &LateContext<'tcx>, ty: Ty<' match predicate.kind().skip_binder() { // For `impl Trait`, it will register a predicate of `T: Trait`, so we go through // and check substitutions to find `U`. - ty::PredicateKind::Clause(ty::Clause::Trait(trait_predicate)) => { + ty::PredicateKind::Clause(ty::ClauseKind::Trait(trait_predicate)) => { if trait_predicate .trait_ref .substs @@ -107,7 +107,7 @@ pub fn contains_ty_adt_constructor_opaque<'tcx>(cx: &LateContext<'tcx>, ty: Ty<' }, // For `impl Trait`, it will register a predicate of `::Assoc = U`, // so we check the term for `U`. - ty::PredicateKind::Clause(ty::Clause::Projection(projection_predicate)) => { + ty::PredicateKind::Clause(ty::ClauseKind::Projection(projection_predicate)) => { if let ty::TermKind::Ty(ty) = projection_predicate.term.unpack() { if contains_ty_adt_constructor_opaque_inner(cx, ty, needle, seen) { return true; @@ -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.explicit_item_bounds(def_id).skip_binder() { - if let ty::PredicateKind::Clause(ty::Clause::Trait(trait_predicate)) = predicate.kind().skip_binder() { + if let ty::PredicateKind::Clause(ty::ClauseKind::Trait(trait_predicate)) = predicate.kind().skip_binder() { if cx.tcx.has_attr(trait_predicate.trait_ref.def_id, sym::must_use) { return true; } @@ -707,7 +707,7 @@ fn sig_from_bounds<'tcx>( for pred in predicates { match pred.kind().skip_binder() { - PredicateKind::Clause(ty::Clause::Trait(p)) + PredicateKind::Clause(ty::ClauseKind::Trait(p)) if (lang_items.fn_trait() == Some(p.def_id()) || lang_items.fn_mut_trait() == Some(p.def_id()) || lang_items.fn_once_trait() == Some(p.def_id())) @@ -720,7 +720,7 @@ fn sig_from_bounds<'tcx>( } inputs = Some(i); }, - PredicateKind::Clause(ty::Clause::Projection(p)) + PredicateKind::Clause(ty::ClauseKind::Projection(p)) if Some(p.projection_ty.def_id) == lang_items.fn_once_output() && p.projection_ty.self_ty() == ty => { if output.is_some() { @@ -747,7 +747,7 @@ fn sig_for_projection<'tcx>(cx: &LateContext<'tcx>, ty: AliasTy<'tcx>) -> Option .subst_iter_copied(cx.tcx, ty.substs) { match pred.kind().skip_binder() { - PredicateKind::Clause(ty::Clause::Trait(p)) + PredicateKind::Clause(ty::ClauseKind::Trait(p)) if (lang_items.fn_trait() == Some(p.def_id()) || lang_items.fn_mut_trait() == Some(p.def_id()) || lang_items.fn_once_trait() == Some(p.def_id())) => @@ -760,7 +760,7 @@ fn sig_for_projection<'tcx>(cx: &LateContext<'tcx>, ty: AliasTy<'tcx>) -> Option } inputs = Some(i); }, - PredicateKind::Clause(ty::Clause::Projection(p)) + PredicateKind::Clause(ty::ClauseKind::Projection(p)) if Some(p.projection_ty.def_id) == lang_items.fn_once_output() => { if output.is_some() { @@ -950,7 +950,7 @@ pub fn ty_is_fn_once_param<'tcx>(tcx: TyCtxt<'_>, ty: Ty<'tcx>, predicates: &'tc predicates .iter() .try_fold(false, |found, p| { - if let PredicateKind::Clause(ty::Clause::Trait(p)) = p.kind().skip_binder() + if let PredicateKind::Clause(ty::ClauseKind::Trait(p)) = p.kind().skip_binder() && let ty::Param(self_ty) = p.trait_ref.self_ty().kind() && ty.index == self_ty.index { From d7e723441ed8747e6e280808abd0e99da40d2100 Mon Sep 17 00:00:00 2001 From: y21 <30553356+y21@users.noreply.github.com> Date: Mon, 19 Jun 2023 17:18:27 +0200 Subject: [PATCH 236/310] [`single_match`]: don't lint if block contains comments --- clippy_lints/src/matches/single_match.rs | 24 ++++++++++++++++++---- tests/ui/single_match.fixed | 26 ++++++++++++++++++++++++ tests/ui/single_match.rs | 26 ++++++++++++++++++++++++ 3 files changed, 72 insertions(+), 4 deletions(-) diff --git a/clippy_lints/src/matches/single_match.rs b/clippy_lints/src/matches/single_match.rs index ad47c13896c..35627d6c649 100644 --- a/clippy_lints/src/matches/single_match.rs +++ b/clippy_lints/src/matches/single_match.rs @@ -1,5 +1,5 @@ use clippy_utils::diagnostics::span_lint_and_sugg; -use clippy_utils::source::{expr_block, snippet}; +use clippy_utils::source::{expr_block, get_source_text, snippet}; use clippy_utils::ty::{implements_trait, is_type_diagnostic_item, peel_mid_ty_refs}; use clippy_utils::{is_lint_allowed, is_unit_expr, is_wild, peel_blocks, peel_hir_pat_refs, peel_n_hir_expr_refs}; use core::cmp::max; @@ -7,10 +7,26 @@ use rustc_errors::Applicability; use rustc_hir::{Arm, BindingAnnotation, Block, Expr, ExprKind, Pat, PatKind}; use rustc_lint::LateContext; use rustc_middle::ty::{self, Ty}; -use rustc_span::sym; +use rustc_span::{sym, Span}; use super::{MATCH_BOOL, SINGLE_MATCH, SINGLE_MATCH_ELSE}; +/// Checks if there are comments contained within a span. +/// This is a very "naive" check, as it just looks for the literal characters // and /* in the +/// source text. This won't be accurate if there are potentially expressions contained within the +/// span, e.g. a string literal `"//"`, but we know that this isn't the case for empty +/// match arms. +fn empty_arm_has_comment(cx: &LateContext<'_>, span: Span) -> bool { + if let Some(ff) = get_source_text(cx, span) + && let Some(text) = ff.as_str() + { + text.as_bytes().windows(2) + .any(|w| w == b"//" || w == b"/*") + } else { + false + } +} + #[rustfmt::skip] pub(crate) fn check(cx: &LateContext<'_>, ex: &Expr<'_>, arms: &[Arm<'_>], expr: &Expr<'_>) { if arms.len() == 2 && arms[0].guard.is_none() && arms[1].guard.is_none() { @@ -25,7 +41,7 @@ pub(crate) fn check(cx: &LateContext<'_>, ex: &Expr<'_>, arms: &[Arm<'_>], expr: return; } let els = arms[1].body; - let els = if is_unit_expr(peel_blocks(els)) { + let els = if is_unit_expr(peel_blocks(els)) && !empty_arm_has_comment(cx, els.span) { None } else if let ExprKind::Block(Block { stmts, expr: block_expr, .. }, _) = els.kind { if stmts.len() == 1 && block_expr.is_none() || stmts.is_empty() && block_expr.is_some() { @@ -35,7 +51,7 @@ pub(crate) fn check(cx: &LateContext<'_>, ex: &Expr<'_>, arms: &[Arm<'_>], expr: // block with 2+ statements or 1 expr and 1+ statement Some(els) } else { - // not a block, don't lint + // not a block or an emtpy block w/ comments, don't lint return; }; diff --git a/tests/ui/single_match.fixed b/tests/ui/single_match.fixed index a54e658bf23..0da59a53320 100644 --- a/tests/ui/single_match.fixed +++ b/tests/ui/single_match.fixed @@ -212,3 +212,29 @@ fn issue_10808(bar: Option) { } } } + +mod issue8634 { + struct SomeError(i32, i32); + + fn foo(x: Result) { + match x { + Ok(y) => { + println!("Yay! {y}"); + }, + Err(()) => { + // Ignore this error because blah blah blah. + }, + } + } + + fn bar(x: Result) { + match x { + Ok(y) => { + println!("Yay! {y}"); + }, + Err(_) => { + // TODO: Process the error properly. + }, + } + } +} diff --git a/tests/ui/single_match.rs b/tests/ui/single_match.rs index f296c6c4d1c..7afadececbf 100644 --- a/tests/ui/single_match.rs +++ b/tests/ui/single_match.rs @@ -270,3 +270,29 @@ fn issue_10808(bar: Option) { _ => {}, } } + +mod issue8634 { + struct SomeError(i32, i32); + + fn foo(x: Result) { + match x { + Ok(y) => { + println!("Yay! {y}"); + }, + Err(()) => { + // Ignore this error because blah blah blah. + }, + } + } + + fn bar(x: Result) { + match x { + Ok(y) => { + println!("Yay! {y}"); + }, + Err(_) => { + // TODO: Process the error properly. + }, + } + } +} From 2e856fa99bc2c7f03c65fd89e44ef22509708e0d Mon Sep 17 00:00:00 2001 From: y21 <30553356+y21@users.noreply.github.com> Date: Mon, 19 Jun 2023 20:07:31 +0200 Subject: [PATCH 237/310] add test for block comment and add note to description --- clippy_lints/src/matches/mod.rs | 5 +++++ tests/ui/single_match.fixed | 14 ++++++++++++++ tests/ui/single_match.rs | 14 ++++++++++++++ 3 files changed, 33 insertions(+) diff --git a/clippy_lints/src/matches/mod.rs b/clippy_lints/src/matches/mod.rs index 3fbd0867ea9..00fa3eb9bfe 100644 --- a/clippy_lints/src/matches/mod.rs +++ b/clippy_lints/src/matches/mod.rs @@ -38,6 +38,11 @@ declare_clippy_lint! { /// Checks for matches with a single arm where an `if let` /// will usually suffice. /// + /// This intentionally does not lint if there are comments + /// inside of the other arm, so as to allow the user to document + /// why having another explicit pattern with an empty body is necessary, + /// or because the comments need to be preserved for other reasons. + /// /// ### Why is this bad? /// Just readability – `if let` nests less than a `match`. /// diff --git a/tests/ui/single_match.fixed b/tests/ui/single_match.fixed index 0da59a53320..e7b1fd6a85f 100644 --- a/tests/ui/single_match.fixed +++ b/tests/ui/single_match.fixed @@ -237,4 +237,18 @@ mod issue8634 { }, } } + + fn block_comment(x: Result) { + match x { + Ok(y) => { + println!("Yay! {y}"); + }, + Err(_) => { + /* + let's make sure that this also + does not lint block comments. + */ + }, + } + } } diff --git a/tests/ui/single_match.rs b/tests/ui/single_match.rs index 7afadececbf..1515a7053e5 100644 --- a/tests/ui/single_match.rs +++ b/tests/ui/single_match.rs @@ -295,4 +295,18 @@ mod issue8634 { }, } } + + fn block_comment(x: Result) { + match x { + Ok(y) => { + println!("Yay! {y}"); + }, + Err(_) => { + /* + let's make sure that this also + does not lint block comments. + */ + }, + } + } } From 62c9e0b87d5cb08f2c7e8ab00cbb8dcf64324b37 Mon Sep 17 00:00:00 2001 From: blyxyas Date: Mon, 19 Jun 2023 20:50:24 +0200 Subject: [PATCH 238/310] Ignore in-proc-macros items --- clippy_lints/src/items_after_test_module.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/clippy_lints/src/items_after_test_module.rs b/clippy_lints/src/items_after_test_module.rs index b992d689aa9..40378ee8205 100644 --- a/clippy_lints/src/items_after_test_module.rs +++ b/clippy_lints/src/items_after_test_module.rs @@ -1,4 +1,4 @@ -use clippy_utils::{diagnostics::span_lint_and_help, is_in_cfg_test}; +use clippy_utils::{diagnostics::span_lint_and_help, is_from_proc_macro, is_in_cfg_test}; use rustc_hir::{HirId, ItemId, ItemKind, Mod}; use rustc_lint::{LateContext, LateLintPass, LintContext}; use rustc_middle::lint::in_external_macro; @@ -59,6 +59,7 @@ impl LateLintPass<'_> for ItemsAfterTestModule { 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); + if !is_from_proc_macro(cx, item); 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"); From cc2e49f6956bba3131f7c695042fdc4a1aefb179 Mon Sep 17 00:00:00 2001 From: Centri3 <114838443+Centri3@users.noreply.github.com> Date: Sun, 18 Jun 2023 14:38:22 -0500 Subject: [PATCH 239/310] allow safety comment above attributes --- CHANGELOG.md | 1 + book/src/lint_configuration.md | 10 +++ clippy_lints/src/lib.rs | 2 + .../src/undocumented_unsafe_blocks.rs | 81 ++++++++++++++++--- clippy_lints/src/utils/conf.rs | 4 + .../toml_unknown_key/conf_unknown_key.stderr | 2 + .../undocumented_unsafe_blocks/clippy.toml | 1 + .../undocumented_unsafe_blocks.rs | 35 +++++++- .../undocumented_unsafe_blocks.stderr | 74 ++++++++--------- 9 files changed, 162 insertions(+), 48 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 3eaa0d199fd..f7295ecf42c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5384,4 +5384,5 @@ Released 2018-09-13 [`allowed-idents-below-min-chars`]: https://doc.rust-lang.org/clippy/lint_configuration.html#allowed-idents-below-min-chars [`min-ident-chars-threshold`]: https://doc.rust-lang.org/clippy/lint_configuration.html#min-ident-chars-threshold [`accept-comment-above-statement`]: https://doc.rust-lang.org/clippy/lint_configuration.html#accept-comment-above-statement +[`accept-comment-above-attributes`]: https://doc.rust-lang.org/clippy/lint_configuration.html#accept-comment-above-attributes diff --git a/book/src/lint_configuration.md b/book/src/lint_configuration.md index 78a5f9da461..ccb24a536af 100644 --- a/book/src/lint_configuration.md +++ b/book/src/lint_configuration.md @@ -705,3 +705,13 @@ Whether to accept a safety comment to be placed above the statement containing t * [`undocumented_unsafe_blocks`](https://rust-lang.github.io/rust-clippy/master/index.html#undocumented_unsafe_blocks) +## `accept-comment-above-attributes` +Whether to accept a safety comment to be placed above the attributes for the `unsafe` block + +**Default Value:** `false` (`bool`) + +--- +**Affected lints:** +* [`undocumented_unsafe_blocks`](https://rust-lang.github.io/rust-clippy/master/index.html#undocumented_unsafe_blocks) + + diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index 6ea329a9542..a0ada107fbf 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -930,9 +930,11 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: )) }); let accept_comment_above_statement = conf.accept_comment_above_statement; + let accept_comment_above_attributes = conf.accept_comment_above_attributes; store.register_late_pass(move |_| { Box::new(undocumented_unsafe_blocks::UndocumentedUnsafeBlocks::new( accept_comment_above_statement, + accept_comment_above_attributes, )) }); let allow_mixed_uninlined = conf.allow_mixed_uninlined_format_args; diff --git a/clippy_lints/src/undocumented_unsafe_blocks.rs b/clippy_lints/src/undocumented_unsafe_blocks.rs index 1676c767a34..a9deee96784 100644 --- a/clippy_lints/src/undocumented_unsafe_blocks.rs +++ b/clippy_lints/src/undocumented_unsafe_blocks.rs @@ -95,12 +95,14 @@ declare_clippy_lint! { #[derive(Copy, Clone)] pub struct UndocumentedUnsafeBlocks { accept_comment_above_statement: bool, + accept_comment_above_attributes: bool, } impl UndocumentedUnsafeBlocks { - pub fn new(accept_comment_above_statement: bool) -> Self { + pub fn new(accept_comment_above_statement: bool, accept_comment_above_attributes: bool) -> Self { Self { accept_comment_above_statement, + accept_comment_above_attributes, } } } @@ -114,7 +116,12 @@ impl<'tcx> LateLintPass<'tcx> for UndocumentedUnsafeBlocks { && !is_lint_allowed(cx, UNDOCUMENTED_UNSAFE_BLOCKS, block.hir_id) && !is_unsafe_from_proc_macro(cx, block.span) && !block_has_safety_comment(cx, block.span) - && !block_parents_have_safety_comment(self.accept_comment_above_statement, cx, block.hir_id) + && !block_parents_have_safety_comment( + self.accept_comment_above_statement, + self.accept_comment_above_attributes, + cx, + block.hir_id, + ) { let source_map = cx.tcx.sess.source_map(); let span = if source_map.is_multiline(block.span) { @@ -328,6 +335,7 @@ fn is_unsafe_from_proc_macro(cx: &LateContext<'_>, span: Span) -> bool { // has a safety comment fn block_parents_have_safety_comment( accept_comment_above_statement: bool, + accept_comment_above_attributes: bool, cx: &LateContext<'_>, id: hir::HirId, ) -> bool { @@ -343,33 +351,77 @@ fn block_parents_have_safety_comment( }), ) = get_parent_node(cx.tcx, expr.hir_id) { + let hir_id = match get_parent_node(cx.tcx, expr.hir_id) { + Some(Node::Local(hir::Local { hir_id, .. })) => *hir_id, + Some(Node::Item(hir::Item { owner_id, .. })) => { + cx.tcx.hir().local_def_id_to_hir_id(owner_id.def_id) + }, + _ => unreachable!(), + }; + // if unsafe block is part of a let/const/static statement, // and accept_comment_above_statement is set to true // we accept the safety comment in the line the precedes this statement. - accept_comment_above_statement && span_in_body_has_safety_comment(cx, *span) + accept_comment_above_statement + && span_with_attrs_in_body_has_safety_comment( + cx, + *span, + hir_id, + accept_comment_above_attributes, + ) } else { - !is_branchy(expr) && span_in_body_has_safety_comment(cx, expr.span) + !is_branchy(expr) + && span_with_attrs_in_body_has_safety_comment( + cx, + expr.span, + expr.hir_id, + accept_comment_above_attributes, + ) } }, Node::Stmt(hir::Stmt { kind: - hir::StmtKind::Local(hir::Local { span, .. }) - | hir::StmtKind::Expr(hir::Expr { span, .. }) - | hir::StmtKind::Semi(hir::Expr { span, .. }), + hir::StmtKind::Local(hir::Local { span, hir_id, .. }) + | hir::StmtKind::Expr(hir::Expr { span, hir_id, .. }) + | hir::StmtKind::Semi(hir::Expr { span, hir_id, .. }), .. }) - | Node::Local(hir::Local { span, .. }) - | Node::Item(hir::Item { + | Node::Local(hir::Local { span, hir_id, .. }) => { + span_with_attrs_in_body_has_safety_comment(cx, *span, *hir_id, accept_comment_above_attributes) + }, + Node::Item(hir::Item { kind: hir::ItemKind::Const(..) | ItemKind::Static(..), span, + owner_id, .. - }) => span_in_body_has_safety_comment(cx, *span), + }) => span_with_attrs_in_body_has_safety_comment( + cx, + *span, + cx.tcx.hir().local_def_id_to_hir_id(owner_id.def_id), + accept_comment_above_attributes, + ), _ => false, }; } false } +/// Extends `span` to also include its attributes, then checks if that span has a safety comment. +fn span_with_attrs_in_body_has_safety_comment( + cx: &LateContext<'_>, + span: Span, + hir_id: HirId, + accept_comment_above_attributes: bool, +) -> bool { + let span = if accept_comment_above_attributes { + include_attrs_in_span(cx, hir_id, span) + } else { + span + }; + + span_in_body_has_safety_comment(cx, span) +} + /// Checks if an expression is "branchy", e.g. loop, match/if/etc. fn is_branchy(expr: &hir::Expr<'_>) -> bool { matches!( @@ -394,6 +446,15 @@ fn block_has_safety_comment(cx: &LateContext<'_>, span: Span) -> bool { ) || span_in_body_has_safety_comment(cx, span) } +fn include_attrs_in_span(cx: &LateContext<'_>, hir_id: HirId, span: Span) -> Span { + span.to(cx + .tcx + .hir() + .attrs(hir_id) + .iter() + .fold(span, |acc, attr| acc.to(attr.span))) +} + enum HasSafetyComment { Yes(BytePos), No, diff --git a/clippy_lints/src/utils/conf.rs b/clippy_lints/src/utils/conf.rs index e8c8d478ffc..b04b3177e98 100644 --- a/clippy_lints/src/utils/conf.rs +++ b/clippy_lints/src/utils/conf.rs @@ -542,6 +542,10 @@ define_Conf! { /// /// Whether to accept a safety comment to be placed above the statement containing the `unsafe` block (accept_comment_above_statement: bool = false), + /// Lint: UNDOCUMENTED_UNSAFE_BLOCKS. + /// + /// Whether to accept a safety comment to be placed above the attributes for the `unsafe` block + (accept_comment_above_attributes: bool = false), } /// Search for the configuration file. 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 db2071ecaaf..475b15a2414 100644 --- a/tests/ui-toml/toml_unknown_key/conf_unknown_key.stderr +++ b/tests/ui-toml/toml_unknown_key/conf_unknown_key.stderr @@ -1,4 +1,5 @@ error: error reading Clippy's configuration file: unknown field `foobar`, expected one of + accept-comment-above-attributes accept-comment-above-statement allow-dbg-in-tests allow-expect-in-tests @@ -66,6 +67,7 @@ LL | foobar = 42 | ^^^^^^ error: error reading Clippy's configuration file: unknown field `barfoo`, expected one of + accept-comment-above-attributes accept-comment-above-statement allow-dbg-in-tests allow-expect-in-tests diff --git a/tests/ui-toml/undocumented_unsafe_blocks/clippy.toml b/tests/ui-toml/undocumented_unsafe_blocks/clippy.toml index 1c2e7aeaff9..e6dbb3d3784 100644 --- a/tests/ui-toml/undocumented_unsafe_blocks/clippy.toml +++ b/tests/ui-toml/undocumented_unsafe_blocks/clippy.toml @@ -1 +1,2 @@ accept-comment-above-statement = true +accept-comment-above-attributes = true diff --git a/tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs b/tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs index 533f90483e5..c0976f0d600 100644 --- a/tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs +++ b/tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs @@ -1,7 +1,8 @@ //@aux-build:proc_macro_unsafe.rs #![warn(clippy::undocumented_unsafe_blocks, clippy::unnecessary_safety_comment)] -#![allow(clippy::let_unit_value, clippy::missing_safety_doc)] +#![allow(deref_nullptr, clippy::let_unit_value, clippy::missing_safety_doc)] +#![feature(lint_reasons)] extern crate proc_macro_unsafe; @@ -531,4 +532,36 @@ fn issue_10832() { unsafe { a_const_function_with_a_very_long_name_to_break_the_line() }; } +fn issue_8679() { + // SAFETY: + #[allow(unsafe_code)] + unsafe {} + + // SAFETY: + #[expect(unsafe_code, reason = "totally safe")] + unsafe { + *std::ptr::null::() + }; + + // Safety: A safety comment + #[allow(unsafe_code)] + let _some_variable_with_a_very_long_name_to_break_the_line = + unsafe { a_function_with_a_very_long_name_to_break_the_line() }; + + // Safety: Another safety comment + #[allow(unsafe_code)] + const _SOME_CONST_WITH_A_VERY_LONG_NAME_TO_BREAK_THE_LINE: u32 = + unsafe { a_const_function_with_a_very_long_name_to_break_the_line() }; + + // Safety: Yet another safety comment + #[allow(unsafe_code)] + static _SOME_STATIC_WITH_A_VERY_LONG_NAME_TO_BREAK_THE_LINE: u32 = + unsafe { a_const_function_with_a_very_long_name_to_break_the_line() }; + + // SAFETY: + #[allow(unsafe_code)] + // This also works I guess + unsafe {} +} + fn main() {} diff --git a/tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.stderr b/tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.stderr index ac987a9e995..9a0fd059389 100644 --- a/tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.stderr +++ b/tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.stderr @@ -1,5 +1,5 @@ error: unsafe block missing a safety comment - --> $DIR/undocumented_unsafe_blocks.rs:262:19 + --> $DIR/undocumented_unsafe_blocks.rs:263:19 | LL | /* Safety: */ unsafe {} | ^^^^^^^^^ @@ -8,7 +8,7 @@ LL | /* Safety: */ unsafe {} = note: `-D clippy::undocumented-unsafe-blocks` implied by `-D warnings` error: unsafe block missing a safety comment - --> $DIR/undocumented_unsafe_blocks.rs:266:5 + --> $DIR/undocumented_unsafe_blocks.rs:267:5 | LL | unsafe {} | ^^^^^^^^^ @@ -16,7 +16,7 @@ LL | unsafe {} = help: consider adding a safety comment on the preceding line error: unsafe block missing a safety comment - --> $DIR/undocumented_unsafe_blocks.rs:270:14 + --> $DIR/undocumented_unsafe_blocks.rs:271:14 | LL | let _ = [unsafe { 14 }, unsafe { 15 }, 42, unsafe { 16 }]; | ^^^^^^^^^^^^^ @@ -24,7 +24,7 @@ LL | let _ = [unsafe { 14 }, unsafe { 15 }, 42, unsafe { 16 }]; = help: consider adding a safety comment on the preceding line error: unsafe block missing a safety comment - --> $DIR/undocumented_unsafe_blocks.rs:270:29 + --> $DIR/undocumented_unsafe_blocks.rs:271:29 | LL | let _ = [unsafe { 14 }, unsafe { 15 }, 42, unsafe { 16 }]; | ^^^^^^^^^^^^^ @@ -32,7 +32,7 @@ LL | let _ = [unsafe { 14 }, unsafe { 15 }, 42, unsafe { 16 }]; = help: consider adding a safety comment on the preceding line error: unsafe block missing a safety comment - --> $DIR/undocumented_unsafe_blocks.rs:270:48 + --> $DIR/undocumented_unsafe_blocks.rs:271:48 | LL | let _ = [unsafe { 14 }, unsafe { 15 }, 42, unsafe { 16 }]; | ^^^^^^^^^^^^^ @@ -40,7 +40,7 @@ LL | let _ = [unsafe { 14 }, unsafe { 15 }, 42, unsafe { 16 }]; = help: consider adding a safety comment on the preceding line error: unsafe block missing a safety comment - --> $DIR/undocumented_unsafe_blocks.rs:274:18 + --> $DIR/undocumented_unsafe_blocks.rs:275:18 | LL | let _ = (42, unsafe {}, "test", unsafe {}); | ^^^^^^^^^ @@ -48,7 +48,7 @@ LL | let _ = (42, unsafe {}, "test", unsafe {}); = help: consider adding a safety comment on the preceding line error: unsafe block missing a safety comment - --> $DIR/undocumented_unsafe_blocks.rs:274:37 + --> $DIR/undocumented_unsafe_blocks.rs:275:37 | LL | let _ = (42, unsafe {}, "test", unsafe {}); | ^^^^^^^^^ @@ -56,7 +56,7 @@ LL | let _ = (42, unsafe {}, "test", unsafe {}); = help: consider adding a safety comment on the preceding line error: unsafe block missing a safety comment - --> $DIR/undocumented_unsafe_blocks.rs:278:14 + --> $DIR/undocumented_unsafe_blocks.rs:279:14 | LL | let _ = *unsafe { &42 }; | ^^^^^^^^^^^^^^ @@ -64,7 +64,7 @@ LL | let _ = *unsafe { &42 }; = help: consider adding a safety comment on the preceding line error: unsafe block missing a safety comment - --> $DIR/undocumented_unsafe_blocks.rs:283:19 + --> $DIR/undocumented_unsafe_blocks.rs:284:19 | LL | let _ = match unsafe {} { | ^^^^^^^^^ @@ -72,7 +72,7 @@ LL | let _ = match unsafe {} { = help: consider adding a safety comment on the preceding line error: unsafe block missing a safety comment - --> $DIR/undocumented_unsafe_blocks.rs:289:14 + --> $DIR/undocumented_unsafe_blocks.rs:290:14 | LL | let _ = &unsafe {}; | ^^^^^^^^^ @@ -80,7 +80,7 @@ LL | let _ = &unsafe {}; = help: consider adding a safety comment on the preceding line error: unsafe block missing a safety comment - --> $DIR/undocumented_unsafe_blocks.rs:293:14 + --> $DIR/undocumented_unsafe_blocks.rs:294:14 | LL | let _ = [unsafe {}; 5]; | ^^^^^^^^^ @@ -88,7 +88,7 @@ LL | let _ = [unsafe {}; 5]; = help: consider adding a safety comment on the preceding line error: unsafe block missing a safety comment - --> $DIR/undocumented_unsafe_blocks.rs:297:13 + --> $DIR/undocumented_unsafe_blocks.rs:298:13 | LL | let _ = unsafe {}; | ^^^^^^^^^ @@ -96,7 +96,7 @@ LL | let _ = unsafe {}; = help: consider adding a safety comment on the preceding line error: unsafe block missing a safety comment - --> $DIR/undocumented_unsafe_blocks.rs:307:8 + --> $DIR/undocumented_unsafe_blocks.rs:308:8 | LL | t!(unsafe {}); | ^^^^^^^^^ @@ -104,7 +104,7 @@ LL | t!(unsafe {}); = help: consider adding a safety comment on the preceding line error: unsafe block missing a safety comment - --> $DIR/undocumented_unsafe_blocks.rs:313:13 + --> $DIR/undocumented_unsafe_blocks.rs:314:13 | LL | unsafe {} | ^^^^^^^^^ @@ -116,7 +116,7 @@ LL | t!(); = note: this error originates in the macro `t` (in Nightly builds, run with -Z macro-backtrace for more info) error: unsafe block missing a safety comment - --> $DIR/undocumented_unsafe_blocks.rs:321:5 + --> $DIR/undocumented_unsafe_blocks.rs:322:5 | LL | unsafe {} // SAFETY: | ^^^^^^^^^ @@ -124,7 +124,7 @@ LL | unsafe {} // SAFETY: = help: consider adding a safety comment on the preceding line error: unsafe block missing a safety comment - --> $DIR/undocumented_unsafe_blocks.rs:325:5 + --> $DIR/undocumented_unsafe_blocks.rs:326:5 | LL | unsafe { | ^^^^^^^^ @@ -132,7 +132,7 @@ LL | unsafe { = help: consider adding a safety comment on the preceding line error: unsafe block missing a safety comment - --> $DIR/undocumented_unsafe_blocks.rs:335:5 + --> $DIR/undocumented_unsafe_blocks.rs:336:5 | LL | unsafe {}; | ^^^^^^^^^ @@ -140,7 +140,7 @@ LL | unsafe {}; = help: consider adding a safety comment on the preceding line error: unsafe block missing a safety comment - --> $DIR/undocumented_unsafe_blocks.rs:339:20 + --> $DIR/undocumented_unsafe_blocks.rs:340:20 | LL | println!("{}", unsafe { String::from_utf8_unchecked(vec![]) }); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -148,7 +148,7 @@ LL | println!("{}", unsafe { String::from_utf8_unchecked(vec![]) }); = help: consider adding a safety comment on the preceding line error: unsafe impl missing a safety comment - --> $DIR/undocumented_unsafe_blocks.rs:346:5 + --> $DIR/undocumented_unsafe_blocks.rs:347:5 | LL | unsafe impl A for () {} | ^^^^^^^^^^^^^^^^^^^^^^^ @@ -156,7 +156,7 @@ LL | unsafe impl A for () {} = help: consider adding a safety comment on the preceding line error: unsafe impl missing a safety comment - --> $DIR/undocumented_unsafe_blocks.rs:353:9 + --> $DIR/undocumented_unsafe_blocks.rs:354:9 | LL | unsafe impl B for (u32) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -164,7 +164,7 @@ LL | unsafe impl B for (u32) {} = help: consider adding a safety comment on the preceding line error: unsafe impl missing a safety comment - --> $DIR/undocumented_unsafe_blocks.rs:374:13 + --> $DIR/undocumented_unsafe_blocks.rs:375:13 | LL | unsafe impl T for $t {} | ^^^^^^^^^^^^^^^^^^^^^^^ @@ -176,7 +176,7 @@ LL | no_safety_comment!(()); = note: this error originates in the macro `no_safety_comment` (in Nightly builds, run with -Z macro-backtrace for more info) error: unsafe impl missing a safety comment - --> $DIR/undocumented_unsafe_blocks.rs:399:13 + --> $DIR/undocumented_unsafe_blocks.rs:400:13 | LL | unsafe impl T for $t {} | ^^^^^^^^^^^^^^^^^^^^^^^ @@ -188,7 +188,7 @@ LL | no_safety_comment!(()); = note: this error originates in the macro `no_safety_comment` (in Nightly builds, run with -Z macro-backtrace for more info) error: unsafe impl missing a safety comment - --> $DIR/undocumented_unsafe_blocks.rs:407:5 + --> $DIR/undocumented_unsafe_blocks.rs:408:5 | LL | unsafe impl T for (i32) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -196,7 +196,7 @@ LL | unsafe impl T for (i32) {} = help: consider adding a safety comment on the preceding line error: unsafe impl missing a safety comment - --> $DIR/undocumented_unsafe_blocks.rs:399:13 + --> $DIR/undocumented_unsafe_blocks.rs:400:13 | LL | unsafe impl T for $t {} | ^^^^^^^^^^^^^^^^^^^^^^^ @@ -208,7 +208,7 @@ LL | no_safety_comment!(u32); = note: this error originates in the macro `no_safety_comment` (in Nightly builds, run with -Z macro-backtrace for more info) error: unsafe impl missing a safety comment - --> $DIR/undocumented_unsafe_blocks.rs:413:5 + --> $DIR/undocumented_unsafe_blocks.rs:414:5 | LL | unsafe impl T for (bool) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -216,7 +216,7 @@ LL | unsafe impl T for (bool) {} = help: consider adding a safety comment on the preceding line error: unsafe impl missing a safety comment - --> $DIR/undocumented_unsafe_blocks.rs:459:5 + --> $DIR/undocumented_unsafe_blocks.rs:460:5 | LL | unsafe impl NoComment for () {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -224,7 +224,7 @@ LL | unsafe impl NoComment for () {} = help: consider adding a safety comment on the preceding line error: unsafe impl missing a safety comment - --> $DIR/undocumented_unsafe_blocks.rs:463:19 + --> $DIR/undocumented_unsafe_blocks.rs:464:19 | LL | /* SAFETY: */ unsafe impl InlineComment for () {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -232,7 +232,7 @@ LL | /* SAFETY: */ unsafe impl InlineComment for () {} = help: consider adding a safety comment on the preceding line error: unsafe impl missing a safety comment - --> $DIR/undocumented_unsafe_blocks.rs:467:5 + --> $DIR/undocumented_unsafe_blocks.rs:468:5 | LL | unsafe impl TrailingComment for () {} // SAFETY: | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -240,20 +240,20 @@ LL | unsafe impl TrailingComment for () {} // SAFETY: = help: consider adding a safety comment on the preceding line error: constant item has unnecessary safety comment - --> $DIR/undocumented_unsafe_blocks.rs:471:5 + --> $DIR/undocumented_unsafe_blocks.rs:472:5 | LL | const BIG_NUMBER: i32 = 1000000; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | help: consider removing the safety comment - --> $DIR/undocumented_unsafe_blocks.rs:470:5 + --> $DIR/undocumented_unsafe_blocks.rs:471:5 | LL | // SAFETY: | ^^^^^^^^^^ = note: `-D clippy::unnecessary-safety-comment` implied by `-D warnings` error: unsafe impl missing a safety comment - --> $DIR/undocumented_unsafe_blocks.rs:472:5 + --> $DIR/undocumented_unsafe_blocks.rs:473:5 | LL | unsafe impl Interference for () {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -261,7 +261,7 @@ LL | unsafe impl Interference for () {} = help: consider adding a safety comment on the preceding line error: unsafe impl missing a safety comment - --> $DIR/undocumented_unsafe_blocks.rs:479:5 + --> $DIR/undocumented_unsafe_blocks.rs:480:5 | LL | unsafe impl ImplInFn for () {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -269,7 +269,7 @@ LL | unsafe impl ImplInFn for () {} = help: consider adding a safety comment on the preceding line error: unsafe impl missing a safety comment - --> $DIR/undocumented_unsafe_blocks.rs:488:1 + --> $DIR/undocumented_unsafe_blocks.rs:489:1 | LL | unsafe impl CrateRoot for () {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -277,7 +277,7 @@ LL | unsafe impl CrateRoot for () {} = help: consider adding a safety comment on the preceding line error: statement has unnecessary safety comment - --> $DIR/undocumented_unsafe_blocks.rs:501:5 + --> $DIR/undocumented_unsafe_blocks.rs:502:5 | LL | / let _ = { LL | | if unsafe { true } { @@ -289,13 +289,13 @@ LL | | }; | |______^ | help: consider removing the safety comment - --> $DIR/undocumented_unsafe_blocks.rs:500:5 + --> $DIR/undocumented_unsafe_blocks.rs:501:5 | LL | // SAFETY: this is more than one level away, so it should warn | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: unsafe block missing a safety comment - --> $DIR/undocumented_unsafe_blocks.rs:502:12 + --> $DIR/undocumented_unsafe_blocks.rs:503:12 | LL | if unsafe { true } { | ^^^^^^^^^^^^^^^ @@ -303,7 +303,7 @@ LL | if unsafe { true } { = help: consider adding a safety comment on the preceding line error: unsafe block missing a safety comment - --> $DIR/undocumented_unsafe_blocks.rs:505:23 + --> $DIR/undocumented_unsafe_blocks.rs:506:23 | LL | let bar = unsafe {}; | ^^^^^^^^^ From 87c28b94635b2ccf5518979b7ab7ee846365653b Mon Sep 17 00:00:00 2001 From: y21 <30553356+y21@users.noreply.github.com> Date: Tue, 20 Jun 2023 17:24:46 +0200 Subject: [PATCH 240/310] [`type_repetition_in_bounds`]: respect msrv for combining maybe bounds --- clippy_lints/src/lib.rs | 2 +- clippy_lints/src/trait_bounds.rs | 33 ++++++++++++++++------- clippy_utils/src/msrvs.rs | 1 + tests/ui/type_repetition_in_bounds.rs | 24 +++++++++++++++++ tests/ui/type_repetition_in_bounds.stderr | 10 ++++++- 5 files changed, 59 insertions(+), 11 deletions(-) diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index 3fb4e6c8fa5..0008f8f6d46 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -792,7 +792,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: store.register_late_pass(|_| Box::new(assertions_on_result_states::AssertionsOnResultStates)); store.register_late_pass(|_| Box::new(inherent_to_string::InherentToString)); let max_trait_bounds = conf.max_trait_bounds; - store.register_late_pass(move |_| Box::new(trait_bounds::TraitBounds::new(max_trait_bounds))); + store.register_late_pass(move |_| Box::new(trait_bounds::TraitBounds::new(max_trait_bounds, msrv()))); store.register_late_pass(|_| Box::new(comparison_chain::ComparisonChain)); let ignore_interior_mutability = conf.ignore_interior_mutability.clone(); store.register_late_pass(move |_| Box::new(mut_key::MutableKeyType::new(ignore_interior_mutability.clone()))); diff --git a/clippy_lints/src/trait_bounds.rs b/clippy_lints/src/trait_bounds.rs index 3917d8f0225..2cf3529bd1b 100644 --- a/clippy_lints/src/trait_bounds.rs +++ b/clippy_lints/src/trait_bounds.rs @@ -1,4 +1,5 @@ use clippy_utils::diagnostics::{span_lint_and_help, span_lint_and_sugg}; +use clippy_utils::msrvs::{self, Msrv}; use clippy_utils::source::{snippet, snippet_opt, snippet_with_applicability}; use clippy_utils::{is_from_proc_macro, SpanlessEq, SpanlessHash}; use core::hash::{Hash, Hasher}; @@ -9,7 +10,7 @@ use rustc_data_structures::unhash::UnhashMap; use rustc_errors::Applicability; use rustc_hir::def::Res; use rustc_hir::{ - GenericArg, GenericBound, Generics, Item, ItemKind, Node, Path, PathSegment, PredicateOrigin, QPath, + GenericArg, GenericBound, Generics, Item, ItemKind, LangItem, Node, Path, PathSegment, PredicateOrigin, QPath, TraitBoundModifier, TraitItem, TraitRef, Ty, TyKind, WherePredicate, }; use rustc_lint::{LateContext, LateLintPass}; @@ -86,15 +87,16 @@ declare_clippy_lint! { "check if the same trait bounds are specified more than once during a generic declaration" } -#[derive(Copy, Clone)] +#[derive(Clone)] pub struct TraitBounds { max_trait_bounds: u64, + msrv: Msrv, } impl TraitBounds { #[must_use] - pub fn new(max_trait_bounds: u64) -> Self { - Self { max_trait_bounds } + pub fn new(max_trait_bounds: u64, msrv: Msrv) -> Self { + Self { max_trait_bounds, msrv } } } @@ -222,10 +224,24 @@ impl<'tcx> LateLintPass<'tcx> for TraitBounds { } } } + + extract_msrv_attr!(LateContext); } impl TraitBounds { - fn check_type_repetition<'tcx>(self, cx: &LateContext<'tcx>, gen: &'tcx Generics<'_>) { + /// Is the given bound a `?Sized` bound, and is combining it (i.e. `T: X + ?Sized`) an error on + /// this MSRV? See https://github.com/rust-lang/rust-clippy/issues/8772 for details. + fn cannot_combine_maybe_bound(&self, cx: &LateContext<'_>, bound: &GenericBound<'_>) -> bool { + if !self.msrv.meets(msrvs::COMBINED_MAYBE_BOUND) + && let GenericBound::Trait(tr, TraitBoundModifier::Maybe) = bound + { + cx.tcx.lang_items().get(LangItem::Sized) == tr.trait_ref.path.res.opt_def_id() + } else { + false + } + } + + fn check_type_repetition<'tcx>(&self, cx: &LateContext<'tcx>, gen: &'tcx Generics<'_>) { struct SpanlessTy<'cx, 'tcx> { ty: &'tcx Ty<'tcx>, cx: &'cx LateContext<'tcx>, @@ -256,10 +272,9 @@ impl TraitBounds { if p.origin != PredicateOrigin::ImplTrait; if p.bounds.len() as u64 <= self.max_trait_bounds; if !p.span.from_expansion(); - if let Some(ref v) = map.insert( - SpanlessTy { ty: p.bounded_ty, cx }, - p.bounds.iter().collect::>() - ); + let bounds = p.bounds.iter().filter(|b| !self.cannot_combine_maybe_bound(cx, b)).collect::>(); + if !bounds.is_empty(); + if let Some(ref v) = map.insert(SpanlessTy { ty: p.bounded_ty, cx }, bounds); if !is_from_proc_macro(cx, p.bounded_ty); then { let trait_bounds = v diff --git a/clippy_utils/src/msrvs.rs b/clippy_utils/src/msrvs.rs index e1b1a6f7184..b1f336461d1 100644 --- a/clippy_utils/src/msrvs.rs +++ b/clippy_utils/src/msrvs.rs @@ -47,6 +47,7 @@ msrv_aliases! { 1,18,0 { HASH_MAP_RETAIN, HASH_SET_RETAIN } 1,17,0 { FIELD_INIT_SHORTHAND, STATIC_IN_CONST, EXPECT_ERR } 1,16,0 { STR_REPEAT } + 1,15,0 { COMBINED_MAYBE_BOUND } } fn parse_msrv(msrv: &str, sess: Option<&Session>, span: Option) -> Option { diff --git a/tests/ui/type_repetition_in_bounds.rs b/tests/ui/type_repetition_in_bounds.rs index 1d36f4b3c7b..874d97f7a46 100644 --- a/tests/ui/type_repetition_in_bounds.rs +++ b/tests/ui/type_repetition_in_bounds.rs @@ -110,4 +110,28 @@ where // This should not lint fn impl_trait(_: impl AsRef, _: impl AsRef) {} +#[clippy::msrv = "1.14.0"] +mod issue8772_fail { + pub trait Trait {} + + pub fn f(arg: usize) + where + T: Trait, Box<[String]>, bool> + 'static, + U: Clone + Sync + 'static, + { + } +} + +#[clippy::msrv = "1.15.0"] +mod issue8772_pass { + pub trait Trait {} + + pub fn f(arg: usize) + where + T: Trait, Box<[String]>, bool> + 'static, + U: Clone + Sync + 'static, + { + } +} + fn main() {} diff --git a/tests/ui/type_repetition_in_bounds.stderr b/tests/ui/type_repetition_in_bounds.stderr index 56867f75b07..54973c5bda5 100644 --- a/tests/ui/type_repetition_in_bounds.stderr +++ b/tests/ui/type_repetition_in_bounds.stderr @@ -35,5 +35,13 @@ LL | T: ?Sized, | = help: consider combining the bounds: `T: Clone + ?Sized` -error: aborting due to 4 previous errors +error: this type has already been used as a bound predicate + --> $DIR/type_repetition_in_bounds.rs:131:9 + | +LL | T: Trait, Box<[String]>, bool> + 'static, + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: consider combining the bounds: `T: ?Sized + Trait, Box<[String]>, bool>` + +error: aborting due to 5 previous errors From 765a6e4a9014977b6f821df164633b3b7f5857f7 Mon Sep 17 00:00:00 2001 From: y21 <30553356+y21@users.noreply.github.com> Date: Tue, 20 Jun 2023 17:36:38 +0200 Subject: [PATCH 241/310] put issue link between <> --- clippy_lints/src/trait_bounds.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clippy_lints/src/trait_bounds.rs b/clippy_lints/src/trait_bounds.rs index 2cf3529bd1b..78e27b775fb 100644 --- a/clippy_lints/src/trait_bounds.rs +++ b/clippy_lints/src/trait_bounds.rs @@ -230,7 +230,7 @@ impl<'tcx> LateLintPass<'tcx> for TraitBounds { impl TraitBounds { /// Is the given bound a `?Sized` bound, and is combining it (i.e. `T: X + ?Sized`) an error on - /// this MSRV? See https://github.com/rust-lang/rust-clippy/issues/8772 for details. + /// this MSRV? See for details. fn cannot_combine_maybe_bound(&self, cx: &LateContext<'_>, bound: &GenericBound<'_>) -> bool { if !self.msrv.meets(msrvs::COMBINED_MAYBE_BOUND) && let GenericBound::Trait(tr, TraitBoundModifier::Maybe) = bound From d8d59965f1e6ba0490533c0bbd1ce50a00606d36 Mon Sep 17 00:00:00 2001 From: Catherine <114838443+Centri3@users.noreply.github.com> Date: Tue, 20 Jun 2023 13:37:03 -0500 Subject: [PATCH 242/310] Lint `mem_forget` if fields are `Drop` --- clippy_lints/src/mem_forget.rs | 32 ++++++++++++++++++++------------ tests/ui/mem_forget.rs | 3 +++ tests/ui/mem_forget.stderr | 8 +++++++- 3 files changed, 30 insertions(+), 13 deletions(-) diff --git a/clippy_lints/src/mem_forget.rs b/clippy_lints/src/mem_forget.rs index d6c235b5a69..fdd55260483 100644 --- a/clippy_lints/src/mem_forget.rs +++ b/clippy_lints/src/mem_forget.rs @@ -7,7 +7,7 @@ use rustc_span::sym; declare_clippy_lint! { /// ### What it does /// Checks for usage of `std::mem::forget(t)` where `t` is - /// `Drop`. + /// `Drop` or has a field that implements `Drop`. /// /// ### Why is this bad? /// `std::mem::forget(t)` prevents `t` from running its @@ -29,18 +29,26 @@ declare_lint_pass!(MemForget => [MEM_FORGET]); impl<'tcx> LateLintPass<'tcx> for MemForget { fn check_expr(&mut self, cx: &LateContext<'tcx>, e: &'tcx Expr<'_>) { - if let ExprKind::Call(path_expr, [ref first_arg, ..]) = e.kind { - if let ExprKind::Path(ref qpath) = path_expr.kind { - if let Some(def_id) = cx.qpath_res(qpath, path_expr.hir_id).opt_def_id() { - if cx.tcx.is_diagnostic_item(sym::mem_forget, def_id) { - let forgot_ty = cx.typeck_results().expr_ty(first_arg); - - if forgot_ty.ty_adt_def().map_or(false, |def| def.has_dtor(cx.tcx)) { - span_lint(cx, MEM_FORGET, e.span, "usage of `mem::forget` on `Drop` type"); - } + if let ExprKind::Call(path_expr, [ref first_arg, ..]) = e.kind + && let ExprKind::Path(ref qpath) = path_expr.kind + && let Some(def_id) = cx.qpath_res(qpath, path_expr.hir_id).opt_def_id() + && cx.tcx.is_diagnostic_item(sym::mem_forget, def_id) + && let forgot_ty = cx.typeck_results().expr_ty(first_arg) + && forgot_ty.needs_drop(cx.tcx, cx.param_env) + { + span_lint( + cx, + MEM_FORGET, + e.span, + &format!( + "usage of `mem::forget` on {}", + if forgot_ty.ty_adt_def().map_or(false, |def| def.has_dtor(cx.tcx)) { + "`Drop` type" + } else { + "type with `Drop` fields" } - } - } + ), + ); } } } diff --git a/tests/ui/mem_forget.rs b/tests/ui/mem_forget.rs index edb9d87d032..b6c8d9e53d8 100644 --- a/tests/ui/mem_forget.rs +++ b/tests/ui/mem_forget.rs @@ -19,5 +19,8 @@ fn main() { let eight: Vec = vec![8]; forgetSomething(eight); + let string = String::new(); + std::mem::forget(string); + std::mem::forget(7); } diff --git a/tests/ui/mem_forget.stderr b/tests/ui/mem_forget.stderr index a90d8b1655d..50711120a15 100644 --- a/tests/ui/mem_forget.stderr +++ b/tests/ui/mem_forget.stderr @@ -18,5 +18,11 @@ error: usage of `mem::forget` on `Drop` type LL | forgetSomething(eight); | ^^^^^^^^^^^^^^^^^^^^^^ -error: aborting due to 3 previous errors +error: usage of `mem::forget` on type with `Drop` fields + --> $DIR/mem_forget.rs:23:5 + | +LL | std::mem::forget(string); + | ^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 4 previous errors From e3b601a1aa3121f2836c67c855dfcc3964043887 Mon Sep 17 00:00:00 2001 From: Catherine <114838443+Centri3@users.noreply.github.com> Date: Tue, 20 Jun 2023 18:12:20 -0500 Subject: [PATCH 243/310] Add WebAssembly to allowed idents --- book/src/lint_configuration.md | 2 +- clippy_lints/src/utils/conf.rs | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/book/src/lint_configuration.md b/book/src/lint_configuration.md index 32cc5d1edcc..6c52563b8ed 100644 --- a/book/src/lint_configuration.md +++ b/book/src/lint_configuration.md @@ -210,7 +210,7 @@ default configuration of Clippy. By default, any configuration will replace the Default list: -**Default Value:** `["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"]` (`Vec`) +**Default Value:** `["KiB", "MiB", "GiB", "TiB", "PiB", "EiB", "DirectX", "ECMAScript", "GPLv2", "GPLv3", "GitHub", "GitLab", "IPv4", "IPv6", "ClojureScript", "CoffeeScript", "JavaScript", "PureScript", "TypeScript", "WebAssembly", "NaN", "NaNs", "OAuth", "GraphQL", "OCaml", "OpenGL", "OpenMP", "OpenSSH", "OpenSSL", "OpenStreetMap", "OpenDNS", "WebGL", "TensorFlow", "TrueType", "iOS", "macOS", "FreeBSD", "TeX", "LaTeX", "BibTeX", "BibLaTeX", "MinGW", "CamelCase"]` (`Vec`) --- **Affected lints:** diff --git a/clippy_lints/src/utils/conf.rs b/clippy_lints/src/utils/conf.rs index 3cf2fbf1f28..f5d6cecc59c 100644 --- a/clippy_lints/src/utils/conf.rs +++ b/clippy_lints/src/utils/conf.rs @@ -21,6 +21,7 @@ const DEFAULT_DOC_VALID_IDENTS: &[&str] = &[ "GitHub", "GitLab", "IPv4", "IPv6", "ClojureScript", "CoffeeScript", "JavaScript", "PureScript", "TypeScript", + "WebAssembly", "NaN", "NaNs", "OAuth", "GraphQL", "OCaml", From 3b89984b56e3bdcf2e99b2a492009753e22251a2 Mon Sep 17 00:00:00 2001 From: Catherine <114838443+Centri3@users.noreply.github.com> Date: Tue, 20 Jun 2023 21:19:58 -0500 Subject: [PATCH 244/310] add WebAssembly to test --- tests/ui/doc/doc-fixable.fixed | 1 + tests/ui/doc/doc-fixable.rs | 1 + tests/ui/doc/doc-fixable.stderr | 32 ++++++++++++++++---------------- 3 files changed, 18 insertions(+), 16 deletions(-) diff --git a/tests/ui/doc/doc-fixable.fixed b/tests/ui/doc/doc-fixable.fixed index d3aa2816cb6..14444df4c10 100644 --- a/tests/ui/doc/doc-fixable.fixed +++ b/tests/ui/doc/doc-fixable.fixed @@ -60,6 +60,7 @@ fn test_units() { /// GitHub GitLab /// IPv4 IPv6 /// ClojureScript CoffeeScript JavaScript PureScript TypeScript +/// WebAssembly /// NaN NaNs /// OAuth GraphQL /// OCaml diff --git a/tests/ui/doc/doc-fixable.rs b/tests/ui/doc/doc-fixable.rs index d1e7d8017d7..542d33b13a4 100644 --- a/tests/ui/doc/doc-fixable.rs +++ b/tests/ui/doc/doc-fixable.rs @@ -60,6 +60,7 @@ fn test_units() { /// GitHub GitLab /// IPv4 IPv6 /// ClojureScript CoffeeScript JavaScript PureScript TypeScript +/// WebAssembly /// NaN NaNs /// OAuth GraphQL /// OCaml diff --git a/tests/ui/doc/doc-fixable.stderr b/tests/ui/doc/doc-fixable.stderr index 6c67c903c75..94ef43afc08 100644 --- a/tests/ui/doc/doc-fixable.stderr +++ b/tests/ui/doc/doc-fixable.stderr @@ -132,7 +132,7 @@ LL | /// `be_sure_we_got_to_the_end_of_it` | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ error: item in documentation is missing backticks - --> $DIR/doc-fixable.rs:74:5 + --> $DIR/doc-fixable.rs:75:5 | LL | /// be_sure_we_got_to_the_end_of_it | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -143,7 +143,7 @@ LL | /// `be_sure_we_got_to_the_end_of_it` | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ error: item in documentation is missing backticks - --> $DIR/doc-fixable.rs:91:5 + --> $DIR/doc-fixable.rs:92:5 | LL | /// be_sure_we_got_to_the_end_of_it | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -154,7 +154,7 @@ LL | /// `be_sure_we_got_to_the_end_of_it` | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ error: item in documentation is missing backticks - --> $DIR/doc-fixable.rs:99:8 + --> $DIR/doc-fixable.rs:100:8 | LL | /// ## CamelCaseThing | ^^^^^^^^^^^^^^ @@ -165,7 +165,7 @@ LL | /// ## `CamelCaseThing` | ~~~~~~~~~~~~~~~~ error: item in documentation is missing backticks - --> $DIR/doc-fixable.rs:102:7 + --> $DIR/doc-fixable.rs:103:7 | LL | /// # CamelCaseThing | ^^^^^^^^^^^^^^ @@ -176,7 +176,7 @@ LL | /// # `CamelCaseThing` | ~~~~~~~~~~~~~~~~ error: item in documentation is missing backticks - --> $DIR/doc-fixable.rs:104:22 + --> $DIR/doc-fixable.rs:105:22 | LL | /// Not a title #897 CamelCaseThing | ^^^^^^^^^^^^^^ @@ -187,7 +187,7 @@ LL | /// Not a title #897 `CamelCaseThing` | ~~~~~~~~~~~~~~~~ error: item in documentation is missing backticks - --> $DIR/doc-fixable.rs:105:5 + --> $DIR/doc-fixable.rs:106:5 | LL | /// be_sure_we_got_to_the_end_of_it | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -198,7 +198,7 @@ LL | /// `be_sure_we_got_to_the_end_of_it` | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ error: item in documentation is missing backticks - --> $DIR/doc-fixable.rs:112:5 + --> $DIR/doc-fixable.rs:113:5 | LL | /// be_sure_we_got_to_the_end_of_it | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -209,7 +209,7 @@ LL | /// `be_sure_we_got_to_the_end_of_it` | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ error: item in documentation is missing backticks - --> $DIR/doc-fixable.rs:125:5 + --> $DIR/doc-fixable.rs:126:5 | LL | /// be_sure_we_got_to_the_end_of_it | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -220,7 +220,7 @@ LL | /// `be_sure_we_got_to_the_end_of_it` | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ error: item in documentation is missing backticks - --> $DIR/doc-fixable.rs:136:43 + --> $DIR/doc-fixable.rs:137:43 | LL | /** E.g., serialization of an empty list: FooBar | ^^^^^^ @@ -231,7 +231,7 @@ LL | /** E.g., serialization of an empty list: `FooBar` | ~~~~~~~~ error: item in documentation is missing backticks - --> $DIR/doc-fixable.rs:141:5 + --> $DIR/doc-fixable.rs:142:5 | LL | And BarQuz too. | ^^^^^^ @@ -242,7 +242,7 @@ LL | And `BarQuz` too. | ~~~~~~~~ error: item in documentation is missing backticks - --> $DIR/doc-fixable.rs:142:1 + --> $DIR/doc-fixable.rs:143:1 | LL | be_sure_we_got_to_the_end_of_it | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -253,7 +253,7 @@ LL | `be_sure_we_got_to_the_end_of_it` | error: item in documentation is missing backticks - --> $DIR/doc-fixable.rs:147:43 + --> $DIR/doc-fixable.rs:148:43 | LL | /** E.g., serialization of an empty list: FooBar | ^^^^^^ @@ -264,7 +264,7 @@ LL | /** E.g., serialization of an empty list: `FooBar` | ~~~~~~~~ error: item in documentation is missing backticks - --> $DIR/doc-fixable.rs:152:5 + --> $DIR/doc-fixable.rs:153:5 | LL | And BarQuz too. | ^^^^^^ @@ -275,7 +275,7 @@ LL | And `BarQuz` too. | ~~~~~~~~ error: item in documentation is missing backticks - --> $DIR/doc-fixable.rs:153:1 + --> $DIR/doc-fixable.rs:154:1 | LL | be_sure_we_got_to_the_end_of_it | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -286,7 +286,7 @@ LL | `be_sure_we_got_to_the_end_of_it` | error: item in documentation is missing backticks - --> $DIR/doc-fixable.rs:164:5 + --> $DIR/doc-fixable.rs:165:5 | LL | /// be_sure_we_got_to_the_end_of_it | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -297,7 +297,7 @@ LL | /// `be_sure_we_got_to_the_end_of_it` | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ error: item in documentation is missing backticks - --> $DIR/doc-fixable.rs:183:22 + --> $DIR/doc-fixable.rs:184:22 | LL | /// An iterator over mycrate::Collection's values. | ^^^^^^^^^^^^^^^^^^^ From 3122e3d78f91bc28becf205193fc4ce67955520a Mon Sep 17 00:00:00 2001 From: y21 <30553356+y21@users.noreply.github.com> Date: Wed, 21 Jun 2023 09:04:40 +0200 Subject: [PATCH 245/310] use let chains, move assignments out of block, add tests --- clippy_lints/src/methods/get_unwrap.rs | 30 ++++++----------- tests/ui/get_unwrap.fixed | 44 +++++++++++++++++++----- tests/ui/get_unwrap.rs | 44 +++++++++++++++++++----- tests/ui/get_unwrap.stderr | 46 ++++++++------------------ 4 files changed, 95 insertions(+), 69 deletions(-) diff --git a/clippy_lints/src/methods/get_unwrap.rs b/clippy_lints/src/methods/get_unwrap.rs index 209d42ebabd..ba5aae28bd6 100644 --- a/clippy_lints/src/methods/get_unwrap.rs +++ b/clippy_lints/src/methods/get_unwrap.rs @@ -3,7 +3,6 @@ use clippy_utils::diagnostics::span_lint_and_sugg; use clippy_utils::get_parent_expr; use clippy_utils::source::snippet_with_applicability; use clippy_utils::ty::is_type_diagnostic_item; -use if_chain::if_chain; use rustc_errors::Applicability; use rustc_hir as hir; use rustc_lint::LateContext; @@ -23,21 +22,16 @@ pub(super) fn check<'tcx>( let mut applicability = Applicability::MachineApplicable; let expr_ty = cx.typeck_results().expr_ty(recv); let get_args_str = snippet_with_applicability(cx, get_arg.span, "..", &mut applicability); - let mut needs_ref; + let mut needs_ref = true; let caller_type = if derefs_to_slice(cx, recv, expr_ty).is_some() { - needs_ref = true; "slice" } else if is_type_diagnostic_item(cx, expr_ty, sym::Vec) { - needs_ref = true; "Vec" } else if is_type_diagnostic_item(cx, expr_ty, sym::VecDeque) { - needs_ref = true; "VecDeque" } else if !is_mut && is_type_diagnostic_item(cx, expr_ty, sym::HashMap) { - needs_ref = true; "HashMap" } else if !is_mut && is_type_diagnostic_item(cx, expr_ty, sym::BTreeMap) { - needs_ref = true; "BTreeMap" } else { return; // caller is not a type that we want to lint @@ -48,21 +42,19 @@ pub(super) fn check<'tcx>( // Handle the case where the result is immediately dereferenced, // either directly be the user, or as a result of a method call or the like // by not requiring an explicit reference - if_chain! { - if needs_ref; - if let Some(parent) = get_parent_expr(cx, expr); - if let hir::ExprKind::Unary(hir::UnOp::Deref, _) + if needs_ref + && let Some(parent) = get_parent_expr(cx, expr) + && let hir::ExprKind::Unary(hir::UnOp::Deref, _) | hir::ExprKind::MethodCall(..) | hir::ExprKind::Field(..) - | hir::ExprKind::Index(..) = parent.kind; - then { - if let hir::ExprKind::Unary(hir::UnOp::Deref, _) = parent.kind { - // if the user explicitly dereferences the result, we can adjust - // the span to also include the deref part - span = parent.span; - } - needs_ref = false; + | hir::ExprKind::Index(..) = parent.kind + { + if let hir::ExprKind::Unary(hir::UnOp::Deref, _) = parent.kind { + // if the user explicitly dereferences the result, we can adjust + // the span to also include the deref part + span = parent.span; } + needs_ref = false; } let mut_str = if is_mut { "_mut" } else { "" }; diff --git a/tests/ui/get_unwrap.fixed b/tests/ui/get_unwrap.fixed index 3e4c2b499e4..f0d28dd9349 100644 --- a/tests/ui/get_unwrap.fixed +++ b/tests/ui/get_unwrap.fixed @@ -69,17 +69,43 @@ fn main() { let _ = some_vec[0..1].to_vec(); let _ = some_vec[0..1].to_vec(); } - issue9909(); } -fn issue9909() { - let f = &[1, 2, 3]; +mod issue9909 { + #![allow(clippy::identity_op, clippy::unwrap_used, dead_code)] - let _x: &i32 = &f[1 + 2]; - // ^ include a borrow in the suggestion, even if the argument is not just a numeric literal + fn reduced() { + let f = &[1, 2, 3]; - let _x = f[1 + 2].to_string(); - // ^ don't include a borrow here + let _x: &i32 = &f[1 + 2]; + // ^ include a borrow in the suggestion, even if the argument is not just a numeric literal - let _x = f[1 + 2].abs(); - // ^ don't include a borrow here + let _x = f[1 + 2].to_string(); + // ^ don't include a borrow here + + let _x = f[1 + 2].abs(); + // ^ don't include a borrow here + } + + // original code: + fn linidx(row: usize, col: usize) -> usize { + row * 1 + col * 3 + } + + fn main_() { + let mut mat = [1.0f32, 5.0, 9.0, 2.0, 6.0, 10.0, 3.0, 7.0, 11.0, 4.0, 8.0, 12.0]; + + for i in 0..2 { + for j in i + 1..3 { + if mat[linidx(j, 3)] > mat[linidx(i, 3)] { + for k in 0..4 { + let (x, rest) = mat.split_at_mut(linidx(i, k) + 1); + let a = x.last_mut().unwrap(); + let b = &mut rest[linidx(j, k) - linidx(i, k) - 1]; + ::std::mem::swap(a, b); + } + } + } + } + assert_eq!([9.0, 5.0, 1.0, 10.0, 6.0, 2.0, 11.0, 7.0, 3.0, 12.0, 8.0, 4.0], mat); + } } diff --git a/tests/ui/get_unwrap.rs b/tests/ui/get_unwrap.rs index a967971a7dc..21c1ecb0af2 100644 --- a/tests/ui/get_unwrap.rs +++ b/tests/ui/get_unwrap.rs @@ -69,17 +69,43 @@ fn main() { let _ = some_vec.get(0..1).unwrap().to_vec(); let _ = some_vec.get_mut(0..1).unwrap().to_vec(); } - issue9909(); } -fn issue9909() { - let f = &[1, 2, 3]; +mod issue9909 { + #![allow(clippy::identity_op, clippy::unwrap_used, dead_code)] - let _x: &i32 = f.get(1 + 2).unwrap(); - // ^ include a borrow in the suggestion, even if the argument is not just a numeric literal + fn reduced() { + let f = &[1, 2, 3]; - let _x = f.get(1 + 2).unwrap().to_string(); - // ^ don't include a borrow here + let _x: &i32 = f.get(1 + 2).unwrap(); + // ^ include a borrow in the suggestion, even if the argument is not just a numeric literal - let _x = f.get(1 + 2).unwrap().abs(); - // ^ don't include a borrow here + let _x = f.get(1 + 2).unwrap().to_string(); + // ^ don't include a borrow here + + let _x = f.get(1 + 2).unwrap().abs(); + // ^ don't include a borrow here + } + + // original code: + fn linidx(row: usize, col: usize) -> usize { + row * 1 + col * 3 + } + + fn main_() { + let mut mat = [1.0f32, 5.0, 9.0, 2.0, 6.0, 10.0, 3.0, 7.0, 11.0, 4.0, 8.0, 12.0]; + + for i in 0..2 { + for j in i + 1..3 { + if mat[linidx(j, 3)] > mat[linidx(i, 3)] { + for k in 0..4 { + let (x, rest) = mat.split_at_mut(linidx(i, k) + 1); + let a = x.last_mut().unwrap(); + let b = rest.get_mut(linidx(j, k) - linidx(i, k) - 1).unwrap(); + ::std::mem::swap(a, b); + } + } + } + } + assert_eq!([9.0, 5.0, 1.0, 10.0, 6.0, 2.0, 11.0, 7.0, 3.0, 12.0, 8.0, 4.0], mat); + } } diff --git a/tests/ui/get_unwrap.stderr b/tests/ui/get_unwrap.stderr index 6221c236830..154083ea654 100644 --- a/tests/ui/get_unwrap.stderr +++ b/tests/ui/get_unwrap.stderr @@ -188,46 +188,28 @@ LL | let _ = some_vec.get_mut(0..1).unwrap().to_vec(); = help: if you don't want to handle the `None` case gracefully, consider using `expect()` to provide a better panic message error: called `.get().unwrap()` on a slice. Using `[]` is more clear and more concise - --> $DIR/get_unwrap.rs:77:20 + --> $DIR/get_unwrap.rs:79:24 | -LL | let _x: &i32 = f.get(1 + 2).unwrap(); - | ^^^^^^^^^^^^^^^^^^^^^ help: try this: `&f[1 + 2]` - -error: used `unwrap()` on an `Option` value - --> $DIR/get_unwrap.rs:77:20 - | -LL | let _x: &i32 = f.get(1 + 2).unwrap(); - | ^^^^^^^^^^^^^^^^^^^^^ - | - = help: if you don't want to handle the `None` case gracefully, consider using `expect()` to provide a better panic message +LL | let _x: &i32 = f.get(1 + 2).unwrap(); + | ^^^^^^^^^^^^^^^^^^^^^ help: try this: `&f[1 + 2]` error: called `.get().unwrap()` on a slice. Using `[]` is more clear and more concise - --> $DIR/get_unwrap.rs:80:14 + --> $DIR/get_unwrap.rs:82:18 | -LL | let _x = f.get(1 + 2).unwrap().to_string(); - | ^^^^^^^^^^^^^^^^^^^^^ help: try this: `f[1 + 2]` - -error: used `unwrap()` on an `Option` value - --> $DIR/get_unwrap.rs:80:14 - | -LL | let _x = f.get(1 + 2).unwrap().to_string(); - | ^^^^^^^^^^^^^^^^^^^^^ - | - = help: if you don't want to handle the `None` case gracefully, consider using `expect()` to provide a better panic message +LL | let _x = f.get(1 + 2).unwrap().to_string(); + | ^^^^^^^^^^^^^^^^^^^^^ help: try this: `f[1 + 2]` error: called `.get().unwrap()` on a slice. Using `[]` is more clear and more concise - --> $DIR/get_unwrap.rs:83:14 + --> $DIR/get_unwrap.rs:85:18 | -LL | let _x = f.get(1 + 2).unwrap().abs(); - | ^^^^^^^^^^^^^^^^^^^^^ help: try this: `f[1 + 2]` +LL | let _x = f.get(1 + 2).unwrap().abs(); + | ^^^^^^^^^^^^^^^^^^^^^ help: try this: `f[1 + 2]` -error: used `unwrap()` on an `Option` value - --> $DIR/get_unwrap.rs:83:14 +error: called `.get_mut().unwrap()` on a slice. Using `[]` is more clear and more concise + --> $DIR/get_unwrap.rs:103:33 | -LL | let _x = f.get(1 + 2).unwrap().abs(); - | ^^^^^^^^^^^^^^^^^^^^^ - | - = help: if you don't want to handle the `None` case gracefully, consider using `expect()` to provide a better panic message +LL | let b = rest.get_mut(linidx(j, k) - linidx(i, k) - 1).unwrap(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `&mut rest[linidx(j, k) - linidx(i, k) - 1]` -error: aborting due to 32 previous errors +error: aborting due to 30 previous errors From bdb2a1710774e0d77058c81fa3c7182f27565ddd Mon Sep 17 00:00:00 2001 From: y21 <30553356+y21@users.noreply.github.com> Date: Wed, 21 Jun 2023 09:16:25 +0200 Subject: [PATCH 246/310] declare needs_ref later --- clippy_lints/src/methods/get_unwrap.rs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/clippy_lints/src/methods/get_unwrap.rs b/clippy_lints/src/methods/get_unwrap.rs index ba5aae28bd6..e35fb12ed79 100644 --- a/clippy_lints/src/methods/get_unwrap.rs +++ b/clippy_lints/src/methods/get_unwrap.rs @@ -22,7 +22,6 @@ pub(super) fn check<'tcx>( let mut applicability = Applicability::MachineApplicable; let expr_ty = cx.typeck_results().expr_ty(recv); let get_args_str = snippet_with_applicability(cx, get_arg.span, "..", &mut applicability); - let mut needs_ref = true; let caller_type = if derefs_to_slice(cx, recv, expr_ty).is_some() { "slice" } else if is_type_diagnostic_item(cx, expr_ty, sym::Vec) { @@ -42,8 +41,7 @@ pub(super) fn check<'tcx>( // Handle the case where the result is immediately dereferenced, // either directly be the user, or as a result of a method call or the like // by not requiring an explicit reference - if needs_ref - && let Some(parent) = get_parent_expr(cx, expr) + let needs_ref = if let Some(parent) = get_parent_expr(cx, expr) && let hir::ExprKind::Unary(hir::UnOp::Deref, _) | hir::ExprKind::MethodCall(..) | hir::ExprKind::Field(..) @@ -54,8 +52,10 @@ pub(super) fn check<'tcx>( // the span to also include the deref part span = parent.span; } - needs_ref = false; - } + false + } else { + true + }; let mut_str = if is_mut { "_mut" } else { "" }; let borrow_str = if !needs_ref { From 716305d4b6976fd778ff9bfad723f7f761e2bd90 Mon Sep 17 00:00:00 2001 From: y21 <30553356+y21@users.noreply.github.com> Date: Wed, 21 Jun 2023 16:36:48 +0200 Subject: [PATCH 247/310] [`question_mark`]: don't lint inside of `try` block --- clippy_lints/src/lib.rs | 2 +- clippy_lints/src/question_mark.rs | 242 +++++++++++++++++------------- tests/ui/question_mark.fixed | 12 ++ tests/ui/question_mark.rs | 12 ++ tests/ui/question_mark.stderr | 30 ++-- 5 files changed, 181 insertions(+), 117 deletions(-) diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index 3fb4e6c8fa5..876fcd0f197 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -770,7 +770,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: store.register_late_pass(|_| Box::::default()); store.register_late_pass(|_| Box::new(implicit_hasher::ImplicitHasher)); store.register_late_pass(|_| Box::new(fallible_impl_from::FallibleImplFrom)); - store.register_late_pass(|_| Box::new(question_mark::QuestionMark)); + store.register_late_pass(|_| Box::::default()); store.register_late_pass(|_| Box::new(question_mark_used::QuestionMarkUsed)); store.register_early_pass(|| Box::new(suspicious_operation_groupings::SuspiciousOperationGroupings)); store.register_late_pass(|_| Box::new(suspicious_trait_impl::SuspiciousImpl)); diff --git a/clippy_lints/src/question_mark.rs b/clippy_lints/src/question_mark.rs index 5269bbd1f1a..036ad3e0d15 100644 --- a/clippy_lints/src/question_mark.rs +++ b/clippy_lints/src/question_mark.rs @@ -1,19 +1,20 @@ use clippy_utils::diagnostics::span_lint_and_sugg; -use clippy_utils::higher; use clippy_utils::source::snippet_with_applicability; use clippy_utils::ty::is_type_diagnostic_item; use clippy_utils::{ eq_expr_value, get_parent_node, in_constant, is_else_clause, is_res_lang_ctor, path_to_local, path_to_local_id, peel_blocks, peel_blocks_with_stmt, }; +use clippy_utils::{higher, is_path_lang_item}; use if_chain::if_chain; use rustc_errors::Applicability; use rustc_hir::def::Res; -use rustc_hir::LangItem::{OptionNone, OptionSome, ResultErr, ResultOk}; +use rustc_hir::LangItem::{self, OptionNone, OptionSome, ResultErr, ResultOk}; use rustc_hir::{BindingAnnotation, ByRef, Expr, ExprKind, Node, PatKind, PathSegment, QPath}; use rustc_lint::{LateContext, LateLintPass}; use rustc_middle::ty::Ty; -use rustc_session::{declare_lint_pass, declare_tool_lint}; +use rustc_session::declare_tool_lint; +use rustc_session::impl_lint_pass; use rustc_span::{sym, symbol::Symbol}; declare_clippy_lint! { @@ -41,7 +42,16 @@ declare_clippy_lint! { "checks for expressions that could be replaced by the question mark operator" } -declare_lint_pass!(QuestionMark => [QUESTION_MARK]); +#[derive(Default)] +pub struct QuestionMark { + /// Keeps track of how many try blocks we are in at any point during linting. + /// This allows us to answer the question "are we inside of a try block" + /// very quickly, without having to walk up the parent chain, by simply checking + /// if it is greater than zero. + /// As for why we need this in the first place: + try_block_depth: u32, +} +impl_lint_pass!(QuestionMark => [QUESTION_MARK]); enum IfBlockType<'hir> { /// An `if x.is_xxx() { a } else { b } ` expression. @@ -68,98 +78,6 @@ enum IfBlockType<'hir> { ), } -/// Checks if the given expression on the given context matches the following structure: -/// -/// ```ignore -/// if option.is_none() { -/// return None; -/// } -/// ``` -/// -/// ```ignore -/// if result.is_err() { -/// return result; -/// } -/// ``` -/// -/// If it matches, it will suggest to use the question mark operator instead -fn check_is_none_or_err_and_early_return<'tcx>(cx: &LateContext<'tcx>, expr: &Expr<'tcx>) { - if_chain! { - if let Some(higher::If { cond, then, r#else }) = higher::If::hir(expr); - if !is_else_clause(cx.tcx, expr); - if let ExprKind::MethodCall(segment, caller, ..) = &cond.kind; - let caller_ty = cx.typeck_results().expr_ty(caller); - let if_block = IfBlockType::IfIs(caller, caller_ty, segment.ident.name, then, r#else); - if is_early_return(sym::Option, cx, &if_block) || is_early_return(sym::Result, cx, &if_block); - then { - let mut applicability = Applicability::MachineApplicable; - let receiver_str = snippet_with_applicability(cx, caller.span, "..", &mut applicability); - let by_ref = !caller_ty.is_copy_modulo_regions(cx.tcx, cx.param_env) && - !matches!(caller.kind, ExprKind::Call(..) | ExprKind::MethodCall(..)); - let sugg = if let Some(else_inner) = r#else { - if eq_expr_value(cx, caller, peel_blocks(else_inner)) { - format!("Some({receiver_str}?)") - } else { - return; - } - } else { - format!("{receiver_str}{}?;", if by_ref { ".as_ref()" } else { "" }) - }; - - span_lint_and_sugg( - cx, - QUESTION_MARK, - expr.span, - "this block may be rewritten with the `?` operator", - "replace it with", - sugg, - applicability, - ); - } - } -} - -fn check_if_let_some_or_err_and_early_return<'tcx>(cx: &LateContext<'tcx>, expr: &Expr<'tcx>) { - if_chain! { - if let Some(higher::IfLet { let_pat, let_expr, if_then, if_else }) = higher::IfLet::hir(cx, expr); - if !is_else_clause(cx.tcx, expr); - if let PatKind::TupleStruct(ref path1, [field], ddpos) = let_pat.kind; - if ddpos.as_opt_usize().is_none(); - if let PatKind::Binding(BindingAnnotation(by_ref, _), bind_id, ident, None) = field.kind; - let caller_ty = cx.typeck_results().expr_ty(let_expr); - let if_block = IfBlockType::IfLet( - cx.qpath_res(path1, let_pat.hir_id), - caller_ty, - ident.name, - let_expr, - if_then, - if_else - ); - if (is_early_return(sym::Option, cx, &if_block) && path_to_local_id(peel_blocks(if_then), bind_id)) - || is_early_return(sym::Result, cx, &if_block); - if if_else.map(|e| eq_expr_value(cx, let_expr, peel_blocks(e))).filter(|e| *e).is_none(); - then { - let mut applicability = Applicability::MachineApplicable; - let receiver_str = snippet_with_applicability(cx, let_expr.span, "..", &mut applicability); - let requires_semi = matches!(get_parent_node(cx.tcx, expr.hir_id), Some(Node::Stmt(_))); - let sugg = format!( - "{receiver_str}{}?{}", - if by_ref == ByRef::Yes { ".as_ref()" } else { "" }, - if requires_semi { ";" } else { "" } - ); - span_lint_and_sugg( - cx, - QUESTION_MARK, - expr.span, - "this block may be rewritten with the `?` operator", - "replace it with", - sugg, - applicability, - ); - } - } -} - fn is_early_return(smbl: Symbol, cx: &LateContext<'_>, if_block: &IfBlockType<'_>) -> bool { match *if_block { IfBlockType::IfIs(caller, caller_ty, call_sym, if_then, _) => { @@ -230,11 +148,133 @@ fn expr_return_none_or_err( } } -impl<'tcx> LateLintPass<'tcx> for QuestionMark { - fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) { - if !in_constant(cx, expr.hir_id) { - check_is_none_or_err_and_early_return(cx, expr); - check_if_let_some_or_err_and_early_return(cx, expr); +impl QuestionMark { + fn inside_try_block(&self) -> bool { + self.try_block_depth > 0 + } + + /// Checks if the given expression on the given context matches the following structure: + /// + /// ```ignore + /// if option.is_none() { + /// return None; + /// } + /// ``` + /// + /// ```ignore + /// if result.is_err() { + /// return result; + /// } + /// ``` + /// + /// If it matches, it will suggest to use the question mark operator instead + fn check_is_none_or_err_and_early_return<'tcx>(&self, cx: &LateContext<'tcx>, expr: &Expr<'tcx>) { + if_chain! { + if !self.inside_try_block(); + if let Some(higher::If { cond, then, r#else }) = higher::If::hir(expr); + if !is_else_clause(cx.tcx, expr); + if let ExprKind::MethodCall(segment, caller, ..) = &cond.kind; + let caller_ty = cx.typeck_results().expr_ty(caller); + let if_block = IfBlockType::IfIs(caller, caller_ty, segment.ident.name, then, r#else); + if is_early_return(sym::Option, cx, &if_block) || is_early_return(sym::Result, cx, &if_block); + then { + let mut applicability = Applicability::MachineApplicable; + let receiver_str = snippet_with_applicability(cx, caller.span, "..", &mut applicability); + let by_ref = !caller_ty.is_copy_modulo_regions(cx.tcx, cx.param_env) && + !matches!(caller.kind, ExprKind::Call(..) | ExprKind::MethodCall(..)); + let sugg = if let Some(else_inner) = r#else { + if eq_expr_value(cx, caller, peel_blocks(else_inner)) { + format!("Some({receiver_str}?)") + } else { + return; + } + } else { + format!("{receiver_str}{}?;", if by_ref { ".as_ref()" } else { "" }) + }; + + span_lint_and_sugg( + cx, + QUESTION_MARK, + expr.span, + "this block may be rewritten with the `?` operator", + "replace it with", + sugg, + applicability, + ); + } + } + } + + fn check_if_let_some_or_err_and_early_return<'tcx>(&self, cx: &LateContext<'tcx>, expr: &Expr<'tcx>) { + if_chain! { + if !self.inside_try_block(); + if let Some(higher::IfLet { let_pat, let_expr, if_then, if_else }) = higher::IfLet::hir(cx, expr); + if !is_else_clause(cx.tcx, expr); + if let PatKind::TupleStruct(ref path1, [field], ddpos) = let_pat.kind; + if ddpos.as_opt_usize().is_none(); + if let PatKind::Binding(BindingAnnotation(by_ref, _), bind_id, ident, None) = field.kind; + let caller_ty = cx.typeck_results().expr_ty(let_expr); + let if_block = IfBlockType::IfLet( + cx.qpath_res(path1, let_pat.hir_id), + caller_ty, + ident.name, + let_expr, + if_then, + if_else + ); + if (is_early_return(sym::Option, cx, &if_block) && path_to_local_id(peel_blocks(if_then), bind_id)) + || is_early_return(sym::Result, cx, &if_block); + if if_else.map(|e| eq_expr_value(cx, let_expr, peel_blocks(e))).filter(|e| *e).is_none(); + then { + let mut applicability = Applicability::MachineApplicable; + let receiver_str = snippet_with_applicability(cx, let_expr.span, "..", &mut applicability); + let requires_semi = matches!(get_parent_node(cx.tcx, expr.hir_id), Some(Node::Stmt(_))); + let sugg = format!( + "{receiver_str}{}?{}", + if by_ref == ByRef::Yes { ".as_ref()" } else { "" }, + if requires_semi { ";" } else { "" } + ); + span_lint_and_sugg( + cx, + QUESTION_MARK, + expr.span, + "this block may be rewritten with the `?` operator", + "replace it with", + sugg, + applicability, + ); + } + } + } +} + +fn is_try_block(cx: &LateContext<'_>, bl: &rustc_hir::Block<'_>) -> bool { + if let Some(expr) = bl.expr + && let rustc_hir::ExprKind::Call(callee, _) = expr.kind + { + is_path_lang_item(cx, callee, LangItem::TryTraitFromOutput) + } else { + false + } +} + +impl<'tcx> LateLintPass<'tcx> for QuestionMark { + fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) { + if !in_constant(cx, expr.hir_id) { + self.check_is_none_or_err_and_early_return(cx, expr); + self.check_if_let_some_or_err_and_early_return(cx, expr); + } + } + + fn check_block(&mut self, cx: &LateContext<'tcx>, block: &'tcx rustc_hir::Block<'tcx>) { + if is_try_block(cx, block) { + self.try_block_depth += 1; + } + } + + fn check_block_post(&mut self, cx: &LateContext<'tcx>, block: &'tcx rustc_hir::Block<'tcx>) { + if is_try_block(cx, block) { + self.try_block_depth -= 1; } } } diff --git a/tests/ui/question_mark.fixed b/tests/ui/question_mark.fixed index 7f1660f31fa..f257378842b 100644 --- a/tests/ui/question_mark.fixed +++ b/tests/ui/question_mark.fixed @@ -1,4 +1,5 @@ //@run-rustfix +#![feature(try_blocks)] #![allow(unreachable_code)] #![allow(dead_code)] #![allow(clippy::unnecessary_wraps)] @@ -227,6 +228,17 @@ fn pattern() -> Result<(), PatternedError> { fn main() {} +// `?` is not the same as `return None;` if inside of a try block +fn issue8628(a: Option) -> Option { + let b: Option = try { + if a.is_none() { + return None; + } + 32 + }; + b.or(Some(128)) +} + // should not lint, `?` operator not available in const context const fn issue9175(option: Option<()>) -> Option<()> { if option.is_none() { diff --git a/tests/ui/question_mark.rs b/tests/ui/question_mark.rs index a90eae50ed4..29d79b078ac 100644 --- a/tests/ui/question_mark.rs +++ b/tests/ui/question_mark.rs @@ -1,4 +1,5 @@ //@run-rustfix +#![feature(try_blocks)] #![allow(unreachable_code)] #![allow(dead_code)] #![allow(clippy::unnecessary_wraps)] @@ -263,6 +264,17 @@ fn pattern() -> Result<(), PatternedError> { fn main() {} +// `?` is not the same as `return None;` if inside of a try block +fn issue8628(a: Option) -> Option { + let b: Option = try { + if a.is_none() { + return None; + } + 32 + }; + b.or(Some(128)) +} + // should not lint, `?` operator not available in const context const fn issue9175(option: Option<()>) -> Option<()> { if option.is_none() { diff --git a/tests/ui/question_mark.stderr b/tests/ui/question_mark.stderr index 23172d7e535..86d89942cc0 100644 --- a/tests/ui/question_mark.stderr +++ b/tests/ui/question_mark.stderr @@ -1,5 +1,5 @@ error: this block may be rewritten with the `?` operator - --> $DIR/question_mark.rs:7:5 + --> $DIR/question_mark.rs:8:5 | LL | / if a.is_none() { LL | | return None; @@ -9,7 +9,7 @@ LL | | } = note: `-D clippy::question-mark` implied by `-D warnings` error: this block may be rewritten with the `?` operator - --> $DIR/question_mark.rs:52:9 + --> $DIR/question_mark.rs:53:9 | LL | / if (self.opt).is_none() { LL | | return None; @@ -17,7 +17,7 @@ LL | | } | |_________^ help: replace it with: `(self.opt)?;` error: this block may be rewritten with the `?` operator - --> $DIR/question_mark.rs:56:9 + --> $DIR/question_mark.rs:57:9 | LL | / if self.opt.is_none() { LL | | return None @@ -25,7 +25,7 @@ LL | | } | |_________^ help: replace it with: `self.opt?;` error: this block may be rewritten with the `?` operator - --> $DIR/question_mark.rs:60:17 + --> $DIR/question_mark.rs:61:17 | LL | let _ = if self.opt.is_none() { | _________________^ @@ -36,7 +36,7 @@ LL | | }; | |_________^ help: replace it with: `Some(self.opt?)` error: this block may be rewritten with the `?` operator - --> $DIR/question_mark.rs:66:17 + --> $DIR/question_mark.rs:67:17 | LL | let _ = if let Some(x) = self.opt { | _________________^ @@ -47,7 +47,7 @@ LL | | }; | |_________^ help: replace it with: `self.opt?` error: this block may be rewritten with the `?` operator - --> $DIR/question_mark.rs:83:9 + --> $DIR/question_mark.rs:84:9 | LL | / if self.opt.is_none() { LL | | return None; @@ -55,7 +55,7 @@ LL | | } | |_________^ help: replace it with: `self.opt.as_ref()?;` error: this block may be rewritten with the `?` operator - --> $DIR/question_mark.rs:91:9 + --> $DIR/question_mark.rs:92:9 | LL | / if self.opt.is_none() { LL | | return None; @@ -63,7 +63,7 @@ LL | | } | |_________^ help: replace it with: `self.opt.as_ref()?;` error: this block may be rewritten with the `?` operator - --> $DIR/question_mark.rs:99:9 + --> $DIR/question_mark.rs:100:9 | LL | / if self.opt.is_none() { LL | | return None; @@ -71,7 +71,7 @@ LL | | } | |_________^ help: replace it with: `self.opt.as_ref()?;` error: this block may be rewritten with the `?` operator - --> $DIR/question_mark.rs:106:26 + --> $DIR/question_mark.rs:107:26 | LL | let v: &Vec<_> = if let Some(ref v) = self.opt { | __________________________^ @@ -82,7 +82,7 @@ LL | | }; | |_________^ help: replace it with: `self.opt.as_ref()?` error: this block may be rewritten with the `?` operator - --> $DIR/question_mark.rs:116:17 + --> $DIR/question_mark.rs:117:17 | LL | let v = if let Some(v) = self.opt { | _________________^ @@ -93,7 +93,7 @@ LL | | }; | |_________^ help: replace it with: `self.opt?` error: this block may be rewritten with the `?` operator - --> $DIR/question_mark.rs:131:5 + --> $DIR/question_mark.rs:132:5 | LL | / if f().is_none() { LL | | return None; @@ -101,13 +101,13 @@ LL | | } | |_____^ help: replace it with: `f()?;` error: this block may be rewritten with the `?` operator - --> $DIR/question_mark.rs:143:13 + --> $DIR/question_mark.rs:144:13 | LL | let _ = if let Ok(x) = x { x } else { return x }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace it with: `x?` error: this block may be rewritten with the `?` operator - --> $DIR/question_mark.rs:145:5 + --> $DIR/question_mark.rs:146:5 | LL | / if x.is_err() { LL | | return x; @@ -115,7 +115,7 @@ LL | | } | |_____^ help: replace it with: `x?;` error: this block may be rewritten with the `?` operator - --> $DIR/question_mark.rs:196:5 + --> $DIR/question_mark.rs:197:5 | LL | / if let Err(err) = func_returning_result() { LL | | return Err(err); @@ -123,7 +123,7 @@ LL | | } | |_____^ help: replace it with: `func_returning_result()?;` error: this block may be rewritten with the `?` operator - --> $DIR/question_mark.rs:203:5 + --> $DIR/question_mark.rs:204:5 | LL | / if let Err(err) = func_returning_result() { LL | | return Err(err); From b6f194b48c2b7b1cd6a19592a8376056a826d223 Mon Sep 17 00:00:00 2001 From: Catherine <114838443+Centri3@users.noreply.github.com> Date: Wed, 21 Jun 2023 15:56:24 -0500 Subject: [PATCH 248/310] move to `drop_forget_ref` --- clippy_lints/src/declared_lints.rs | 2 +- clippy_lints/src/drop_forget_ref.rs | 46 ++++++++++++++++++++---- clippy_lints/src/lib.rs | 2 -- clippy_lints/src/mem_forget.rs | 54 ----------------------------- tests/ui/mem_forget.stderr | 23 ++++++++++++ 5 files changed, 64 insertions(+), 63 deletions(-) delete mode 100644 clippy_lints/src/mem_forget.rs diff --git a/clippy_lints/src/declared_lints.rs b/clippy_lints/src/declared_lints.rs index 9c1e1f6702d..0eec18a91bc 100644 --- a/clippy_lints/src/declared_lints.rs +++ b/clippy_lints/src/declared_lints.rs @@ -140,6 +140,7 @@ pub(crate) static LINTS: &[&crate::LintInfo] = &[ crate::double_parens::DOUBLE_PARENS_INFO, crate::drop_forget_ref::DROP_NON_DROP_INFO, crate::drop_forget_ref::FORGET_NON_DROP_INFO, + crate::drop_forget_ref::MEM_FORGET_INFO, crate::drop_forget_ref::UNDROPPED_MANUALLY_DROPS_INFO, crate::duplicate_mod::DUPLICATE_MOD_INFO, crate::else_if_without_else::ELSE_IF_WITHOUT_ELSE_INFO, @@ -310,7 +311,6 @@ pub(crate) static LINTS: &[&crate::LintInfo] = &[ crate::matches::TRY_ERR_INFO, crate::matches::WILDCARD_ENUM_MATCH_ARM_INFO, crate::matches::WILDCARD_IN_OR_PATTERNS_INFO, - crate::mem_forget::MEM_FORGET_INFO, crate::mem_replace::MEM_REPLACE_OPTION_WITH_NONE_INFO, crate::mem_replace::MEM_REPLACE_WITH_DEFAULT_INFO, crate::mem_replace::MEM_REPLACE_WITH_UNINIT_INFO, diff --git a/clippy_lints/src/drop_forget_ref.rs b/clippy_lints/src/drop_forget_ref.rs index 9c60edb1794..36b231023a7 100644 --- a/clippy_lints/src/drop_forget_ref.rs +++ b/clippy_lints/src/drop_forget_ref.rs @@ -6,6 +6,7 @@ use rustc_hir::{Arm, Expr, ExprKind, LangItem, Node}; use rustc_lint::{LateContext, LateLintPass}; use rustc_session::{declare_lint_pass, declare_tool_lint}; use rustc_span::sym; +use std::borrow::Cow; declare_clippy_lint! { /// ### What it does @@ -76,6 +77,27 @@ declare_clippy_lint! { "use of safe `std::mem::drop` function to drop a std::mem::ManuallyDrop, which will not drop the inner value" } +declare_clippy_lint! { + /// ### What it does + /// Checks for usage of `std::mem::forget(t)` where `t` is + /// `Drop` or has a field that implements `Drop`. + /// + /// ### Why is this bad? + /// `std::mem::forget(t)` prevents `t` from running its + /// destructor, possibly causing leaks. + /// + /// ### Example + /// ```rust + /// # use std::mem; + /// # use std::rc::Rc; + /// mem::forget(Rc::new(55)) + /// ``` + #[clippy::version = "pre 1.29.0"] + pub MEM_FORGET, + restriction, + "`mem::forget` usage on `Drop` types, likely to cause memory leaks" +} + const DROP_NON_DROP_SUMMARY: &str = "call to `std::mem::drop` with a value that does not implement `Drop`. \ Dropping such a type only extends its contained lifetimes"; const FORGET_NON_DROP_SUMMARY: &str = "call to `std::mem::forget` with a value that does not implement `Drop`. \ @@ -84,7 +106,8 @@ const FORGET_NON_DROP_SUMMARY: &str = "call to `std::mem::forget` with a value t declare_lint_pass!(DropForgetRef => [ DROP_NON_DROP, FORGET_NON_DROP, - UNDROPPED_MANUALLY_DROPS + UNDROPPED_MANUALLY_DROPS, + MEM_FORGET, ]); impl<'tcx> LateLintPass<'tcx> for DropForgetRef { @@ -121,18 +144,29 @@ impl<'tcx> LateLintPass<'tcx> for DropForgetRef { || drop_is_single_call_in_arm ) => { - (DROP_NON_DROP, DROP_NON_DROP_SUMMARY) - }, - sym::mem_forget if !arg_ty.needs_drop(cx.tcx, cx.param_env) => { - (FORGET_NON_DROP, FORGET_NON_DROP_SUMMARY) + (DROP_NON_DROP, DROP_NON_DROP_SUMMARY.into()) }, + sym::mem_forget => { + if arg_ty.needs_drop(cx.tcx, cx.param_env) { + (MEM_FORGET, Cow::Owned(format!( + "usage of `mem::forget` on {}", + if arg_ty.ty_adt_def().map_or(false, |def| def.has_dtor(cx.tcx)) { + "`Drop` type" + } else { + "type with `Drop` fields" + } + ))) + } else { + (FORGET_NON_DROP, FORGET_NON_DROP_SUMMARY.into()) + } + } _ => return, }; span_lint_and_note( cx, lint, expr.span, - msg, + &msg, Some(arg.span), &format!("argument has type `{arg_ty}`"), ); diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index 3fb4e6c8fa5..71b8af7a821 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -196,7 +196,6 @@ mod manual_strip; mod map_unit_fn; mod match_result_ok; mod matches; -mod mem_forget; mod mem_replace; mod methods; mod min_ident_chars; @@ -744,7 +743,6 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: let missing_docs_in_crate_items = conf.missing_docs_in_crate_items; store.register_late_pass(move |_| Box::new(doc::DocMarkdown::new(doc_valid_idents.clone()))); store.register_late_pass(|_| Box::new(neg_multiply::NegMultiply)); - store.register_late_pass(|_| Box::new(mem_forget::MemForget)); store.register_late_pass(|_| Box::new(let_if_seq::LetIfSeq)); store.register_late_pass(|_| Box::new(mixed_read_write_in_expression::EvalOrderDependence)); store.register_late_pass(move |_| Box::new(missing_doc::MissingDoc::new(missing_docs_in_crate_items))); diff --git a/clippy_lints/src/mem_forget.rs b/clippy_lints/src/mem_forget.rs deleted file mode 100644 index fdd55260483..00000000000 --- a/clippy_lints/src/mem_forget.rs +++ /dev/null @@ -1,54 +0,0 @@ -use clippy_utils::diagnostics::span_lint; -use rustc_hir::{Expr, ExprKind}; -use rustc_lint::{LateContext, LateLintPass}; -use rustc_session::{declare_lint_pass, declare_tool_lint}; -use rustc_span::sym; - -declare_clippy_lint! { - /// ### What it does - /// Checks for usage of `std::mem::forget(t)` where `t` is - /// `Drop` or has a field that implements `Drop`. - /// - /// ### Why is this bad? - /// `std::mem::forget(t)` prevents `t` from running its - /// destructor, possibly causing leaks. - /// - /// ### Example - /// ```rust - /// # use std::mem; - /// # use std::rc::Rc; - /// mem::forget(Rc::new(55)) - /// ``` - #[clippy::version = "pre 1.29.0"] - pub MEM_FORGET, - restriction, - "`mem::forget` usage on `Drop` types, likely to cause memory leaks" -} - -declare_lint_pass!(MemForget => [MEM_FORGET]); - -impl<'tcx> LateLintPass<'tcx> for MemForget { - fn check_expr(&mut self, cx: &LateContext<'tcx>, e: &'tcx Expr<'_>) { - if let ExprKind::Call(path_expr, [ref first_arg, ..]) = e.kind - && let ExprKind::Path(ref qpath) = path_expr.kind - && let Some(def_id) = cx.qpath_res(qpath, path_expr.hir_id).opt_def_id() - && cx.tcx.is_diagnostic_item(sym::mem_forget, def_id) - && let forgot_ty = cx.typeck_results().expr_ty(first_arg) - && forgot_ty.needs_drop(cx.tcx, cx.param_env) - { - span_lint( - cx, - MEM_FORGET, - e.span, - &format!( - "usage of `mem::forget` on {}", - if forgot_ty.ty_adt_def().map_or(false, |def| def.has_dtor(cx.tcx)) { - "`Drop` type" - } else { - "type with `Drop` fields" - } - ), - ); - } - } -} diff --git a/tests/ui/mem_forget.stderr b/tests/ui/mem_forget.stderr index 50711120a15..6e3c31804d7 100644 --- a/tests/ui/mem_forget.stderr +++ b/tests/ui/mem_forget.stderr @@ -4,6 +4,11 @@ error: usage of `mem::forget` on `Drop` type LL | memstuff::forget(six); | ^^^^^^^^^^^^^^^^^^^^^ | +note: argument has type `std::sync::Arc` + --> $DIR/mem_forget.rs:14:22 + | +LL | memstuff::forget(six); + | ^^^ = note: `-D clippy::mem-forget` implied by `-D warnings` error: usage of `mem::forget` on `Drop` type @@ -11,18 +16,36 @@ error: usage of `mem::forget` on `Drop` type | LL | std::mem::forget(seven); | ^^^^^^^^^^^^^^^^^^^^^^^ + | +note: argument has type `std::rc::Rc` + --> $DIR/mem_forget.rs:17:22 + | +LL | std::mem::forget(seven); + | ^^^^^ error: usage of `mem::forget` on `Drop` type --> $DIR/mem_forget.rs:20:5 | LL | forgetSomething(eight); | ^^^^^^^^^^^^^^^^^^^^^^ + | +note: argument has type `std::vec::Vec` + --> $DIR/mem_forget.rs:20:21 + | +LL | forgetSomething(eight); + | ^^^^^ error: usage of `mem::forget` on type with `Drop` fields --> $DIR/mem_forget.rs:23:5 | LL | std::mem::forget(string); | ^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: argument has type `std::string::String` + --> $DIR/mem_forget.rs:23:22 + | +LL | std::mem::forget(string); + | ^^^^^^ error: aborting due to 4 previous errors From 242807a9c1cb24ef5e0d665fa9ac696d2a095c71 Mon Sep 17 00:00:00 2001 From: Centri3 <114838443+Centri3@users.noreply.github.com> Date: Tue, 20 Jun 2023 00:39:22 -0500 Subject: [PATCH 249/310] Don't lint `iter_nth_zero` in `next` --- clippy_lints/src/methods/iter_nth.rs | 4 +-- clippy_lints/src/methods/iter_nth_zero.rs | 35 ++++++++++++----------- tests/ui/iter_nth.stderr | 8 +++--- tests/ui/iter_nth_zero.fixed | 15 ++++++++++ tests/ui/iter_nth_zero.rs | 15 ++++++++++ 5 files changed, 54 insertions(+), 23 deletions(-) diff --git a/clippy_lints/src/methods/iter_nth.rs b/clippy_lints/src/methods/iter_nth.rs index ceee12784cb..12104310405 100644 --- a/clippy_lints/src/methods/iter_nth.rs +++ b/clippy_lints/src/methods/iter_nth.rs @@ -20,9 +20,9 @@ pub(super) fn check<'tcx>( let caller_type = if derefs_to_slice(cx, iter_recv, cx.typeck_results().expr_ty(iter_recv)).is_some() { "slice" } else if is_type_diagnostic_item(cx, cx.typeck_results().expr_ty(iter_recv), sym::Vec) { - "Vec" + "`Vec`" } else if is_type_diagnostic_item(cx, cx.typeck_results().expr_ty(iter_recv), sym::VecDeque) { - "VecDeque" + "`VecDeque`" } else { iter_nth_zero::check(cx, expr, nth_recv, nth_arg); return; // caller is not a type that we want to lint diff --git a/clippy_lints/src/methods/iter_nth_zero.rs b/clippy_lints/src/methods/iter_nth_zero.rs index d1609eebfdc..e1f950d5a4a 100644 --- a/clippy_lints/src/methods/iter_nth_zero.rs +++ b/clippy_lints/src/methods/iter_nth_zero.rs @@ -1,8 +1,8 @@ use clippy_utils::consts::{constant, Constant}; use clippy_utils::diagnostics::span_lint_and_sugg; -use clippy_utils::is_trait_method; use clippy_utils::source::snippet_with_applicability; -use if_chain::if_chain; +use clippy_utils::{is_lang_item_or_ctor, is_trait_method}; +use hir::{LangItem, OwnerNode}; use rustc_errors::Applicability; use rustc_hir as hir; use rustc_lint::LateContext; @@ -11,20 +11,21 @@ use rustc_span::sym; use super::ITER_NTH_ZERO; pub(super) fn check(cx: &LateContext<'_>, expr: &hir::Expr<'_>, recv: &hir::Expr<'_>, arg: &hir::Expr<'_>) { - if_chain! { - if is_trait_method(cx, expr, sym::Iterator); - if let Some(Constant::Int(0)) = constant(cx, cx.typeck_results(), arg); - then { - let mut applicability = Applicability::MachineApplicable; - span_lint_and_sugg( - cx, - ITER_NTH_ZERO, - expr.span, - "called `.nth(0)` on a `std::iter::Iterator`, when `.next()` is equivalent", - "try calling `.next()` instead of `.nth(0)`", - format!("{}.next()", snippet_with_applicability(cx, recv.span, "..", &mut applicability)), - applicability, - ); - } + if let OwnerNode::Item(item) = cx.tcx.hir().owner(cx.tcx.hir().get_parent_item(expr.hir_id)) + && let def_id = item.owner_id.to_def_id() + && is_trait_method(cx, expr, sym::Iterator) + && let Some(Constant::Int(0)) = constant(cx, cx.typeck_results(), arg) + && !is_lang_item_or_ctor(cx, def_id, LangItem::IteratorNext) + { + let mut app = Applicability::MachineApplicable; + span_lint_and_sugg( + cx, + ITER_NTH_ZERO, + expr.span, + "called `.nth(0)` on a `std::iter::Iterator`, when `.next()` is equivalent", + "try calling `.next()` instead of `.nth(0)`", + format!("{}.next()", snippet_with_applicability(cx, recv.span, "..", &mut app)), + app, + ); } } diff --git a/tests/ui/iter_nth.stderr b/tests/ui/iter_nth.stderr index 975a5a62ad5..24be814548a 100644 --- a/tests/ui/iter_nth.stderr +++ b/tests/ui/iter_nth.stderr @@ -1,4 +1,4 @@ -error: called `.iter().nth()` on a Vec +error: called `.iter().nth()` on a `Vec` --> $DIR/iter_nth.rs:34:23 | LL | let bad_vec = some_vec.iter().nth(3); @@ -23,7 +23,7 @@ LL | let bad_boxed_slice = boxed_slice.iter().nth(3); | = help: calling `.get()` is both faster and more readable -error: called `.iter().nth()` on a VecDeque +error: called `.iter().nth()` on a `VecDeque` --> $DIR/iter_nth.rs:37:29 | LL | let bad_vec_deque = some_vec_deque.iter().nth(3); @@ -31,7 +31,7 @@ LL | let bad_vec_deque = some_vec_deque.iter().nth(3); | = help: calling `.get()` is both faster and more readable -error: called `.iter_mut().nth()` on a Vec +error: called `.iter_mut().nth()` on a `Vec` --> $DIR/iter_nth.rs:42:23 | LL | let bad_vec = some_vec.iter_mut().nth(3); @@ -47,7 +47,7 @@ LL | let bad_slice = &some_vec[..].iter_mut().nth(3); | = help: calling `.get_mut()` is both faster and more readable -error: called `.iter_mut().nth()` on a VecDeque +error: called `.iter_mut().nth()` on a `VecDeque` --> $DIR/iter_nth.rs:48:29 | LL | let bad_vec_deque = some_vec_deque.iter_mut().nth(3); diff --git a/tests/ui/iter_nth_zero.fixed b/tests/ui/iter_nth_zero.fixed index 587b0d1d366..91f4a7ba0d2 100644 --- a/tests/ui/iter_nth_zero.fixed +++ b/tests/ui/iter_nth_zero.fixed @@ -29,3 +29,18 @@ fn main() { let mut iter2 = s3.iter(); let _unwrapped = iter2.next().unwrap(); } + +struct Issue9820; + +impl Iterator for Issue9820 { + type Item = (); + + fn nth(&mut self, _n: usize) -> Option { + todo!() + } + + // Don't lint in implementations of `next`, as calling `next` in `next` is incorrect + fn next(&mut self) -> Option { + self.nth(0) + } +} diff --git a/tests/ui/iter_nth_zero.rs b/tests/ui/iter_nth_zero.rs index 93b576ec56f..160a895bb7b 100644 --- a/tests/ui/iter_nth_zero.rs +++ b/tests/ui/iter_nth_zero.rs @@ -29,3 +29,18 @@ fn main() { let mut iter2 = s3.iter(); let _unwrapped = iter2.nth(0).unwrap(); } + +struct Issue9820; + +impl Iterator for Issue9820 { + type Item = (); + + fn nth(&mut self, _n: usize) -> Option { + todo!() + } + + // Don't lint in implementations of `next`, as calling `next` in `next` is incorrect + fn next(&mut self) -> Option { + self.nth(0) + } +} From 6a1084c26fdd9653c0b8940bc5d3894ec9bb7d9d Mon Sep 17 00:00:00 2001 From: Catherine <114838443+Centri3@users.noreply.github.com> Date: Thu, 22 Jun 2023 04:31:05 -0500 Subject: [PATCH 250/310] Check if `if` conditions always evaluate to true in `never_loop` --- clippy_lints/src/loops/never_loop.rs | 82 +++++++++++++++++----------- clippy_utils/src/consts.rs | 4 +- tests/ui/large_futures.rs | 1 + tests/ui/large_futures.stderr | 16 +++--- tests/ui/never_loop.rs | 38 +++++++++++++ tests/ui/never_loop.stderr | 40 +++++++++----- 6 files changed, 127 insertions(+), 54 deletions(-) diff --git a/clippy_lints/src/loops/never_loop.rs b/clippy_lints/src/loops/never_loop.rs index 5f1fdf00be8..4f2092492aa 100644 --- a/clippy_lints/src/loops/never_loop.rs +++ b/clippy_lints/src/loops/never_loop.rs @@ -1,22 +1,23 @@ use super::utils::make_iterator_snippet; use super::NEVER_LOOP; -use clippy_utils::diagnostics::span_lint_and_then; +use clippy_utils::consts::constant; use clippy_utils::higher::ForLoop; use clippy_utils::source::snippet; +use clippy_utils::{consts::Constant, diagnostics::span_lint_and_then}; use rustc_errors::Applicability; use rustc_hir::{Block, Destination, Expr, ExprKind, HirId, InlineAsmOperand, Pat, Stmt, StmtKind}; use rustc_lint::LateContext; use rustc_span::Span; use std::iter::{once, Iterator}; -pub(super) fn check( - cx: &LateContext<'_>, - block: &Block<'_>, +pub(super) fn check<'tcx>( + cx: &LateContext<'tcx>, + block: &Block<'tcx>, loop_id: HirId, span: Span, for_loop: Option<&ForLoop<'_>>, ) { - match never_loop_block(block, &mut Vec::new(), loop_id) { + match never_loop_block(cx, block, &mut Vec::new(), loop_id) { NeverLoopResult::AlwaysBreak => { span_lint_and_then(cx, NEVER_LOOP, span, "this loop never actually loops", |diag| { if let Some(ForLoop { @@ -95,7 +96,12 @@ fn combine_branches(b1: NeverLoopResult, b2: NeverLoopResult, ignore_ids: &[HirI } } -fn never_loop_block(block: &Block<'_>, ignore_ids: &mut Vec, main_loop_id: HirId) -> NeverLoopResult { +fn never_loop_block<'tcx>( + cx: &LateContext<'tcx>, + block: &Block<'tcx>, + ignore_ids: &mut Vec, + main_loop_id: HirId, +) -> NeverLoopResult { let iter = block .stmts .iter() @@ -103,10 +109,10 @@ fn never_loop_block(block: &Block<'_>, ignore_ids: &mut Vec, main_loop_id .chain(block.expr.map(|expr| (expr, None))); iter.map(|(e, els)| { - let e = never_loop_expr(e, ignore_ids, main_loop_id); + let e = never_loop_expr(cx, e, ignore_ids, main_loop_id); // els is an else block in a let...else binding els.map_or(e, |els| { - combine_branches(e, never_loop_block(els, ignore_ids, main_loop_id), ignore_ids) + combine_branches(e, never_loop_block(cx, els, ignore_ids, main_loop_id), ignore_ids) }) }) .fold(NeverLoopResult::Otherwise, combine_seq) @@ -122,7 +128,12 @@ fn stmt_to_expr<'tcx>(stmt: &Stmt<'tcx>) -> Option<(&'tcx Expr<'tcx>, Option<&'t } #[allow(clippy::too_many_lines)] -fn never_loop_expr(expr: &Expr<'_>, ignore_ids: &mut Vec, main_loop_id: HirId) -> NeverLoopResult { +fn never_loop_expr<'tcx>( + cx: &LateContext<'tcx>, + expr: &Expr<'tcx>, + ignore_ids: &mut Vec, + main_loop_id: HirId, +) -> NeverLoopResult { match expr.kind { ExprKind::Unary(_, e) | ExprKind::Cast(e, _) @@ -130,45 +141,51 @@ fn never_loop_expr(expr: &Expr<'_>, ignore_ids: &mut Vec, main_loop_id: H | ExprKind::Field(e, _) | ExprKind::AddrOf(_, _, e) | ExprKind::Repeat(e, _) - | ExprKind::DropTemps(e) => never_loop_expr(e, ignore_ids, main_loop_id), - ExprKind::Let(let_expr) => never_loop_expr(let_expr.init, ignore_ids, main_loop_id), - ExprKind::Array(es) | ExprKind::Tup(es) => never_loop_expr_all(&mut es.iter(), ignore_ids, main_loop_id), + | ExprKind::DropTemps(e) => never_loop_expr(cx, e, ignore_ids, main_loop_id), + ExprKind::Let(let_expr) => never_loop_expr(cx, let_expr.init, ignore_ids, main_loop_id), + ExprKind::Array(es) | ExprKind::Tup(es) => never_loop_expr_all(cx, &mut es.iter(), ignore_ids, main_loop_id), ExprKind::MethodCall(_, receiver, es, _) => never_loop_expr_all( + cx, &mut std::iter::once(receiver).chain(es.iter()), ignore_ids, main_loop_id, ), ExprKind::Struct(_, fields, base) => { - let fields = never_loop_expr_all(&mut fields.iter().map(|f| f.expr), ignore_ids, main_loop_id); + let fields = never_loop_expr_all(cx, &mut fields.iter().map(|f| f.expr), ignore_ids, main_loop_id); if let Some(base) = base { - combine_seq(fields, never_loop_expr(base, ignore_ids, main_loop_id)) + combine_seq(fields, never_loop_expr(cx, base, ignore_ids, main_loop_id)) } else { fields } }, - ExprKind::Call(e, es) => never_loop_expr_all(&mut once(e).chain(es.iter()), ignore_ids, main_loop_id), + ExprKind::Call(e, es) => never_loop_expr_all(cx, &mut once(e).chain(es.iter()), ignore_ids, main_loop_id), ExprKind::Binary(_, e1, e2) | ExprKind::Assign(e1, e2, _) | ExprKind::AssignOp(_, e1, e2) - | ExprKind::Index(e1, e2) => never_loop_expr_all(&mut [e1, e2].iter().copied(), ignore_ids, main_loop_id), + | ExprKind::Index(e1, e2) => never_loop_expr_all(cx, &mut [e1, e2].iter().copied(), ignore_ids, main_loop_id), ExprKind::Loop(b, _, _, _) => { // Break can come from the inner loop so remove them. - absorb_break(never_loop_block(b, ignore_ids, main_loop_id)) + absorb_break(never_loop_block(cx, b, ignore_ids, main_loop_id)) }, ExprKind::If(e, e2, e3) => { - let e1 = never_loop_expr(e, ignore_ids, main_loop_id); - let e2 = never_loop_expr(e2, ignore_ids, main_loop_id); + let e1 = never_loop_expr(cx, e, ignore_ids, main_loop_id); + let e2 = never_loop_expr(cx, e2, ignore_ids, main_loop_id); + // If we know the `if` condition evaluates to `true`, don't check everything past it; it + // should just return whatever's evaluated for `e1` and `e2` since `e3` is unreachable + if let Some(Constant::Bool(true)) = constant(cx, cx.typeck_results(), e) { + return combine_seq(e1, e2); + } let e3 = e3.as_ref().map_or(NeverLoopResult::Otherwise, |e| { - never_loop_expr(e, ignore_ids, main_loop_id) + never_loop_expr(cx, e, ignore_ids, main_loop_id) }); combine_seq(e1, combine_branches(e2, e3, ignore_ids)) }, ExprKind::Match(e, arms, _) => { - let e = never_loop_expr(e, ignore_ids, main_loop_id); + let e = never_loop_expr(cx, e, ignore_ids, main_loop_id); if arms.is_empty() { e } else { - let arms = never_loop_expr_branch(&mut arms.iter().map(|a| a.body), ignore_ids, main_loop_id); + let arms = never_loop_expr_branch(cx, &mut arms.iter().map(|a| a.body), ignore_ids, main_loop_id); combine_seq(e, arms) } }, @@ -176,7 +193,7 @@ fn never_loop_expr(expr: &Expr<'_>, ignore_ids: &mut Vec, main_loop_id: H if l.is_some() { ignore_ids.push(b.hir_id); } - let ret = never_loop_block(b, ignore_ids, main_loop_id); + let ret = never_loop_block(cx, b, ignore_ids, main_loop_id); if l.is_some() { ignore_ids.pop(); } @@ -198,11 +215,11 @@ fn never_loop_expr(expr: &Expr<'_>, ignore_ids: &mut Vec, main_loop_id: H // checks if break targets a block instead of a loop ExprKind::Break(Destination { target_id: Ok(t), .. }, e) if ignore_ids.contains(&t) => e .map_or(NeverLoopResult::IgnoreUntilEnd(t), |e| { - never_loop_expr(e, ignore_ids, main_loop_id) + never_loop_expr(cx, e, ignore_ids, main_loop_id) }), ExprKind::Break(_, e) | ExprKind::Ret(e) => e.as_ref().map_or(NeverLoopResult::AlwaysBreak, |e| { combine_seq( - never_loop_expr(e, ignore_ids, main_loop_id), + never_loop_expr(cx, e, ignore_ids, main_loop_id), NeverLoopResult::AlwaysBreak, ) }), @@ -211,12 +228,13 @@ fn never_loop_expr(expr: &Expr<'_>, ignore_ids: &mut Vec, main_loop_id: H .iter() .map(|(o, _)| match o { InlineAsmOperand::In { expr, .. } | InlineAsmOperand::InOut { expr, .. } => { - never_loop_expr(expr, ignore_ids, main_loop_id) + never_loop_expr(cx, expr, ignore_ids, main_loop_id) }, InlineAsmOperand::Out { expr, .. } => { - never_loop_expr_all(&mut expr.iter().copied(), ignore_ids, main_loop_id) + never_loop_expr_all(cx, &mut expr.iter().copied(), ignore_ids, main_loop_id) }, InlineAsmOperand::SplitInOut { in_expr, out_expr, .. } => never_loop_expr_all( + cx, &mut once(*in_expr).chain(out_expr.iter().copied()), ignore_ids, main_loop_id, @@ -236,22 +254,24 @@ fn never_loop_expr(expr: &Expr<'_>, ignore_ids: &mut Vec, main_loop_id: H } } -fn never_loop_expr_all<'a, T: Iterator>>( +fn never_loop_expr_all<'tcx, T: Iterator>>( + cx: &LateContext<'tcx>, es: &mut T, ignore_ids: &mut Vec, main_loop_id: HirId, ) -> NeverLoopResult { - es.map(|e| never_loop_expr(e, ignore_ids, main_loop_id)) + es.map(|e| never_loop_expr(cx, e, ignore_ids, main_loop_id)) .fold(NeverLoopResult::Otherwise, combine_seq) } -fn never_loop_expr_branch<'a, T: Iterator>>( +fn never_loop_expr_branch<'tcx, T: Iterator>>( + cx: &LateContext<'tcx>, e: &mut T, ignore_ids: &mut Vec, main_loop_id: HirId, ) -> NeverLoopResult { e.fold(NeverLoopResult::AlwaysBreak, |a, b| { - combine_branches(a, never_loop_expr(b, ignore_ids, main_loop_id), ignore_ids) + combine_branches(a, never_loop_expr(cx, b, ignore_ids, main_loop_id), ignore_ids) }) } diff --git a/clippy_utils/src/consts.rs b/clippy_utils/src/consts.rs index 72582ba7e78..03dc9ca56ff 100644 --- a/clippy_utils/src/consts.rs +++ b/clippy_utils/src/consts.rs @@ -6,7 +6,7 @@ use if_chain::if_chain; use rustc_ast::ast::{self, LitFloatType, LitKind}; use rustc_data_structures::sync::Lrc; use rustc_hir::def::{DefKind, Res}; -use rustc_hir::{BinOp, BinOpKind, Block, Expr, ExprKind, HirId, Item, ItemKind, Node, QPath, UnOp}; +use rustc_hir::{AnonConst, BinOp, BinOpKind, Block, Expr, ExprKind, HirId, Item, ItemKind, Node, QPath, UnOp}; use rustc_lexer::tokenize; use rustc_lint::LateContext; use rustc_middle::mir; @@ -344,6 +344,8 @@ impl<'a, 'tcx> ConstEvalLateContext<'a, 'tcx> { /// Simple constant folding: Insert an expression, get a constant or none. pub fn expr(&mut self, e: &Expr<'_>) -> Option> { match e.kind { + ExprKind::ConstBlock(AnonConst { body, .. }) => self.expr(self.lcx.tcx.hir().body(body).value), + ExprKind::DropTemps(e) => self.expr(e), ExprKind::Path(ref qpath) => self.fetch_path(qpath, e.hir_id, self.typeck_results.expr_ty(e)), ExprKind::Block(block, _) => self.block(block), ExprKind::Lit(lit) => { diff --git a/tests/ui/large_futures.rs b/tests/ui/large_futures.rs index 4a8ba995da5..e0f6b3d9d3b 100644 --- a/tests/ui/large_futures.rs +++ b/tests/ui/large_futures.rs @@ -1,5 +1,6 @@ #![feature(generators)] #![warn(clippy::large_futures)] +#![allow(clippy::never_loop)] #![allow(clippy::future_not_send)] #![allow(clippy::manual_async_fn)] diff --git a/tests/ui/large_futures.stderr b/tests/ui/large_futures.stderr index 67e0fceff6e..5bcf054884e 100644 --- a/tests/ui/large_futures.stderr +++ b/tests/ui/large_futures.stderr @@ -1,5 +1,5 @@ error: large future with a size of 16385 bytes - --> $DIR/large_futures.rs:10:9 + --> $DIR/large_futures.rs:11:9 | LL | big_fut([0u8; 1024 * 16]).await; | ^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider `Box::pin` on it: `Box::pin(big_fut([0u8; 1024 * 16]))` @@ -7,37 +7,37 @@ LL | big_fut([0u8; 1024 * 16]).await; = note: `-D clippy::large-futures` implied by `-D warnings` error: large future with a size of 16386 bytes - --> $DIR/large_futures.rs:12:5 + --> $DIR/large_futures.rs:13: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 + --> $DIR/large_futures.rs:17: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 + --> $DIR/large_futures.rs:21: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 + --> $DIR/large_futures.rs:28: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 + --> $DIR/large_futures.rs:29: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 + --> $DIR/large_futures.rs:41:5 | LL | / async { LL | | let x = [0i32; 1024 * 16]; @@ -56,7 +56,7 @@ LL + }) | error: large future with a size of 65540 bytes - --> $DIR/large_futures.rs:51:13 + --> $DIR/large_futures.rs:52:13 | LL | / async { LL | | let x = [0i32; 1024 * 16]; diff --git a/tests/ui/never_loop.rs b/tests/ui/never_loop.rs index 29821ff96fc..eb179f30e75 100644 --- a/tests/ui/never_loop.rs +++ b/tests/ui/never_loop.rs @@ -1,4 +1,6 @@ +#![feature(inline_const)] #![allow( + clippy::eq_op, clippy::single_match, unused_assignments, unused_variables, @@ -295,6 +297,42 @@ pub fn test24() { } } +// Do not lint, we can evaluate `true` to always succeed thus can short-circuit before the `return` +pub fn test25() { + loop { + 'label: { + if const { true } { + break 'label; + } + return; + } + } +} + +pub fn test26() { + loop { + 'label: { + if 1 == 1 { + break 'label; + } + return; + } + } +} + +pub fn test27() { + loop { + 'label: { + let x = true; + // Lints because we cannot prove it's always `true` + if x { + break 'label; + } + return; + } + } +} + fn main() { test1(); test2(); diff --git a/tests/ui/never_loop.stderr b/tests/ui/never_loop.stderr index b2eafb345e3..0446c09cd5b 100644 --- a/tests/ui/never_loop.stderr +++ b/tests/ui/never_loop.stderr @@ -1,5 +1,5 @@ error: this loop never actually loops - --> $DIR/never_loop.rs:10:5 + --> $DIR/never_loop.rs:12:5 | LL | / loop { LL | | // clippy::never_loop @@ -13,7 +13,7 @@ LL | | } = note: `#[deny(clippy::never_loop)]` on by default error: this loop never actually loops - --> $DIR/never_loop.rs:32:5 + --> $DIR/never_loop.rs:34:5 | LL | / loop { LL | | // never loops @@ -23,7 +23,7 @@ LL | | } | |_____^ error: this loop never actually loops - --> $DIR/never_loop.rs:52:5 + --> $DIR/never_loop.rs:54:5 | LL | / loop { LL | | // never loops @@ -35,7 +35,7 @@ LL | | } | |_____^ error: this loop never actually loops - --> $DIR/never_loop.rs:54:9 + --> $DIR/never_loop.rs:56:9 | LL | / while i == 0 { LL | | // never loops @@ -44,7 +44,7 @@ LL | | } | |_________^ error: this loop never actually loops - --> $DIR/never_loop.rs:66:9 + --> $DIR/never_loop.rs:68:9 | LL | / loop { LL | | // never loops @@ -56,7 +56,7 @@ LL | | } | |_________^ error: this loop never actually loops - --> $DIR/never_loop.rs:102:5 + --> $DIR/never_loop.rs:104:5 | LL | / while let Some(y) = x { LL | | // never loops @@ -65,7 +65,7 @@ LL | | } | |_____^ error: this loop never actually loops - --> $DIR/never_loop.rs:109:5 + --> $DIR/never_loop.rs:111:5 | LL | / for x in 0..10 { LL | | // never loops @@ -82,7 +82,7 @@ LL | if let Some(x) = (0..10).next() { | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ error: this loop never actually loops - --> $DIR/never_loop.rs:157:5 + --> $DIR/never_loop.rs:159:5 | LL | / 'outer: while a { LL | | // never loops @@ -94,7 +94,7 @@ LL | | } | |_____^ error: this loop never actually loops - --> $DIR/never_loop.rs:172:9 + --> $DIR/never_loop.rs:174:9 | LL | / while false { LL | | break 'label; @@ -102,7 +102,7 @@ LL | | } | |_________^ error: this loop never actually loops - --> $DIR/never_loop.rs:223:13 + --> $DIR/never_loop.rs:225:13 | LL | let _ = loop { | _____________^ @@ -115,7 +115,7 @@ LL | | }; | |_____^ error: this loop never actually loops - --> $DIR/never_loop.rs:244:5 + --> $DIR/never_loop.rs:246:5 | LL | / 'a: loop { LL | | 'b: { @@ -127,7 +127,7 @@ LL | | } | |_____^ error: sub-expression diverges - --> $DIR/never_loop.rs:247:17 + --> $DIR/never_loop.rs:249:17 | LL | break 'a; | ^^^^^^^^ @@ -135,7 +135,7 @@ LL | break 'a; = note: `-D clippy::diverging-sub-expression` implied by `-D warnings` error: this loop never actually loops - --> $DIR/never_loop.rs:278:13 + --> $DIR/never_loop.rs:280:13 | LL | / for _ in 0..20 { LL | | break 'block; @@ -147,5 +147,17 @@ help: if you need the first element of the iterator, try writing LL | if let Some(_) = (0..20).next() { | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -error: aborting due to 13 previous errors +error: this loop never actually loops + --> $DIR/never_loop.rs:324:5 + | +LL | / loop { +LL | | 'label: { +LL | | let x = true; +LL | | // Lints because we cannot prove it's always `true` +... | +LL | | } +LL | | } + | |_____^ + +error: aborting due to 14 previous errors From 33b6d0d206f4519d0a196c1ae490e8e13c8fbcc6 Mon Sep 17 00:00:00 2001 From: y21 <30553356+y21@users.noreply.github.com> Date: Thu, 22 Jun 2023 17:19:43 +0200 Subject: [PATCH 251/310] rename MSRV alias, add MSRV to lint doc --- clippy_lints/src/trait_bounds.rs | 2 +- clippy_lints/src/utils/conf.rs | 2 +- clippy_utils/src/msrvs.rs | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/clippy_lints/src/trait_bounds.rs b/clippy_lints/src/trait_bounds.rs index 78e27b775fb..6db330dfa61 100644 --- a/clippy_lints/src/trait_bounds.rs +++ b/clippy_lints/src/trait_bounds.rs @@ -232,7 +232,7 @@ impl TraitBounds { /// Is the given bound a `?Sized` bound, and is combining it (i.e. `T: X + ?Sized`) an error on /// this MSRV? See for details. fn cannot_combine_maybe_bound(&self, cx: &LateContext<'_>, bound: &GenericBound<'_>) -> bool { - if !self.msrv.meets(msrvs::COMBINED_MAYBE_BOUND) + if !self.msrv.meets(msrvs::MAYBE_BOUND_IN_WHERE) && let GenericBound::Trait(tr, TraitBoundModifier::Maybe) = bound { cx.tcx.lang_items().get(LangItem::Sized) == tr.trait_ref.path.res.opt_def_id() diff --git a/clippy_lints/src/utils/conf.rs b/clippy_lints/src/utils/conf.rs index 3cf2fbf1f28..54ee960c472 100644 --- a/clippy_lints/src/utils/conf.rs +++ b/clippy_lints/src/utils/conf.rs @@ -293,7 +293,7 @@ define_Conf! { /// /// Suppress lints whenever the suggested change would cause breakage for other crates. (avoid_breaking_exported_api: bool = true), - /// Lint: MANUAL_SPLIT_ONCE, MANUAL_STR_REPEAT, CLONED_INSTEAD_OF_COPIED, REDUNDANT_FIELD_NAMES, REDUNDANT_STATIC_LIFETIMES, FILTER_MAP_NEXT, CHECKED_CONVERSIONS, MANUAL_RANGE_CONTAINS, USE_SELF, MEM_REPLACE_WITH_DEFAULT, MANUAL_NON_EXHAUSTIVE, OPTION_AS_REF_DEREF, MAP_UNWRAP_OR, MATCH_LIKE_MATCHES_MACRO, MANUAL_STRIP, MISSING_CONST_FOR_FN, UNNESTED_OR_PATTERNS, FROM_OVER_INTO, PTR_AS_PTR, IF_THEN_SOME_ELSE_NONE, APPROX_CONSTANT, DEPRECATED_CFG_ATTR, INDEX_REFUTABLE_SLICE, MAP_CLONE, BORROW_AS_PTR, MANUAL_BITS, ERR_EXPECT, CAST_ABS_TO_UNSIGNED, UNINLINED_FORMAT_ARGS, MANUAL_CLAMP, MANUAL_LET_ELSE, UNCHECKED_DURATION_SUBTRACTION, COLLAPSIBLE_STR_REPLACE, SEEK_FROM_CURRENT, SEEK_REWIND, UNNECESSARY_LAZY_EVALUATIONS, TRANSMUTE_PTR_TO_REF, ALMOST_COMPLETE_RANGE, NEEDLESS_BORROW, DERIVABLE_IMPLS, MANUAL_IS_ASCII_CHECK, MANUAL_REM_EUCLID, MANUAL_RETAIN. + /// Lint: MANUAL_SPLIT_ONCE, MANUAL_STR_REPEAT, CLONED_INSTEAD_OF_COPIED, REDUNDANT_FIELD_NAMES, REDUNDANT_STATIC_LIFETIMES, FILTER_MAP_NEXT, CHECKED_CONVERSIONS, MANUAL_RANGE_CONTAINS, USE_SELF, MEM_REPLACE_WITH_DEFAULT, MANUAL_NON_EXHAUSTIVE, OPTION_AS_REF_DEREF, MAP_UNWRAP_OR, MATCH_LIKE_MATCHES_MACRO, MANUAL_STRIP, MISSING_CONST_FOR_FN, UNNESTED_OR_PATTERNS, FROM_OVER_INTO, PTR_AS_PTR, IF_THEN_SOME_ELSE_NONE, APPROX_CONSTANT, DEPRECATED_CFG_ATTR, INDEX_REFUTABLE_SLICE, MAP_CLONE, BORROW_AS_PTR, MANUAL_BITS, ERR_EXPECT, CAST_ABS_TO_UNSIGNED, UNINLINED_FORMAT_ARGS, MANUAL_CLAMP, MANUAL_LET_ELSE, UNCHECKED_DURATION_SUBTRACTION, COLLAPSIBLE_STR_REPLACE, SEEK_FROM_CURRENT, SEEK_REWIND, UNNECESSARY_LAZY_EVALUATIONS, TRANSMUTE_PTR_TO_REF, ALMOST_COMPLETE_RANGE, NEEDLESS_BORROW, DERIVABLE_IMPLS, MANUAL_IS_ASCII_CHECK, MANUAL_REM_EUCLID, MANUAL_RETAIN, TYPE_REPETITION_IN_BOUNDS. /// /// The minimum rust version that the project supports (msrv: Option = None), diff --git a/clippy_utils/src/msrvs.rs b/clippy_utils/src/msrvs.rs index b1f336461d1..0a4c3418a08 100644 --- a/clippy_utils/src/msrvs.rs +++ b/clippy_utils/src/msrvs.rs @@ -47,7 +47,7 @@ msrv_aliases! { 1,18,0 { HASH_MAP_RETAIN, HASH_SET_RETAIN } 1,17,0 { FIELD_INIT_SHORTHAND, STATIC_IN_CONST, EXPECT_ERR } 1,16,0 { STR_REPEAT } - 1,15,0 { COMBINED_MAYBE_BOUND } + 1,15,0 { MAYBE_BOUND_IN_WHERE } } fn parse_msrv(msrv: &str, sess: Option<&Session>, span: Option) -> Option { From 533a8191154a8cdfc1fe1a6113223dcbd91ddd03 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Mon, 19 Jun 2023 20:46:46 +0000 Subject: [PATCH 252/310] Migrate item_bounds to ty::Clause --- clippy_lints/src/future_not_send.rs | 2 +- clippy_utils/src/ty.rs | 14 +++++++------- 2 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 a391b76910a..818ebd1134d 100644 --- a/clippy_lints/src/future_not_send.rs +++ b/clippy_lints/src/future_not_send.rs @@ -67,7 +67,7 @@ impl<'tcx> LateLintPass<'tcx> for FutureNotSend { 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() { + if let Some(trait_pred) = p.as_trait_clause() { if Some(trait_pred.skip_binder().trait_ref.def_id) == cx.tcx.lang_items().future_trait() { is_future = true; break; diff --git a/clippy_utils/src/ty.rs b/clippy_utils/src/ty.rs index 12f18614d71..2b185943c59 100644 --- a/clippy_utils/src/ty.rs +++ b/clippy_utils/src/ty.rs @@ -94,7 +94,7 @@ pub fn contains_ty_adt_constructor_opaque<'tcx>(cx: &LateContext<'tcx>, ty: Ty<' match predicate.kind().skip_binder() { // For `impl Trait`, it will register a predicate of `T: Trait`, so we go through // and check substitutions to find `U`. - ty::PredicateKind::Clause(ty::ClauseKind::Trait(trait_predicate)) => { + ty::ClauseKind::Trait(trait_predicate) => { if trait_predicate .trait_ref .substs @@ -107,7 +107,7 @@ pub fn contains_ty_adt_constructor_opaque<'tcx>(cx: &LateContext<'tcx>, ty: Ty<' }, // For `impl Trait`, it will register a predicate of `::Assoc = U`, // so we check the term for `U`. - ty::PredicateKind::Clause(ty::ClauseKind::Projection(projection_predicate)) => { + ty::ClauseKind::Projection(projection_predicate) => { if let ty::TermKind::Ty(ty) = projection_predicate.term.unpack() { if contains_ty_adt_constructor_opaque_inner(cx, ty, needle, seen) { return true; @@ -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.explicit_item_bounds(def_id).skip_binder() { - if let ty::PredicateKind::Clause(ty::ClauseKind::Trait(trait_predicate)) = predicate.kind().skip_binder() { + if let ty::ClauseKind::Trait(trait_predicate) = predicate.kind().skip_binder() { if cx.tcx.has_attr(trait_predicate.trait_ref.def_id, sym::must_use) { return true; } @@ -665,7 +665,7 @@ pub fn ty_sig<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>) -> Option sig_from_bounds( cx, ty, - cx.tcx.item_bounds(def_id).subst(cx.tcx, substs), + cx.tcx.item_bounds(def_id).subst_iter(cx.tcx, substs).map(|c| c.as_predicate()), cx.tcx.opt_parent(def_id), ), ty::FnPtr(sig) => Some(ExprFnSig::Sig(sig, None)), @@ -698,7 +698,7 @@ pub fn ty_sig<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>) -> Option( cx: &LateContext<'tcx>, ty: Ty<'tcx>, - predicates: &'tcx [Predicate<'tcx>], + predicates: impl IntoIterator>, predicates_id: Option, ) -> Option> { let mut inputs = None; @@ -747,7 +747,7 @@ fn sig_for_projection<'tcx>(cx: &LateContext<'tcx>, ty: AliasTy<'tcx>) -> Option .subst_iter_copied(cx.tcx, ty.substs) { match pred.kind().skip_binder() { - PredicateKind::Clause(ty::ClauseKind::Trait(p)) + ty::ClauseKind::Trait(p) if (lang_items.fn_trait() == Some(p.def_id()) || lang_items.fn_mut_trait() == Some(p.def_id()) || lang_items.fn_once_trait() == Some(p.def_id())) => @@ -760,7 +760,7 @@ fn sig_for_projection<'tcx>(cx: &LateContext<'tcx>, ty: AliasTy<'tcx>) -> Option } inputs = Some(i); }, - PredicateKind::Clause(ty::ClauseKind::Projection(p)) + ty::ClauseKind::Projection(p) if Some(p.projection_ty.def_id) == lang_items.fn_once_output() => { if output.is_some() { From 75f9fbc93d7eb1fa0182c8491f6152917055dac4 Mon Sep 17 00:00:00 2001 From: y21 <30553356+y21@users.noreply.github.com> Date: Fri, 23 Jun 2023 02:07:05 +0200 Subject: [PATCH 253/310] update lint configuration --- book/src/lint_configuration.md | 1 + 1 file changed, 1 insertion(+) diff --git a/book/src/lint_configuration.md b/book/src/lint_configuration.md index 32cc5d1edcc..dd605b76a3d 100644 --- a/book/src/lint_configuration.md +++ b/book/src/lint_configuration.md @@ -147,6 +147,7 @@ The minimum rust version that the project supports * [`manual_is_ascii_check`](https://rust-lang.github.io/rust-clippy/master/index.html#manual_is_ascii_check) * [`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) +* [`type_repetition_in_bounds`](https://rust-lang.github.io/rust-clippy/master/index.html#type_repetition_in_bounds) ## `cognitive-complexity-threshold` From db4efe3f6dbe6286b579e3cd6c71d9347ec2f1a5 Mon Sep 17 00:00:00 2001 From: Catherine <114838443+Centri3@users.noreply.github.com> Date: Sat, 24 Jun 2023 03:03:05 -0500 Subject: [PATCH 254/310] Don't lint `ptr_arg` when return type uses Cow's lifetime --- clippy_lints/src/ptr.rs | 105 ++++++++++++++++++++++++++-------------- tests/ui/ptr_arg.rs | 33 ++++++++++++- tests/ui/ptr_arg.stderr | 60 +++++++++++++++-------- 3 files changed, 141 insertions(+), 57 deletions(-) diff --git a/clippy_lints/src/ptr.rs b/clippy_lints/src/ptr.rs index fc550936165..e8854394150 100644 --- a/clippy_lints/src/ptr.rs +++ b/clippy_lints/src/ptr.rs @@ -5,6 +5,7 @@ use clippy_utils::source::snippet_opt; use clippy_utils::ty::expr_sig; use clippy_utils::visitors::contains_unsafe_block; use clippy_utils::{get_expr_use_or_unification_node, is_lint_allowed, path_def_id, path_to_local, paths}; +use hir::LifetimeName; use if_chain::if_chain; use rustc_errors::{Applicability, MultiSpan}; use rustc_hir::def_id::DefId; @@ -15,6 +16,7 @@ use rustc_hir::{ ImplItemKind, ItemKind, Lifetime, Mutability, Node, Param, PatKind, QPath, TraitFn, TraitItem, TraitItemKind, TyKind, Unsafety, }; +use rustc_hir_analysis::hir_ty_to_ty; use rustc_infer::infer::TyCtxtInferExt; use rustc_infer::traits::{Obligation, ObligationCause}; use rustc_lint::{LateContext, LateLintPass}; @@ -166,6 +168,7 @@ impl<'tcx> LateLintPass<'tcx> for Ptr { cx, cx.tcx.fn_sig(item.owner_id).subst_identity().skip_binder().inputs(), sig.decl.inputs, + &sig.decl.output, &[], ) .filter(|arg| arg.mutability() == Mutability::Not) @@ -218,7 +221,7 @@ impl<'tcx> LateLintPass<'tcx> for Ptr { check_mut_from_ref(cx, sig, Some(body)); let decl = sig.decl; let sig = cx.tcx.fn_sig(item_id).subst_identity().skip_binder(); - let lint_args: Vec<_> = check_fn_args(cx, sig.inputs(), decl.inputs, body.params) + let lint_args: Vec<_> = check_fn_args(cx, sig.inputs(), decl.inputs, &decl.output, body.params) .filter(|arg| !is_trait_item || arg.mutability() == Mutability::Not) .collect(); let results = check_ptr_arg_usage(cx, body, &lint_args); @@ -407,29 +410,27 @@ impl<'tcx> DerefTy<'tcx> { } } +#[expect(clippy::too_many_lines)] fn check_fn_args<'cx, 'tcx: 'cx>( cx: &'cx LateContext<'tcx>, tys: &'tcx [Ty<'tcx>], hir_tys: &'tcx [hir::Ty<'tcx>], + ret_ty: &'tcx FnRetTy<'tcx>, params: &'tcx [Param<'tcx>], ) -> impl Iterator> + 'cx { tys.iter() .zip(hir_tys.iter()) .enumerate() - .filter_map(|(i, (ty, hir_ty))| { - if_chain! { - if let ty::Ref(_, ty, mutability) = *ty.kind(); - if let ty::Adt(adt, substs) = *ty.kind(); - - if let TyKind::Ref(lt, ref ty) = hir_ty.kind; - if let TyKind::Path(QPath::Resolved(None, path)) = ty.ty.kind; - + .filter_map(move |(i, (ty, hir_ty))| { + if let ty::Ref(_, ty, mutability) = *ty.kind() + && let ty::Adt(adt, substs) = *ty.kind() + && let TyKind::Ref(lt, ref ty) = hir_ty.kind + && let TyKind::Path(QPath::Resolved(None, path)) = ty.ty.kind // Check that the name as typed matches the actual name of the type. // e.g. `fn foo(_: &Foo)` shouldn't trigger the lint when `Foo` is an alias for `Vec` - if let [.., name] = path.segments; - if cx.tcx.item_name(adt.did()) == name.ident.name; - - then { + && let [.., name] = path.segments + && cx.tcx.item_name(adt.did()) == name.ident.name + { let emission_id = params.get(i).map_or(hir_ty.hir_id, |param| param.hir_id); let (method_renames, deref_ty) = match cx.tcx.get_diagnostic_name(adt.did()) { Some(sym::Vec) => ( @@ -454,30 +455,65 @@ fn check_fn_args<'cx, 'tcx: 'cx>( DerefTy::Path, ), Some(sym::Cow) if mutability == Mutability::Not => { - let ty_name = name.args + if let Some((lifetime, ty)) = name.args .and_then(|args| { - args.args.iter().find_map(|a| match a { - GenericArg::Type(x) => Some(x), - _ => None, - }) + if let [GenericArg::Lifetime(lifetime), ty] = args.args { + return Some((lifetime, ty)); + } + None }) - .and_then(|arg| snippet_opt(cx, arg.span)) - .unwrap_or_else(|| substs.type_at(1).to_string()); - span_lint_hir_and_then( - cx, - PTR_ARG, - emission_id, - hir_ty.span, - "using a reference to `Cow` is not recommended", - |diag| { - diag.span_suggestion( - hir_ty.span, - "change this to", - format!("&{}{ty_name}", mutability.prefix_str()), - Applicability::Unspecified, - ); + { + if !lifetime.is_anonymous() + && let FnRetTy::Return(ret_ty) = ret_ty + && let ret_ty = hir_ty_to_ty(cx.tcx, ret_ty) + && ret_ty + .walk() + .filter_map(|arg| { + arg.as_region().and_then(|lifetime| { + match lifetime.kind() { + ty::ReEarlyBound(r) => Some(r.def_id), + ty::ReLateBound(_, r) => r.kind.get_id(), + ty::ReFree(r) => r.bound_region.get_id(), + ty::ReStatic + | ty::ReVar(_) + | ty::RePlaceholder(_) + | ty::ReErased + | ty::ReError(_) => None, + } + }) + }) + .any(|def_id| { + matches!( + lifetime.res, + LifetimeName::Param(param_def_id) if def_id + .as_local() + .is_some_and(|def_id| def_id == param_def_id), + ) + }) + { + // `&Cow<'a, T>` when the return type uses 'a is okay + return None; } - ); + + let ty_name = + snippet_opt(cx, ty.span()).unwrap_or_else(|| substs.type_at(1).to_string()); + + span_lint_hir_and_then( + cx, + PTR_ARG, + emission_id, + hir_ty.span, + "using a reference to `Cow` is not recommended", + |diag| { + diag.span_suggestion( + hir_ty.span, + "change this to", + format!("&{}{ty_name}", mutability.prefix_str()), + Applicability::Unspecified, + ); + } + ); + } return None; }, _ => return None, @@ -495,7 +531,6 @@ fn check_fn_args<'cx, 'tcx: 'cx>( }, deref_ty, }); - } } None }) diff --git a/tests/ui/ptr_arg.rs b/tests/ui/ptr_arg.rs index 5f54101ca15..709f74ee6aa 100644 --- a/tests/ui/ptr_arg.rs +++ b/tests/ui/ptr_arg.rs @@ -1,5 +1,10 @@ #![feature(lint_reasons)] -#![allow(unused, clippy::many_single_char_names, clippy::redundant_clone)] +#![allow( + unused, + clippy::many_single_char_names, + clippy::needless_lifetimes, + clippy::redundant_clone +)] #![warn(clippy::ptr_arg)] use std::borrow::Cow; @@ -235,3 +240,29 @@ fn dyn_trait(a: &mut Vec, b: &mut String, c: &mut PathBuf) { takes_dyn(b); takes_dyn(c); } + +mod issue_9218 { + use std::borrow::Cow; + + fn cow_non_elided_lifetime<'a>(input: &Cow<'a, str>) -> &'a str { + todo!() + } + + // This one has an anonymous lifetime so it's not okay + fn cow_elided_lifetime<'a>(input: &'a Cow) -> &'a str { + todo!() + } + + // These two's return types don't use use 'a so it's not okay + fn cow_bad_ret_ty_1<'a>(input: &'a Cow<'a, str>) -> &'static str { + todo!() + } + fn cow_bad_ret_ty_2<'a, 'b>(input: &'a Cow<'a, str>) -> &'b str { + todo!() + } + + // Inferred to be `&'a str`, afaik. + fn cow_good_ret_ty<'a>(input: &'a Cow<'a, str>) -> &str { + todo!() + } +} diff --git a/tests/ui/ptr_arg.stderr b/tests/ui/ptr_arg.stderr index 6b4de98ce88..d663b070b9c 100644 --- a/tests/ui/ptr_arg.stderr +++ b/tests/ui/ptr_arg.stderr @@ -1,5 +1,5 @@ error: writing `&Vec` instead of `&[_]` involves a new object where a slice will do - --> $DIR/ptr_arg.rs:8:14 + --> $DIR/ptr_arg.rs:13:14 | LL | fn do_vec(x: &Vec) { | ^^^^^^^^^ help: change this to: `&[i64]` @@ -7,43 +7,43 @@ LL | fn do_vec(x: &Vec) { = note: `-D clippy::ptr-arg` implied by `-D warnings` error: writing `&mut Vec` instead of `&mut [_]` involves a new object where a slice will do - --> $DIR/ptr_arg.rs:12:18 + --> $DIR/ptr_arg.rs:17:18 | LL | fn do_vec_mut(x: &mut Vec) { | ^^^^^^^^^^^^^ help: change this to: `&mut [i64]` error: writing `&String` instead of `&str` involves a new object where a slice will do - --> $DIR/ptr_arg.rs:16:14 + --> $DIR/ptr_arg.rs:21:14 | LL | fn do_str(x: &String) { | ^^^^^^^ help: change this to: `&str` error: writing `&mut String` instead of `&mut str` involves a new object where a slice will do - --> $DIR/ptr_arg.rs:20:18 + --> $DIR/ptr_arg.rs:25:18 | LL | fn do_str_mut(x: &mut String) { | ^^^^^^^^^^^ help: change this to: `&mut str` error: writing `&PathBuf` instead of `&Path` involves a new object where a slice will do - --> $DIR/ptr_arg.rs:24:15 + --> $DIR/ptr_arg.rs:29:15 | LL | fn do_path(x: &PathBuf) { | ^^^^^^^^ help: change this to: `&Path` error: writing `&mut PathBuf` instead of `&mut Path` involves a new object where a slice will do - --> $DIR/ptr_arg.rs:28:19 + --> $DIR/ptr_arg.rs:33:19 | LL | fn do_path_mut(x: &mut PathBuf) { | ^^^^^^^^^^^^ help: change this to: `&mut Path` error: writing `&Vec` instead of `&[_]` involves a new object where a slice will do - --> $DIR/ptr_arg.rs:36:18 + --> $DIR/ptr_arg.rs:41:18 | LL | fn do_vec(x: &Vec); | ^^^^^^^^^ help: change this to: `&[i64]` error: writing `&Vec` instead of `&[_]` involves a new object where a slice will do - --> $DIR/ptr_arg.rs:49:14 + --> $DIR/ptr_arg.rs:54:14 | LL | fn cloned(x: &Vec) -> Vec { | ^^^^^^^^ @@ -60,7 +60,7 @@ LL ~ x.to_owned() | error: writing `&String` instead of `&str` involves a new object where a slice will do - --> $DIR/ptr_arg.rs:58:18 + --> $DIR/ptr_arg.rs:63:18 | LL | fn str_cloned(x: &String) -> String { | ^^^^^^^ @@ -76,7 +76,7 @@ LL ~ x.to_owned() | error: writing `&PathBuf` instead of `&Path` involves a new object where a slice will do - --> $DIR/ptr_arg.rs:66:19 + --> $DIR/ptr_arg.rs:71:19 | LL | fn path_cloned(x: &PathBuf) -> PathBuf { | ^^^^^^^^ @@ -92,7 +92,7 @@ LL ~ x.to_path_buf() | error: writing `&String` instead of `&str` involves a new object where a slice will do - --> $DIR/ptr_arg.rs:74:44 + --> $DIR/ptr_arg.rs:79:44 | LL | fn false_positive_capacity(x: &Vec, y: &String) { | ^^^^^^^ @@ -106,19 +106,19 @@ LL ~ let c = y; | error: using a reference to `Cow` is not recommended - --> $DIR/ptr_arg.rs:88:25 + --> $DIR/ptr_arg.rs:93:25 | LL | fn test_cow_with_ref(c: &Cow<[i32]>) {} | ^^^^^^^^^^^ help: change this to: `&[i32]` error: writing `&String` instead of `&str` involves a new object where a slice will do - --> $DIR/ptr_arg.rs:117:66 + --> $DIR/ptr_arg.rs:122:66 | LL | fn some_allowed(#[allow(clippy::ptr_arg)] _v: &Vec, _s: &String) {} | ^^^^^^^ help: change this to: `&str` error: writing `&Vec` instead of `&[_]` involves a new object where a slice will do - --> $DIR/ptr_arg.rs:146:21 + --> $DIR/ptr_arg.rs:151:21 | LL | fn foo_vec(vec: &Vec) { | ^^^^^^^^ @@ -131,7 +131,7 @@ LL ~ let _ = vec.to_owned().clone(); | error: writing `&PathBuf` instead of `&Path` involves a new object where a slice will do - --> $DIR/ptr_arg.rs:151:23 + --> $DIR/ptr_arg.rs:156:23 | LL | fn foo_path(path: &PathBuf) { | ^^^^^^^^ @@ -144,7 +144,7 @@ LL ~ let _ = path.to_path_buf().clone(); | error: writing `&PathBuf` instead of `&Path` involves a new object where a slice will do - --> $DIR/ptr_arg.rs:156:21 + --> $DIR/ptr_arg.rs:161:21 | LL | fn foo_str(str: &PathBuf) { | ^^^^^^^^ @@ -157,28 +157,46 @@ LL ~ let _ = str.to_path_buf().clone(); | error: writing `&mut Vec` instead of `&mut [_]` involves a new object where a slice will do - --> $DIR/ptr_arg.rs:162:29 + --> $DIR/ptr_arg.rs:167:29 | LL | fn mut_vec_slice_methods(v: &mut Vec) { | ^^^^^^^^^^^^^ help: change this to: `&mut [u32]` error: writing `&mut Vec` instead of `&mut [_]` involves a new object where a slice will do - --> $DIR/ptr_arg.rs:224:17 + --> $DIR/ptr_arg.rs:229:17 | LL | fn dyn_trait(a: &mut Vec, b: &mut String, c: &mut PathBuf) { | ^^^^^^^^^^^^^ help: change this to: `&mut [u32]` error: writing `&mut String` instead of `&mut str` involves a new object where a slice will do - --> $DIR/ptr_arg.rs:224:35 + --> $DIR/ptr_arg.rs:229:35 | LL | fn dyn_trait(a: &mut Vec, b: &mut String, c: &mut PathBuf) { | ^^^^^^^^^^^ help: change this to: `&mut str` error: writing `&mut PathBuf` instead of `&mut Path` involves a new object where a slice will do - --> $DIR/ptr_arg.rs:224:51 + --> $DIR/ptr_arg.rs:229:51 | LL | fn dyn_trait(a: &mut Vec, b: &mut String, c: &mut PathBuf) { | ^^^^^^^^^^^^ help: change this to: `&mut Path` -error: aborting due to 20 previous errors +error: using a reference to `Cow` is not recommended + --> $DIR/ptr_arg.rs:252:39 + | +LL | fn cow_elided_lifetime<'a>(input: &'a Cow) -> &'a str { + | ^^^^^^^^^^^^ help: change this to: `&str` + +error: using a reference to `Cow` is not recommended + --> $DIR/ptr_arg.rs:257:36 + | +LL | fn cow_bad_ret_ty_1<'a>(input: &'a Cow<'a, str>) -> &'static str { + | ^^^^^^^^^^^^^^^^ help: change this to: `&str` + +error: using a reference to `Cow` is not recommended + --> $DIR/ptr_arg.rs:260:40 + | +LL | fn cow_bad_ret_ty_2<'a, 'b>(input: &'a Cow<'a, str>) -> &'b str { + | ^^^^^^^^^^^^^^^^ help: change this to: `&str` + +error: aborting due to 23 previous errors From fe856d383f75a9c8341a451033fa03992cfb0b3c Mon Sep 17 00:00:00 2001 From: y21 <30553356+y21@users.noreply.github.com> Date: Sat, 24 Jun 2023 19:54:12 +0200 Subject: [PATCH 255/310] [`format_push_string`]: look through match, if, if-let --- clippy_lints/src/format_push_string.rs | 23 ++++++++++++---- tests/ui/format_push_string.rs | 29 ++++++++++++++++++++ tests/ui/format_push_string.stderr | 37 +++++++++++++++++++++++++- 3 files changed, 83 insertions(+), 6 deletions(-) diff --git a/clippy_lints/src/format_push_string.rs b/clippy_lints/src/format_push_string.rs index 68c5c3673fe..45f67020c2d 100644 --- a/clippy_lints/src/format_push_string.rs +++ b/clippy_lints/src/format_push_string.rs @@ -1,7 +1,7 @@ use clippy_utils::diagnostics::span_lint_and_help; use clippy_utils::ty::is_type_lang_item; -use clippy_utils::{match_def_path, paths, peel_hir_expr_refs}; -use rustc_hir::{BinOpKind, Expr, ExprKind, LangItem}; +use clippy_utils::{higher, match_def_path, paths}; +use rustc_hir::{BinOpKind, Expr, ExprKind, LangItem, MatchSource}; use rustc_lint::{LateContext, LateLintPass}; use rustc_session::{declare_lint_pass, declare_tool_lint}; use rustc_span::sym; @@ -44,10 +44,24 @@ fn is_string(cx: &LateContext<'_>, e: &Expr<'_>) -> bool { is_type_lang_item(cx, cx.typeck_results().expr_ty(e).peel_refs(), LangItem::String) } fn is_format(cx: &LateContext<'_>, e: &Expr<'_>) -> bool { - if let Some(macro_def_id) = e.span.ctxt().outer_expn_data().macro_def_id { + let e = e.peel_blocks().peel_borrows(); + + if e.span.from_expansion() + && let Some(macro_def_id) = e.span.ctxt().outer_expn_data().macro_def_id + { cx.tcx.get_diagnostic_name(macro_def_id) == Some(sym::format_macro) + } else if let Some(higher::If { then, r#else, .. }) = higher::If::hir(e) { + is_format(cx, then) || r#else.is_some_and(|e| is_format(cx, e)) } else { - false + match higher::IfLetOrMatch::parse(cx, e) { + Some(higher::IfLetOrMatch::Match(_, arms, MatchSource::Normal)) => { + arms.iter().any(|arm| is_format(cx, arm.body)) + }, + Some(higher::IfLetOrMatch::IfLet(_, _, then, r#else)) => { + is_format(cx, then) ||r#else.is_some_and(|e| is_format(cx, e)) + }, + _ => false, + } } } @@ -68,7 +82,6 @@ impl<'tcx> LateLintPass<'tcx> for FormatPushString { }, _ => return, }; - let (arg, _) = peel_hir_expr_refs(arg); if is_format(cx, arg) { span_lint_and_help( cx, diff --git a/tests/ui/format_push_string.rs b/tests/ui/format_push_string.rs index 4db13d650eb..89423ffe1cf 100644 --- a/tests/ui/format_push_string.rs +++ b/tests/ui/format_push_string.rs @@ -5,3 +5,32 @@ fn main() { string += &format!("{:?}", 1234); string.push_str(&format!("{:?}", 5678)); } + +mod issue9493 { + pub fn u8vec_to_hex(vector: &Vec, upper: bool) -> String { + let mut hex = String::with_capacity(vector.len() * 2); + for byte in vector { + hex += &(if upper { + format!("{byte:02X}") + } else { + format!("{byte:02x}") + }); + } + hex + } + + pub fn other_cases() { + let mut s = String::new(); + // if let + s += &(if let Some(_a) = Some(1234) { + format!("{}", 1234) + } else { + format!("{}", 1234) + }); + // match + s += &(match Some(1234) { + Some(_) => format!("{}", 1234), + None => format!("{}", 1234), + }); + } +} diff --git a/tests/ui/format_push_string.stderr b/tests/ui/format_push_string.stderr index d7be9a5f206..76762c4a1d1 100644 --- a/tests/ui/format_push_string.stderr +++ b/tests/ui/format_push_string.stderr @@ -15,5 +15,40 @@ LL | string.push_str(&format!("{:?}", 5678)); | = help: consider using `write!` to avoid the extra allocation -error: aborting due to 2 previous errors +error: `format!(..)` appended to existing `String` + --> $DIR/format_push_string.rs:13:13 + | +LL | / hex += &(if upper { +LL | | format!("{byte:02X}") +LL | | } else { +LL | | format!("{byte:02x}") +LL | | }); + | |______________^ + | + = help: consider using `write!` to avoid the extra allocation + +error: `format!(..)` appended to existing `String` + --> $DIR/format_push_string.rs:25:9 + | +LL | / s += &(if let Some(_a) = Some(1234) { +LL | | format!("{}", 1234) +LL | | } else { +LL | | format!("{}", 1234) +LL | | }); + | |__________^ + | + = help: consider using `write!` to avoid the extra allocation + +error: `format!(..)` appended to existing `String` + --> $DIR/format_push_string.rs:31:9 + | +LL | / s += &(match Some(1234) { +LL | | Some(_) => format!("{}", 1234), +LL | | None => format!("{}", 1234), +LL | | }); + | |__________^ + | + = help: consider using `write!` to avoid the extra allocation + +error: aborting due to 5 previous errors From f0eb40c981fe2de71fe96aa4e91c2164270ba2f9 Mon Sep 17 00:00:00 2001 From: Renato Lochetti Date: Sat, 24 Jun 2023 19:45:16 -0300 Subject: [PATCH 256/310] Avoid linting on procedural macros --- clippy_lints/src/extra_unused_type_parameters.rs | 2 ++ tests/ui/extra_unused_type_parameters.fixed | 12 ++++++++++++ tests/ui/extra_unused_type_parameters.rs | 12 ++++++++++++ tests/ui/extra_unused_type_parameters.stderr | 16 ++++++++-------- 4 files changed, 34 insertions(+), 8 deletions(-) diff --git a/clippy_lints/src/extra_unused_type_parameters.rs b/clippy_lints/src/extra_unused_type_parameters.rs index eeb4de8b58f..126bed6789c 100644 --- a/clippy_lints/src/extra_unused_type_parameters.rs +++ b/clippy_lints/src/extra_unused_type_parameters.rs @@ -1,4 +1,5 @@ use clippy_utils::diagnostics::{span_lint_and_help, span_lint_and_then}; +use clippy_utils::is_from_proc_macro; use clippy_utils::trait_ref_of_method; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_errors::Applicability; @@ -265,6 +266,7 @@ 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.is_empty_exported_or_macro(cx, item.span, item.owner_id.def_id, body_id) + && !is_from_proc_macro(cx, item) { let mut walker = TypeWalker::new(cx, generics); walk_item(&mut walker, item); diff --git a/tests/ui/extra_unused_type_parameters.fixed b/tests/ui/extra_unused_type_parameters.fixed index adcd1f6d407..03ac9abf498 100644 --- a/tests/ui/extra_unused_type_parameters.fixed +++ b/tests/ui/extra_unused_type_parameters.fixed @@ -1,8 +1,12 @@ //@run-rustfix +//@aux-build:proc_macros.rs #![allow(unused, clippy::needless_lifetimes)] #![warn(clippy::extra_unused_type_parameters)] +extern crate proc_macros; +use proc_macros::with_span; + fn unused_ty(x: u8) { unimplemented!() } @@ -102,4 +106,12 @@ mod issue10319 { } } +with_span!( + span + + fn should_not_lint(x: u8) { + unimplemented!() + } +); + fn main() {} diff --git a/tests/ui/extra_unused_type_parameters.rs b/tests/ui/extra_unused_type_parameters.rs index c4c5227ac91..731c89c18dc 100644 --- a/tests/ui/extra_unused_type_parameters.rs +++ b/tests/ui/extra_unused_type_parameters.rs @@ -1,8 +1,12 @@ //@run-rustfix +//@aux-build:proc_macros.rs #![allow(unused, clippy::needless_lifetimes)] #![warn(clippy::extra_unused_type_parameters)] +extern crate proc_macros; +use proc_macros::with_span; + fn unused_ty(x: u8) { unimplemented!() } @@ -102,4 +106,12 @@ mod issue10319 { } } +with_span!( + span + + fn should_not_lint(x: u8) { + unimplemented!() + } +); + fn main() {} diff --git a/tests/ui/extra_unused_type_parameters.stderr b/tests/ui/extra_unused_type_parameters.stderr index c042a5a2290..b5277d49861 100644 --- a/tests/ui/extra_unused_type_parameters.stderr +++ b/tests/ui/extra_unused_type_parameters.stderr @@ -1,5 +1,5 @@ error: type parameter `T` goes unused in function definition - --> $DIR/extra_unused_type_parameters.rs:6:13 + --> $DIR/extra_unused_type_parameters.rs:10:13 | LL | fn unused_ty(x: u8) { | ^^^ help: consider removing the parameter @@ -7,19 +7,19 @@ LL | fn unused_ty(x: u8) { = note: `-D clippy::extra-unused-type-parameters` implied by `-D warnings` error: type parameters go unused in function definition: T, U - --> $DIR/extra_unused_type_parameters.rs:10:16 + --> $DIR/extra_unused_type_parameters.rs:14:16 | LL | fn unused_multi(x: u8) { | ^^^^^^ help: consider removing the parameters error: type parameter `T` goes unused in function definition - --> $DIR/extra_unused_type_parameters.rs:14:21 + --> $DIR/extra_unused_type_parameters.rs:18:21 | LL | fn unused_with_lt<'a, T>(x: &'a u8) { | ^^^ help: consider removing the parameter error: type parameters go unused in function definition: T, V - --> $DIR/extra_unused_type_parameters.rs:26:19 + --> $DIR/extra_unused_type_parameters.rs:30:19 | LL | fn unused_bounded(x: U) { | ^^^^^^^^^^^^ ^^^^^^^^^^^^ @@ -31,7 +31,7 @@ LL + fn unused_bounded(x: U) { | error: type parameters go unused in function definition: A, D, E - --> $DIR/extra_unused_type_parameters.rs:30:16 + --> $DIR/extra_unused_type_parameters.rs:34:16 | LL | fn some_unused, E>(b: B, c: C) { | ^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -43,19 +43,19 @@ LL + fn some_unused(b: B, c: C) { | error: type parameter `T` goes unused in function definition - --> $DIR/extra_unused_type_parameters.rs:55:22 + --> $DIR/extra_unused_type_parameters.rs:59:22 | LL | fn unused_ty_impl(&self) { | ^^^ help: consider removing the parameter error: type parameters go unused in function definition: A, B - --> $DIR/extra_unused_type_parameters.rs:77:17 + --> $DIR/extra_unused_type_parameters.rs:81:17 | LL | fn unused_opaque(dummy: impl Default) { | ^^^^^^ help: consider removing the parameters error: type parameter `U` goes unused in function definition - --> $DIR/extra_unused_type_parameters.rs:90:56 + --> $DIR/extra_unused_type_parameters.rs:94:56 | LL | fn unused_with_priv_trait_bound() { | ^^^ help: consider removing the parameter From 23d7a07e86210ba0e9b18fdcb9dd88a17bb0b4ec Mon Sep 17 00:00:00 2001 From: yukang Date: Tue, 6 Jun 2023 02:48:57 +0800 Subject: [PATCH 257/310] Do not offer any of the suggestions in emit_coerce_suggestions for expr from destructuring assignment desugaring --- tests/ui/crashes/ice-6250.stderr | 5 ----- 1 file changed, 5 deletions(-) diff --git a/tests/ui/crashes/ice-6250.stderr b/tests/ui/crashes/ice-6250.stderr index 4506d1550bd..db34e6bfa7b 100644 --- a/tests/ui/crashes/ice-6250.stderr +++ b/tests/ui/crashes/ice-6250.stderr @@ -12,11 +12,6 @@ LL | for reference in vec![1, 2, 3] { ... LL | Some(reference) = cache.data.get(key) { | ^^^^^^^^^ expected integer, found `&i32` - | -help: consider dereferencing the borrow - | -LL | Some(*reference) = cache.data.get(key) { - | + error[E0308]: mismatched types --> $DIR/ice-6250.rs:12:9 From a5ae9044fbe53996a6d914de539b0fabd95232b4 Mon Sep 17 00:00:00 2001 From: Catherine <114838443+Centri3@users.noreply.github.com> Date: Sun, 25 Jun 2023 04:28:40 -0500 Subject: [PATCH 258/310] make note less verbose --- clippy_lints/src/drop_forget_ref.rs | 28 ++++++++++++++++------------ tests/ui/mem_forget.stderr | 24 ++++-------------------- 2 files changed, 20 insertions(+), 32 deletions(-) diff --git a/clippy_lints/src/drop_forget_ref.rs b/clippy_lints/src/drop_forget_ref.rs index 36b231023a7..6f8261ed84e 100644 --- a/clippy_lints/src/drop_forget_ref.rs +++ b/clippy_lints/src/drop_forget_ref.rs @@ -120,7 +120,7 @@ impl<'tcx> LateLintPass<'tcx> for DropForgetRef { let arg_ty = cx.typeck_results().expr_ty(arg); let is_copy = is_copy(cx, arg_ty); let drop_is_single_call_in_arm = is_single_call_in_arm(cx, arg, expr); - let (lint, msg) = match fn_name { + let (lint, msg, note_span) = match fn_name { // early return for uplifted lints: dropping_references, dropping_copy_types, forgetting_references, forgetting_copy_types sym::mem_drop if arg_ty.is_ref() && !drop_is_single_call_in_arm => return, sym::mem_forget if arg_ty.is_ref() => return, @@ -144,20 +144,24 @@ impl<'tcx> LateLintPass<'tcx> for DropForgetRef { || drop_is_single_call_in_arm ) => { - (DROP_NON_DROP, DROP_NON_DROP_SUMMARY.into()) + (DROP_NON_DROP, DROP_NON_DROP_SUMMARY.into(), Some(arg.span)) }, sym::mem_forget => { if arg_ty.needs_drop(cx.tcx, cx.param_env) { - (MEM_FORGET, Cow::Owned(format!( - "usage of `mem::forget` on {}", - if arg_ty.ty_adt_def().map_or(false, |def| def.has_dtor(cx.tcx)) { - "`Drop` type" - } else { - "type with `Drop` fields" - } - ))) + ( + MEM_FORGET, + Cow::Owned(format!( + "usage of `mem::forget` on {}", + if arg_ty.ty_adt_def().map_or(false, |def| def.has_dtor(cx.tcx)) { + "`Drop` type" + } else { + "type with `Drop` fields" + } + )), + None, + ) } else { - (FORGET_NON_DROP, FORGET_NON_DROP_SUMMARY.into()) + (FORGET_NON_DROP, FORGET_NON_DROP_SUMMARY.into(), Some(arg.span)) } } _ => return, @@ -167,7 +171,7 @@ impl<'tcx> LateLintPass<'tcx> for DropForgetRef { lint, expr.span, &msg, - Some(arg.span), + note_span, &format!("argument has type `{arg_ty}`"), ); } diff --git a/tests/ui/mem_forget.stderr b/tests/ui/mem_forget.stderr index 6e3c31804d7..8004b2aa8db 100644 --- a/tests/ui/mem_forget.stderr +++ b/tests/ui/mem_forget.stderr @@ -4,11 +4,7 @@ error: usage of `mem::forget` on `Drop` type LL | memstuff::forget(six); | ^^^^^^^^^^^^^^^^^^^^^ | -note: argument has type `std::sync::Arc` - --> $DIR/mem_forget.rs:14:22 - | -LL | memstuff::forget(six); - | ^^^ + = note: argument has type `std::sync::Arc` = note: `-D clippy::mem-forget` implied by `-D warnings` error: usage of `mem::forget` on `Drop` type @@ -17,11 +13,7 @@ error: usage of `mem::forget` on `Drop` type LL | std::mem::forget(seven); | ^^^^^^^^^^^^^^^^^^^^^^^ | -note: argument has type `std::rc::Rc` - --> $DIR/mem_forget.rs:17:22 - | -LL | std::mem::forget(seven); - | ^^^^^ + = note: argument has type `std::rc::Rc` error: usage of `mem::forget` on `Drop` type --> $DIR/mem_forget.rs:20:5 @@ -29,11 +21,7 @@ error: usage of `mem::forget` on `Drop` type LL | forgetSomething(eight); | ^^^^^^^^^^^^^^^^^^^^^^ | -note: argument has type `std::vec::Vec` - --> $DIR/mem_forget.rs:20:21 - | -LL | forgetSomething(eight); - | ^^^^^ + = note: argument has type `std::vec::Vec` error: usage of `mem::forget` on type with `Drop` fields --> $DIR/mem_forget.rs:23:5 @@ -41,11 +29,7 @@ error: usage of `mem::forget` on type with `Drop` fields LL | std::mem::forget(string); | ^^^^^^^^^^^^^^^^^^^^^^^^ | -note: argument has type `std::string::String` - --> $DIR/mem_forget.rs:23:22 - | -LL | std::mem::forget(string); - | ^^^^^^ + = note: argument has type `std::string::String` error: aborting due to 4 previous errors From 555bd985d2d388e31e87b881f3629afd7bafde0f Mon Sep 17 00:00:00 2001 From: Maybe Waffle Date: Wed, 21 Jun 2023 14:00:51 +0000 Subject: [PATCH 259/310] Support `hir::ExprKind::Become` in clippy --- clippy_lints/src/loops/never_loop.rs | 6 ++++++ clippy_lints/src/matches/significant_drop_in_scrutinee.rs | 1 + clippy_lints/src/utils/author.rs | 5 +++++ clippy_utils/src/eager_or_lazy.rs | 1 + clippy_utils/src/hir_utils.rs | 3 +++ clippy_utils/src/sugg.rs | 1 + clippy_utils/src/visitors.rs | 1 + 7 files changed, 18 insertions(+) diff --git a/clippy_lints/src/loops/never_loop.rs b/clippy_lints/src/loops/never_loop.rs index 5f1fdf00be8..10b5e1edf92 100644 --- a/clippy_lints/src/loops/never_loop.rs +++ b/clippy_lints/src/loops/never_loop.rs @@ -206,6 +206,12 @@ fn never_loop_expr(expr: &Expr<'_>, ignore_ids: &mut Vec, main_loop_id: H NeverLoopResult::AlwaysBreak, ) }), + ExprKind::Become(e) => { + combine_seq( + never_loop_expr(e, ignore_ids, main_loop_id), + NeverLoopResult::AlwaysBreak, + ) + } ExprKind::InlineAsm(asm) => asm .operands .iter() diff --git a/clippy_lints/src/matches/significant_drop_in_scrutinee.rs b/clippy_lints/src/matches/significant_drop_in_scrutinee.rs index 7945275393c..93ef07d36ae 100644 --- a/clippy_lints/src/matches/significant_drop_in_scrutinee.rs +++ b/clippy_lints/src/matches/significant_drop_in_scrutinee.rs @@ -329,6 +329,7 @@ impl<'a, 'tcx> Visitor<'tcx> for SigDropHelper<'a, 'tcx> { ExprKind::Field(..) | ExprKind::Index(..) | ExprKind::Ret(..) | + ExprKind::Become(..) | ExprKind::Repeat(..) | ExprKind::Yield(..) => walk_expr(self, ex), ExprKind::AddrOf(_, _, _) | diff --git a/clippy_lints/src/utils/author.rs b/clippy_lints/src/utils/author.rs index 3c2bf5abab2..6b51974d739 100644 --- a/clippy_lints/src/utils/author.rs +++ b/clippy_lints/src/utils/author.rs @@ -559,6 +559,11 @@ impl<'a, 'tcx> PrintVisitor<'a, 'tcx> { kind!("Ret({value})"); value.if_some(|e| self.expr(e)); }, + ExprKind::Become(value) => { + bind!(self, value); + kind!("Become({value})"); + self.expr(value); + }, ExprKind::InlineAsm(_) => { kind!("InlineAsm(_)"); out!("// unimplemented: `ExprKind::InlineAsm` is not further destructured at the moment"); diff --git a/clippy_utils/src/eager_or_lazy.rs b/clippy_utils/src/eager_or_lazy.rs index 941df3318ae..a42b2ccee88 100644 --- a/clippy_utils/src/eager_or_lazy.rs +++ b/clippy_utils/src/eager_or_lazy.rs @@ -191,6 +191,7 @@ fn expr_eagerness<'tcx>(cx: &LateContext<'tcx>, e: &'tcx Expr<'_>) -> EagernessS ExprKind::Break(..) | ExprKind::Continue(_) | ExprKind::Ret(_) + | ExprKind::Become(_) | ExprKind::InlineAsm(_) | ExprKind::Yield(..) | ExprKind::Err(_) => { diff --git a/clippy_utils/src/hir_utils.rs b/clippy_utils/src/hir_utils.rs index a49246a7832..3e1d7356414 100644 --- a/clippy_utils/src/hir_utils.rs +++ b/clippy_utils/src/hir_utils.rs @@ -845,6 +845,9 @@ impl<'a, 'tcx> SpanlessHash<'a, 'tcx> { self.hash_expr(e); } }, + ExprKind::Become(f) => { + self.hash_expr(f); + }, ExprKind::Path(ref qpath) => { self.hash_qpath(qpath); }, diff --git a/clippy_utils/src/sugg.rs b/clippy_utils/src/sugg.rs index a87d58110b0..b38b9553558 100644 --- a/clippy_utils/src/sugg.rs +++ b/clippy_utils/src/sugg.rs @@ -147,6 +147,7 @@ impl<'a> Sugg<'a> { | hir::ExprKind::Path(..) | hir::ExprKind::Repeat(..) | hir::ExprKind::Ret(..) + | hir::ExprKind::Become(..) | hir::ExprKind::Struct(..) | hir::ExprKind::Tup(..) | hir::ExprKind::Err(_) => Sugg::NonParen(get_snippet(expr.span)), diff --git a/clippy_utils/src/visitors.rs b/clippy_utils/src/visitors.rs index 5dcd71cef12..8dafa723afa 100644 --- a/clippy_utils/src/visitors.rs +++ b/clippy_utils/src/visitors.rs @@ -651,6 +651,7 @@ pub fn for_each_unconsumed_temporary<'tcx, B>( // Either drops temporaries, jumps out of the current expression, or has no sub expression. ExprKind::DropTemps(_) | ExprKind::Ret(_) + | ExprKind::Become(_) | ExprKind::Break(..) | ExprKind::Yield(..) | ExprKind::Block(..) From aea731ebdb90cdb734e2ecb8405de7b5c60b3898 Mon Sep 17 00:00:00 2001 From: blyxyas Date: Sun, 25 Jun 2023 21:28:19 +0200 Subject: [PATCH 260/310] update changelog's data ranges --- CHANGELOG.md | 108 +++++++++++------- .../infrastructure/changelog_update.md | 22 ++++ 2 files changed, 89 insertions(+), 41 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 3b58e25c611..941efb1abff 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,7 +12,7 @@ document. Current stable, released 2023-06-01 -[149392b0...83e42a23](https://github.com/rust-lang/rust-clippy/compare/149392b0...83e42a23) +[**View 85 PRs merged since 1.69**](https://github.com/rust-lang/rust-clippy/pulls?q=is%3Apr+is%3Aclosed+merged%3A2023-04-20..2023-06-01+base%3Amaster+sort%3Amerged-desc+) ### New Lints @@ -137,7 +137,7 @@ Current stable, released 2023-06-01 Released 2023-04-20 -[7f27e2e7...149392b0](https://github.com/rust-lang/rust-clippy/compare/7f27e2e7...149392b0) +[**View 86 PRs merged since 1.68**](https://github.com/rust-lang/rust-clippy/pulls?q=is%3Apr+is%3Aclosed+merged%3A2023-03-09..2023-04-20+base%3Amaster+sort%3Amerged-desc+) ### New Lints @@ -252,7 +252,7 @@ Released 2023-04-20 Released 2023-03-09 -[d822110d...7f27e2e7](https://github.com/rust-lang/rust-clippy/compare/d822110d...7f27e2e7) +[**View 85 PRs merged since 1.67**](https://github.com/rust-lang/rust-clippy/pulls?q=is%3Apr+is%3Aclosed+merged%3A2023-01-26..2023-03-09+base%3Amaster+sort%3Amerged-desc+) ### New Lints @@ -399,7 +399,7 @@ Released 2023-03-09 Released 2023-01-26 -[4f142aa1...d822110d](https://github.com/rust-lang/rust-clippy/compare/4f142aa1...d822110d) +[**View 68 PRs merged since 1.66**](https://github.com/rust-lang/rust-clippy/pulls?q=is%3Apr+is%3Aclosed+merged%3A2022-12-15..2023-01-26+base%3Amaster+sort%3Amerged-desc+) ### New Lints @@ -590,7 +590,8 @@ Released 2023-01-26 Released 2022-12-15 -[b52fb523...4f142aa1](https://github.com/rust-lang/rust-clippy/compare/b52fb523...4f142aa1) +[**View 93 PRs merged since 1.65**](https://github.com/rust-lang/rust-clippy/pulls?q=is%3Apr+is%3Aclosed+merged%3A2022-11-03..2022-12-15+base%3Amaster+sort%3Amerged-desc+) + ### New Lints @@ -761,7 +762,8 @@ Released 2022-12-15 Released 2022-11-03 -[3c7e7dbc...b52fb523](https://github.com/rust-lang/rust-clippy/compare/3c7e7dbc...b52fb523) +[**View 129 PRs merged since 1.64**](https://github.com/rust-lang/rust-clippy/pulls?q=is%3Apr+is%3Aclosed+merged%3A2022-09-22..2022-11-03+base%3Amaster+sort%3Amerged-desc+) + ### Important Changes @@ -905,7 +907,8 @@ Released 2022-11-03 Released 2022-09-22 -[d7b5cbf0...3c7e7dbc](https://github.com/rust-lang/rust-clippy/compare/d7b5cbf0...3c7e7dbc) +[**View 92 PRs merged since 1.63**](https://github.com/rust-lang/rust-clippy/pulls?q=is%3Apr+is%3Aclosed+merged%3A2022-08-11..2022-09-22+base%3Amaster+sort%3Amerged-desc+) + ### New Lints @@ -1055,7 +1058,8 @@ Released 2022-09-22 Released 2022-08-11 -[7c21f91b...d7b5cbf0](https://github.com/rust-lang/rust-clippy/compare/7c21f91b...d7b5cbf0) +[**View 100 PRs merged since 1.62**](https://github.com/rust-lang/rust-clippy/pulls?q=is%3Apr+is%3Aclosed+merged%3A2022-06-30..2022-08-11+base%3Amaster+sort%3Amerged-desc+) + ### New Lints @@ -1201,7 +1205,8 @@ Released 2022-08-11 Released 2022-06-30 -[d0cf3481...7c21f91b](https://github.com/rust-lang/rust-clippy/compare/d0cf3481...7c21f91b) +[**View 104 PRs merged since 1.61**](https://github.com/rust-lang/rust-clippy/pulls?q=is%3Apr+is%3Aclosed+merged%3A2022-05-19..2022-06-30+base%3Amaster+sort%3Amerged-desc+) + ### New Lints @@ -1358,7 +1363,8 @@ Released 2022-06-30 Released 2022-05-19 -[57b3c4b...d0cf3481](https://github.com/rust-lang/rust-clippy/compare/57b3c4b...d0cf3481) +[**View 93 PRs merged since 1.60**](https://github.com/rust-lang/rust-clippy/pulls?q=is%3Apr+is%3Aclosed+merged%3A2022-04-07..2022-05-19+base%3Amaster+sort%3Amerged-desc+) + ### New Lints @@ -1459,7 +1465,8 @@ Released 2022-05-19 Released 2022-04-07 -[0eff589...57b3c4b](https://github.com/rust-lang/rust-clippy/compare/0eff589...57b3c4b) +[**View 75 PRs merged since 1.59**](https://github.com/rust-lang/rust-clippy/pulls?q=is%3Apr+is%3Aclosed+merged%3A2022-02-24..2022-04-07+base%3Amaster+sort%3Amerged-desc+) + ### New Lints @@ -1591,7 +1598,8 @@ Released 2022-04-07 Released 2022-02-24 -[e181011...0eff589](https://github.com/rust-lang/rust-clippy/compare/e181011...0eff589) +[**View 63 PRs merged since 1.58**](https://github.com/rust-lang/rust-clippy/pulls?q=is%3Apr+is%3Aclosed+merged%3A2022-01-13..2022-02-24+base%3Amaster+sort%3Amerged-desc+) + ### New Lints @@ -1755,7 +1763,8 @@ Released 2022-02-24 Released 2022-01-13 -[00e31fa...e181011](https://github.com/rust-lang/rust-clippy/compare/00e31fa...e181011) +[**View 73 PRs merged since 1.57**](https://github.com/rust-lang/rust-clippy/pulls?q=is%3Apr+is%3Aclosed+merged%3A2021-12-02..2022-01-13+base%3Amaster+sort%3Amerged-desc+) + ### Rust 1.58.1 @@ -1876,7 +1885,8 @@ Released 2022-01-13 Released 2021-12-02 -[7bfc26e...00e31fa](https://github.com/rust-lang/rust-clippy/compare/7bfc26e...00e31fa) +[**View 92 PRs merged since 1.56**](https://github.com/rust-lang/rust-clippy/pulls?q=is%3Apr+is%3Aclosed+merged%3A2021-10-21..2021-12-02+base%3Amaster+sort%3Amerged-desc+) + ### New Lints @@ -2027,7 +2037,7 @@ Released 2021-12-02 Released 2021-10-21 -[74d1561...7bfc26e](https://github.com/rust-lang/rust-clippy/compare/74d1561...7bfc26e) +[**View 92 PRs merged since 1.55**](https://github.com/rust-lang/rust-clippy/pulls?q=is%3Apr+is%3Aclosed+merged%3A2021-09-09..2021-10-21+base%3Amaster+sort%3Amerged-desc+) ### New Lints @@ -2093,7 +2103,7 @@ Released 2021-10-21 Released 2021-09-09 -[3ae8faf...74d1561](https://github.com/rust-lang/rust-clippy/compare/3ae8faf...74d1561) +[**View 61 PRs merged since 1.54**](https://github.com/rust-lang/rust-clippy/pulls?q=is%3Apr+is%3Aclosed+merged%3A2021-07-29..2021-09-09+base%3Amaster+sort%3Amerged-desc+) ### Important Changes @@ -2211,7 +2221,8 @@ Released 2021-09-09 Released 2021-07-29 -[7c7683c...3ae8faf](https://github.com/rust-lang/rust-clippy/compare/7c7683c...3ae8faf) +[**View 68 PRs merged since 1.53**](https://github.com/rust-lang/rust-clippy/pulls?q=is%3Apr+is%3Aclosed+merged%3A2021-06-17..2021-07-29+base%3Amaster+sort%3Amerged-desc+) + ### New Lints @@ -2339,7 +2350,7 @@ Released 2021-07-29 Released 2021-06-17 -[6ed6f1e...7c7683c](https://github.com/rust-lang/rust-clippy/compare/6ed6f1e...7c7683c) +[**View 80 PRs merged since 1.52**](https://github.com/rust-lang/rust-clippy/pulls?q=is%3Apr+is%3Aclosed+merged%3A2021-05-06..2021-06-17+base%3Amaster+sort%3Amerged-desc+) ### New Lints @@ -2523,7 +2534,8 @@ Released 2021-06-17 Released 2021-05-06 -[3e41797...6ed6f1e](https://github.com/rust-lang/rust-clippy/compare/3e41797...6ed6f1e) +[**View 113 PRs merged since 1.51**](https://github.com/rust-lang/rust-clippy/pulls?q=is%3Apr+is%3Aclosed+merged%3A2021-03-25..2021-05-06+base%3Amaster+sort%3Amerged-desc+) + ### New Lints @@ -2658,7 +2670,8 @@ Released 2021-05-06 Released 2021-03-25 -[4911ab1...3e41797](https://github.com/rust-lang/rust-clippy/compare/4911ab1...3e41797) +[**View 117 PRs merged since 1.50**](https://github.com/rust-lang/rust-clippy/pulls?q=is%3Apr+is%3Aclosed+merged%3A2021-02-11..2021-03-25+base%3Amaster+sort%3Amerged-desc+) + ### New Lints @@ -2773,7 +2786,8 @@ Released 2021-03-25 Released 2021-02-11 -[b20d4c1...4bd77a1](https://github.com/rust-lang/rust-clippy/compare/b20d4c1...4bd77a1) +[**View 90 PRs merged since 1.49**](https://github.com/rust-lang/rust-clippy/pulls?q=is%3Apr+is%3Aclosed+merged%3A2020-12-31..2021-02-11+base%3Amaster+sort%3Amerged-desc+) + ### New Lints @@ -2902,7 +2916,8 @@ Released 2021-02-11 Released 2020-12-31 -[e636b88...b20d4c1](https://github.com/rust-lang/rust-clippy/compare/e636b88...b20d4c1) +[**View 85 PRs merged since 1.48**](https://github.com/rust-lang/rust-clippy/pulls?q=is%3Apr+is%3Aclosed+merged%3A2020-11-19..2020-12-31+base%3Amaster+sort%3Amerged-desc+) + ### New Lints @@ -3008,7 +3023,7 @@ Released 2020-12-31 Released 2020-11-19 -[09bd400...e636b88](https://github.com/rust-lang/rust-clippy/compare/09bd400...e636b88) +[**View 112 PRs merged since 1.47**](https://github.com/rust-lang/rust-clippy/pulls?q=is%3Apr+is%3Aclosed+merged%3A2020-10-08..2020-11-19+base%3Amaster+sort%3Amerged-desc+) ### New lints @@ -3126,7 +3141,8 @@ Released 2020-11-19 Released 2020-10-08 -[c2c07fa...09bd400](https://github.com/rust-lang/rust-clippy/compare/c2c07fa...09bd400) +[**View 80 PRs merged since 1.46**](https://github.com/rust-lang/rust-clippy/pulls?q=is%3Apr+is%3Aclosed+merged%3A2020-08-27..2020-10-08+base%3Amaster+sort%3Amerged-desc+) + ### New lints @@ -3228,7 +3244,8 @@ Released 2020-10-08 Released 2020-08-27 -[7ea7cd1...c2c07fa](https://github.com/rust-lang/rust-clippy/compare/7ea7cd1...c2c07fa) +[**View 93 PRs merged since 1.45**](https://github.com/rust-lang/rust-clippy/pulls?q=is%3Apr+is%3Aclosed+merged%3A2020-07-16..2020-08-27+base%3Amaster+sort%3Amerged-desc+) + ### New lints @@ -3290,7 +3307,8 @@ Released 2020-08-27 Released 2020-07-16 -[891e1a8...7ea7cd1](https://github.com/rust-lang/rust-clippy/compare/891e1a8...7ea7cd1) +[**View 65 PRs merged since 1.44**](https://github.com/rust-lang/rust-clippy/pulls?q=is%3Apr+is%3Aclosed+merged%3A2020-06-04..2020-07-16+base%3Amaster+sort%3Amerged-desc+) + ### New lints @@ -3367,7 +3385,8 @@ and [`similar_names`]. [#5651](https://github.com/rust-lang/rust-clippy/pull/565 Released 2020-06-04 -[204bb9b...891e1a8](https://github.com/rust-lang/rust-clippy/compare/204bb9b...891e1a8) +[**View 88 PRs merged since 1.43**](https://github.com/rust-lang/rust-clippy/pulls?q=is%3Apr+is%3Aclosed+merged%3A2020-04-23..2020-06-04+base%3Amaster+sort%3Amerged-desc+) + ### New lints @@ -3450,7 +3469,8 @@ Released 2020-06-04 Released 2020-04-23 -[4ee1206...204bb9b](https://github.com/rust-lang/rust-clippy/compare/4ee1206...204bb9b) +[**View 121 PRs merged since 1.42**](https://github.com/rust-lang/rust-clippy/pulls?q=is%3Apr+is%3Aclosed+merged%3A2020-03-12..2020-04-23+base%3Amaster+sort%3Amerged-desc+) + ### New lints @@ -3508,7 +3528,7 @@ Released 2020-04-23 Released 2020-03-12 -[69f99e7...4ee1206](https://github.com/rust-lang/rust-clippy/compare/69f99e7...4ee1206) +[**View 106 PRs merged since 1.41**](https://github.com/rust-lang/rust-clippy/pulls?q=is%3Apr+is%3Aclosed+merged%3A2020-01-30..2020-03-12+base%3Amaster+sort%3Amerged-desc+) ### New lints @@ -3575,7 +3595,7 @@ Released 2020-03-12 Released 2020-01-30 -[c8e3cfb...69f99e7](https://github.com/rust-lang/rust-clippy/compare/c8e3cfb...69f99e7) +[**View 107 PRs merged since 1.40**](https://github.com/rust-lang/rust-clippy/pulls?q=is%3Apr+is%3Aclosed+merged%3A2019-12-19..2020-01-30+base%3Amaster+sort%3Amerged-desc+) * New Lints: * [`exit`] [#4697](https://github.com/rust-lang/rust-clippy/pull/4697) @@ -3620,7 +3640,8 @@ Released 2020-01-30 Released 2019-12-19 -[4e7e71b...c8e3cfb](https://github.com/rust-lang/rust-clippy/compare/4e7e71b...c8e3cfb) +[**View 69 😺 PRs merged since 1.39**](https://github.com/rust-lang/rust-clippy/pulls?q=is%3Apr+is%3Aclosed+merged%3A2019-11-07..2019-12-19+base%3Amaster+sort%3Amerged-desc+) + * New Lints: * [`unneeded_wildcard_pattern`] [#4537](https://github.com/rust-lang/rust-clippy/pull/4537) @@ -3662,7 +3683,7 @@ Released 2019-12-19 Released 2019-11-07 -[3aea860...4e7e71b](https://github.com/rust-lang/rust-clippy/compare/3aea860...4e7e71b) +[**View 84 PRs merged since 1.38**](https://github.com/rust-lang/rust-clippy/pulls?q=is%3Apr+is%3Aclosed+merged%3A2019-09-26..2019-11-07+base%3Amaster+sort%3Amerged-desc+) * New Lints: * [`uninit_assumed_init`] [#4479](https://github.com/rust-lang/rust-clippy/pull/4479) @@ -3706,7 +3727,7 @@ Released 2019-11-07 Released 2019-09-26 -[e3cb40e...3aea860](https://github.com/rust-lang/rust-clippy/compare/e3cb40e...3aea860) +[**View 102 PRs merged since 1.37**](https://github.com/rust-lang/rust-clippy/pulls?q=is%3Apr+is%3Aclosed+merged%3A2019-08-15..2019-09-26+base%3Amaster+sort%3Amerged-desc+) * New Lints: * [`main_recursion`] [#4203](https://github.com/rust-lang/rust-clippy/pull/4203) @@ -3736,7 +3757,7 @@ Released 2019-09-26 Released 2019-08-15 -[082cfa7...e3cb40e](https://github.com/rust-lang/rust-clippy/compare/082cfa7...e3cb40e) +[**View 83 PRs merged since 1.36**](https://github.com/rust-lang/rust-clippy/pulls?q=is%3Apr+is%3Aclosed+merged%3A2019-07-04..2019-08-15+base%3Amaster+sort%3Amerged-desc+) * New Lints: * [`checked_conversions`] [#4088](https://github.com/rust-lang/rust-clippy/pull/4088) @@ -3760,7 +3781,8 @@ Released 2019-08-15 Released 2019-07-04 -[eb9f9b1...082cfa7](https://github.com/rust-lang/rust-clippy/compare/eb9f9b1...082cfa7) +[**View 75 PRs merged since 1.35**](https://github.com/rust-lang/rust-clippy/pulls?q=is%3Apr+is%3Aclosed+merged%3A2019-05-20..2019-07-04+base%3Amaster+sort%3Amerged-desc+) + * New lints: [`find_map`], [`filter_map_next`] [#4039](https://github.com/rust-lang/rust-clippy/pull/4039) * New lint: [`path_buf_push_overwrite`] [#3954](https://github.com/rust-lang/rust-clippy/pull/3954) @@ -3791,7 +3813,8 @@ Released 2019-07-04 Released 2019-05-20 -[1fac380..37f5c1e](https://github.com/rust-lang/rust-clippy/compare/1fac380...37f5c1e) +[**View 90 PRs merged since 1.34**](https://github.com/rust-lang/rust-clippy/pulls?q=is%3Apr+is%3Aclosed+merged%3A2019-04-10..2019-05-20+base%3Amaster+sort%3Amerged-desc+) + * New lint: `drop_bounds` to detect `T: Drop` bounds * Split [`redundant_closure`] into [`redundant_closure`] and [`redundant_closure_for_method_calls`] [#4110](https://github.com/rust-lang/rust-clippy/pull/4101) @@ -3819,7 +3842,8 @@ Released 2019-05-20 Released 2019-04-10 -[1b89724...1fac380](https://github.com/rust-lang/rust-clippy/compare/1b89724...1fac380) +[**View 66 PRs merged since 1.33**](https://github.com/rust-lang/rust-clippy/pulls?q=is%3Apr+is%3Aclosed+merged%3A2019-02-26..2019-04-10+base%3Amaster+sort%3Amerged-desc+) + * New lint: [`assertions_on_constants`] to detect for example `assert!(true)` * New lint: [`dbg_macro`] to detect uses of the `dbg!` macro @@ -3849,7 +3873,7 @@ Released 2019-04-10 Released 2019-02-26 -[b2601be...1b89724](https://github.com/rust-lang/rust-clippy/compare/b2601be...1b89724) +[**View 83 PRs merged since 1.32**](https://github.com/rust-lang/rust-clippy/pulls?q=is%3Apr+is%3Aclosed+merged%3A2019-01-17..2019-02-26+base%3Amaster+sort%3Amerged-desc+) * New lints: [`implicit_return`], [`vec_box`], [`cast_ref_to_mut`] * The `rust-clippy` repository is now part of the `rust-lang` org. @@ -3882,7 +3906,7 @@ Released 2019-02-26 Released 2019-01-17 -[2e26fdc2...b2601be](https://github.com/rust-lang/rust-clippy/compare/2e26fdc2...b2601be) +[**View 106 PRs merged since 1.31**](https://github.com/rust-lang/rust-clippy/pulls?q=is%3Apr+is%3Aclosed+merged%3A2018-12-06..2019-01-17+base%3Amaster+sort%3Amerged-desc+) * New lints: [`slow_vector_initialization`], `mem_discriminant_non_enum`, [`redundant_clone`], [`wildcard_dependencies`], @@ -3912,7 +3936,8 @@ Released 2019-01-17 Released 2018-12-06 -[125907ad..2e26fdc2](https://github.com/rust-lang/rust-clippy/compare/125907ad..2e26fdc2) +[**View 85 PRs merged since 1.30**](https://github.com/rust-lang/rust-clippy/pulls?q=is%3Apr+is%3Aclosed+merged%3A2018-10-25..2018-12-06+base%3Amaster+sort%3Amerged-desc+) + * Clippy has been relicensed under a dual MIT / Apache license. See [#3093](https://github.com/rust-lang/rust-clippy/issues/3093) for more @@ -3952,7 +3977,8 @@ Released 2018-12-06 Released 2018-10-25 -[14207503...125907ad](https://github.com/rust-lang/rust-clippy/compare/14207503...125907ad) +[**View 106 PRs merged since 1.29**](https://github.com/rust-lang/rust-clippy/pulls?q=is%3Apr+is%3Aclosed+merged%3A2018-09-13..2018-10-25+base%3Amaster+sort%3Amerged-desc+) + * Deprecate `assign_ops` lint * New lints: [`mistyped_literal_suffixes`], [`ptr_offset_with_cast`], diff --git a/book/src/development/infrastructure/changelog_update.md b/book/src/development/infrastructure/changelog_update.md index df9b1bbe18f..52445494436 100644 --- a/book/src/development/infrastructure/changelog_update.md +++ b/book/src/development/infrastructure/changelog_update.md @@ -56,6 +56,28 @@ and open that file in your editor of choice. When updating the changelog it's also a good idea to make sure that `commit1` is already correct in the current changelog. +#### PR ranges + +We developed the concept of PR ranges to help the user understand the size of a new update. To create a PR range, +get the current release date and the date that the last version was released (YYYY-MM-DD) and use the following link: + +``` +[**View PRs merged since 1.**](https://github.com/rust-lang/rust-clippy/pulls?q=is%3Apr+is%3Aclosed+merged%3A..+base%3Amaster+sort%3Amerged-desc+) +``` + +> Note: Be sure to check click the link and check how many PRs got merged between + +Example: + +``` +[**View 85 PRs merged since 1.69**](https://github.com/rust-lang/rust-clippy/pulls?q=is%3Apr+is%3Aclosed+merged%3A2023-04-20..2023-06-01+base%3Amaster+sort%3Amerged-desc+) +``` + +Which renders to: +[**View 85 PRs merged since 1.69**](https://github.com/rust-lang/rust-clippy/pulls?q=is%3Apr+is%3Aclosed+merged%3A2023-04-20..2023-06-01+base%3Amaster+sort%3Amerged-desc+) + +Note that **commit ranges should not be included**, only PR ranges. + ### 3. Authoring the final changelog The above script should have dumped all the relevant PRs to the file you From 514b6d04bb63b08e76a3690973b7090b14a85799 Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Tue, 28 Feb 2023 16:12:10 +0000 Subject: [PATCH 261/310] Port clippy away from compiletest to ui_test --- .cargo/config.toml | 2 + Cargo.toml | 19 +- book/src/development/adding_lints.md | 17 +- book/src/development/basics.md | 2 +- clippy_dev/src/bless.rs | 60 ---- clippy_dev/src/lib.rs | 1 - clippy_dev/src/main.rs | 6 +- clippy_dev/src/new_lint.rs | 2 +- clippy_test_deps/Cargo.toml | 25 ++ clippy_test_deps/src/lib.rs | 14 + clippy_utils/src/lib.rs | 6 +- tests/compile-test.rs | 436 +++++++++------------------ tests/missing-test-files.rs | 6 +- util/etc/vscode-tasks.json | 4 +- 14 files changed, 208 insertions(+), 392 deletions(-) delete mode 100644 clippy_dev/src/bless.rs create mode 100644 clippy_test_deps/Cargo.toml create mode 100644 clippy_test_deps/src/lib.rs diff --git a/.cargo/config.toml b/.cargo/config.toml index 4d80d3ce63d..48a63e48568 100644 --- a/.cargo/config.toml +++ b/.cargo/config.toml @@ -1,5 +1,7 @@ [alias] uitest = "test --test compile-test" +uibless = "test --test compile-test -- -- --bless" +bless = "test -- -- --bless" dev = "run --package clippy_dev --bin clippy_dev --manifest-path clippy_dev/Cargo.toml --" lintcheck = "run --package lintcheck --bin lintcheck --manifest-path lintcheck/Cargo.toml -- " collect-metadata = "test --test dogfood --features internal -- run_metadata_collection_lint --ignored" diff --git a/Cargo.toml b/Cargo.toml index ca8bf9fac91..76c804f935e 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -27,27 +27,14 @@ tempfile = { version = "3.2", optional = true } termize = "0.1" [dev-dependencies] -compiletest_rs = { version = "0.10", features = ["tmp"] } +ui_test = "0.11.5" tester = "0.9" regex = "1.5" toml = "0.7.3" walkdir = "2.3" # This is used by the `collect-metadata` alias. filetime = "0.2" - -# UI test dependencies -clap = { version = "4.1.4", features = ["derive"] } -clippy_utils = { path = "clippy_utils" } -derive-new = "0.5" -if_chain = "1.0" itertools = "0.10.1" -quote = "1.0" -serde = { version = "1.0.125", features = ["derive"] } -syn = { version = "2.0", features = ["full"] } -futures = "0.3" -parking_lot = "0.12" -tokio = { version = "1", features = ["io-util"] } -rustc-semver = "1.1" [build-dependencies] rustc_tools_util = "0.3.0" @@ -60,3 +47,7 @@ internal = ["clippy_lints/internal", "tempfile"] [package.metadata.rust-analyzer] # This package uses #[feature(rustc_private)] rustc_private = true + +[[test]] +name = "compile-test" +harness = false diff --git a/book/src/development/adding_lints.md b/book/src/development/adding_lints.md index c26aa883eba..cfcb060c46e 100644 --- a/book/src/development/adding_lints.md +++ b/book/src/development/adding_lints.md @@ -122,20 +122,17 @@ fn main() { } ``` -Now we can run the test with `TESTNAME=foo_functions cargo uitest`, currently +Now we can run the test with `TESTNAME=foo_functions cargo uibless`, currently this test is meaningless though. While we are working on implementing our lint, we can keep running the UI test. -That allows us to check if the output is turning into what we want. +That allows us to check if the output is turning into what we want by checking the +`.stderr` file that gets updated on every test run. -Once we are satisfied with the output, we need to run `cargo dev bless` to -update the `.stderr` file for our lint. Please note that, we should run -`TESTNAME=foo_functions cargo uitest` every time before running `cargo dev -bless`. Running `TESTNAME=foo_functions cargo uitest` should pass then. When we +Running `TESTNAME=foo_functions cargo uitest` should pass on its own. When we commit our lint, we need to commit the generated `.stderr` files, too. In -general, you should only commit files changed by `cargo dev bless` for the -specific lint you are creating/editing. Note that if the generated files are -empty, they should be removed. +general, you should only commit files changed by `cargo bless` for the +specific lint you are creating/editing. > _Note:_ you can run multiple test files by specifying a comma separated list: > `TESTNAME=foo_functions,test2,test3`. @@ -169,7 +166,7 @@ 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. -Use `cargo dev bless` to automatically generate the `.fixed` file after running +Use `cargo bless` to automatically generate the `.fixed` file while running the tests. [rustfix]: https://github.com/rust-lang/rustfix diff --git a/book/src/development/basics.md b/book/src/development/basics.md index 7615dc12f9e..f4c109ff119 100644 --- a/book/src/development/basics.md +++ b/book/src/development/basics.md @@ -66,7 +66,7 @@ If the output of a [UI test] differs from the expected output, you can update the reference file with: ```bash -cargo dev bless +cargo bless ``` For example, this is necessary if you fix a typo in an error message of a lint, diff --git a/clippy_dev/src/bless.rs b/clippy_dev/src/bless.rs deleted file mode 100644 index 92b2771f3fe..00000000000 --- a/clippy_dev/src/bless.rs +++ /dev/null @@ -1,60 +0,0 @@ -//! `bless` updates the reference files in the repo with changed output files -//! from the last test run. - -use crate::cargo_clippy_path; -use std::ffi::OsStr; -use std::fs; -use std::path::{Path, PathBuf}; -use std::sync::LazyLock; -use walkdir::{DirEntry, WalkDir}; - -static CLIPPY_BUILD_TIME: LazyLock> = - LazyLock::new(|| cargo_clippy_path().metadata().ok()?.modified().ok()); - -/// # Panics -/// -/// Panics if the path to a test file is broken -pub fn bless(ignore_timestamp: bool) { - let extensions = ["stdout", "stderr", "fixed"].map(OsStr::new); - - WalkDir::new(build_dir()) - .into_iter() - .map(Result::unwrap) - .filter(|entry| entry.path().extension().map_or(false, |ext| extensions.contains(&ext))) - .for_each(|entry| update_reference_file(&entry, ignore_timestamp)); -} - -fn update_reference_file(test_output_entry: &DirEntry, ignore_timestamp: bool) { - let test_output_path = test_output_entry.path(); - - let reference_file_name = test_output_entry.file_name().to_str().unwrap().replace(".stage-id", ""); - let reference_file_path = Path::new("tests") - .join(test_output_path.strip_prefix(build_dir()).unwrap()) - .with_file_name(reference_file_name); - - // If the test output was not updated since the last clippy build, it may be outdated - if !ignore_timestamp && !updated_since_clippy_build(test_output_entry).unwrap_or(true) { - return; - } - - let test_output_file = fs::read(test_output_path).expect("Unable to read test output file"); - let reference_file = fs::read(&reference_file_path).unwrap_or_default(); - - if test_output_file != reference_file { - // If a test run caused an output file to change, update the reference file - println!("updating {}", reference_file_path.display()); - fs::copy(test_output_path, &reference_file_path).expect("Could not update reference file"); - } -} - -fn updated_since_clippy_build(entry: &DirEntry) -> Option { - let clippy_build_time = (*CLIPPY_BUILD_TIME)?; - let modified = entry.metadata().ok()?.modified().ok()?; - Some(modified >= clippy_build_time) -} - -fn build_dir() -> PathBuf { - let mut path = std::env::current_exe().unwrap(); - path.set_file_name("test"); - path -} diff --git a/clippy_dev/src/lib.rs b/clippy_dev/src/lib.rs index 8aaa029f776..4624451cff4 100644 --- a/clippy_dev/src/lib.rs +++ b/clippy_dev/src/lib.rs @@ -14,7 +14,6 @@ use std::io; use std::path::PathBuf; use std::process::{self, ExitStatus}; -pub mod bless; pub mod dogfood; pub mod fmt; pub mod lint; diff --git a/clippy_dev/src/main.rs b/clippy_dev/src/main.rs index 97d6a8353a0..43eaccdf5a3 100644 --- a/clippy_dev/src/main.rs +++ b/clippy_dev/src/main.rs @@ -3,7 +3,7 @@ #![warn(rust_2018_idioms, unused_lifetimes)] use clap::{Arg, ArgAction, ArgMatches, Command}; -use clippy_dev::{bless, dogfood, fmt, lint, new_lint, serve, setup, update_lints}; +use clippy_dev::{dogfood, fmt, lint, new_lint, serve, setup, update_lints}; use indoc::indoc; use std::convert::Infallible; @@ -11,8 +11,8 @@ fn main() { let matches = get_clap_config(); match matches.subcommand() { - Some(("bless", matches)) => { - bless::bless(matches.get_flag("ignore-timestamp")); + Some(("bless", _)) => { + eprintln!("use `cargo bless` to automatically replace `.stderr` and `.fixed` files as tests are being run"); }, Some(("dogfood", matches)) => { dogfood::dogfood( diff --git a/clippy_dev/src/new_lint.rs b/clippy_dev/src/new_lint.rs index f0ccdb0fe10..f11aa547bd7 100644 --- a/clippy_dev/src/new_lint.rs +++ b/clippy_dev/src/new_lint.rs @@ -96,7 +96,7 @@ fn create_test(lint: &LintData<'_>) -> io::Result<()> { path.push("src"); fs::create_dir(&path)?; - let header = format!("// compile-flags: --crate-name={lint_name}"); + let header = format!("//@compile-flags: --crate-name={lint_name}"); write_file(path.join("main.rs"), get_test_file_contents(lint_name, Some(&header)))?; Ok(()) diff --git a/clippy_test_deps/Cargo.toml b/clippy_test_deps/Cargo.toml new file mode 100644 index 00000000000..6d053253fc3 --- /dev/null +++ b/clippy_test_deps/Cargo.toml @@ -0,0 +1,25 @@ +[package] +name = "clippy_test_deps" +version = "0.1.0" +edition = "2021" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +clap = { version = "4.1.4", features = ["derive"] } +clippy_utils = { path = "../clippy_utils" } +derive-new = "0.5" +if_chain = "1.0" +itertools = "0.10.1" +quote = "1.0" +serde = { version = "1.0.125", features = ["derive"] } +syn = { version = "2.0", features = ["full"] } +futures = "0.3" +parking_lot = "0.12" +tokio = { version = "1", features = ["io-util"] } +rustc-semver = "1.1" +regex = "1.5" +clippy_lints = { path = "../clippy_lints" } + +[features] +internal = ["clippy_lints/internal"] diff --git a/clippy_test_deps/src/lib.rs b/clippy_test_deps/src/lib.rs new file mode 100644 index 00000000000..7d12d9af819 --- /dev/null +++ b/clippy_test_deps/src/lib.rs @@ -0,0 +1,14 @@ +pub fn add(left: usize, right: usize) -> usize { + left + right +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn it_works() { + let result = add(2, 2); + assert_eq!(result, 4); + } +} diff --git a/clippy_utils/src/lib.rs b/clippy_utils/src/lib.rs index 5b5e9fba6af..078dcef1927 100644 --- a/clippy_utils/src/lib.rs +++ b/clippy_utils/src/lib.rs @@ -2397,7 +2397,7 @@ fn with_test_item_names(tcx: TyCtxt<'_>, module: LocalDefId, f: impl Fn(&[Symbol /// Checks if the function containing the given `HirId` is a `#[test]` function /// -/// Note: Add `// compile-flags: --test` to UI tests with a `#[test]` function +/// Note: Add `//@compile-flags: --test` to UI tests with a `#[test]` function pub fn is_in_test_function(tcx: TyCtxt<'_>, id: hir::HirId) -> bool { with_test_item_names(tcx, tcx.parent_module(id), |names| { tcx.hir() @@ -2419,7 +2419,7 @@ pub fn is_in_test_function(tcx: TyCtxt<'_>, id: hir::HirId) -> bool { /// Checks if the item containing the given `HirId` has `#[cfg(test)]` attribute applied /// -/// Note: Add `// compile-flags: --test` to UI tests with a `#[cfg(test)]` function +/// Note: Add `//@compile-flags: --test` to UI tests with a `#[cfg(test)]` function pub fn is_in_cfg_test(tcx: TyCtxt<'_>, id: hir::HirId) -> bool { fn is_cfg_test(attr: &Attribute) -> bool { if attr.has_name(sym::cfg) @@ -2441,7 +2441,7 @@ pub fn is_in_cfg_test(tcx: TyCtxt<'_>, id: hir::HirId) -> bool { /// Checks whether item either has `test` attribute applied, or /// is a module with `test` in its name. /// -/// Note: Add `// compile-flags: --test` to UI tests with a `#[test]` function +/// Note: Add `//@compile-flags: --test` to UI tests with a `#[test]` function pub fn is_test_module_or_function(tcx: TyCtxt<'_>, item: &Item<'_>) -> bool { is_in_test_function(tcx, item.hir_id()) || matches!(item.kind, ItemKind::Mod(..)) diff --git a/tests/compile-test.rs b/tests/compile-test.rs index 35d75cc51c2..281e778ada6 100644 --- a/tests/compile-test.rs +++ b/tests/compile-test.rs @@ -4,16 +4,14 @@ #![cfg_attr(feature = "deny-warnings", deny(warnings))] #![warn(rust_2018_idioms, unused_lifetimes)] -use compiletest_rs as compiletest; -use compiletest_rs::common::Mode as TestMode; +use compiletest::{status_emitter, CommandBuilder}; +use ui_test as compiletest; +use ui_test::Mode as TestMode; -use std::collections::HashMap; use std::env::{self, remove_var, set_var, var_os}; use std::ffi::{OsStr, OsString}; use std::fs; -use std::io; use std::path::{Path, PathBuf}; -use std::sync::LazyLock; use test_utils::IS_RUSTC_TEST_SUITE; mod test_utils; @@ -21,143 +19,41 @@ mod test_utils; // whether to run internal tests or not const RUN_INTERNAL_TESTS: bool = cfg!(feature = "internal"); -/// All crates used in UI tests are listed here -static TEST_DEPENDENCIES: &[&str] = &[ - "clippy_lints", - "clippy_utils", - "derive_new", - "futures", - "if_chain", - "itertools", - "quote", - "regex", - "serde", - "serde_derive", - "syn", - "tokio", - "parking_lot", - "rustc_semver", -]; - -// Test dependencies may need an `extern crate` here to ensure that they show up -// in the depinfo file (otherwise cargo thinks they are unused) -#[allow(unused_extern_crates)] -extern crate clippy_lints; -#[allow(unused_extern_crates)] -extern crate clippy_utils; -#[allow(unused_extern_crates)] -extern crate derive_new; -#[allow(unused_extern_crates)] -extern crate futures; -#[allow(unused_extern_crates)] -extern crate if_chain; -#[allow(unused_extern_crates)] -extern crate itertools; -#[allow(unused_extern_crates)] -extern crate parking_lot; -#[allow(unused_extern_crates)] -extern crate quote; -#[allow(unused_extern_crates)] -extern crate rustc_semver; -#[allow(unused_extern_crates)] -extern crate syn; -#[allow(unused_extern_crates)] -extern crate tokio; - -/// Produces a string with an `--extern` flag for all UI test crate -/// dependencies. -/// -/// The dependency files are located by parsing the depinfo file for this test -/// module. This assumes the `-Z binary-dep-depinfo` flag is enabled. All test -/// dependencies must be added to Cargo.toml at the project root. Test -/// dependencies that are not *directly* used by this test module require an -/// `extern crate` declaration. -static EXTERN_FLAGS: LazyLock = LazyLock::new(|| { - let current_exe_depinfo = { - let mut path = env::current_exe().unwrap(); - path.set_extension("d"); - fs::read_to_string(path).unwrap() - }; - let mut crates: HashMap<&str, &str> = HashMap::with_capacity(TEST_DEPENDENCIES.len()); - for line in current_exe_depinfo.lines() { - // each dependency is expected to have a Makefile rule like `/path/to/crate-hash.rlib:` - let parse_name_path = || { - if line.starts_with(char::is_whitespace) { - return None; - } - let path_str = line.strip_suffix(':')?; - let path = Path::new(path_str); - if !matches!(path.extension()?.to_str()?, "rlib" | "so" | "dylib" | "dll") { - return None; - } - let (name, _hash) = path.file_stem()?.to_str()?.rsplit_once('-')?; - // the "lib" prefix is not present for dll files - let name = name.strip_prefix("lib").unwrap_or(name); - Some((name, path_str)) - }; - if let Some((name, path)) = parse_name_path() { - if TEST_DEPENDENCIES.contains(&name) { - // A dependency may be listed twice if it is available in sysroot, - // and the sysroot dependencies are listed first. As of the writing, - // this only seems to apply to if_chain. - crates.insert(name, path); - } - } - } - let not_found: Vec<&str> = TEST_DEPENDENCIES - .iter() - .copied() - .filter(|n| !crates.contains_key(n)) - .collect(); - assert!( - not_found.is_empty(), - "dependencies not found in depinfo: {not_found:?}\n\ - help: Make sure the `-Z binary-dep-depinfo` rust flag is enabled\n\ - help: Try adding to dev-dependencies in Cargo.toml\n\ - help: Be sure to also add `extern crate ...;` to tests/compile-test.rs", - ); - crates - .into_iter() - .map(|(name, path)| format!(" --extern {name}={path}")) - .collect() -}); - 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() + mode: TestMode::Yolo, + stderr_filters: vec![], + stdout_filters: vec![], + output_conflict_handling: if std::env::args().any(|arg| arg == "--bless") { + compiletest::OutputConflictHandling::Bless + } else { + compiletest::OutputConflictHandling::Error("cargo test -- -- --bless".into()) + }, + dependencies_crate_manifest_path: Some("clippy_test_deps/Cargo.toml".into()), + target: None, + out_dir: "target/ui_test".into(), + ..compiletest::Config::rustc(Path::new("tests").join(test_dir)) }; - if let Ok(filters) = env::var("TESTNAME") { - config.filters = filters.split(',').map(ToString::to_string).collect(); - } - - if let Some(path) = option_env!("RUSTC_LIB_PATH") { - let path = PathBuf::from(path); - config.run_lib_path = path.clone(); - config.compile_lib_path = path; + if let Some(_path) = option_env!("RUSTC_LIB_PATH") { + //let path = PathBuf::from(path); + //config.run_lib_path = path.clone(); + //config.compile_lib_path = path; } let current_exe_path = env::current_exe().unwrap(); let deps_path = current_exe_path.parent().unwrap(); let profile_path = deps_path.parent().unwrap(); - // Using `-L dependency={}` enforces that external dependencies are added with `--extern`. - // This is valuable because a) it allows us to monitor what external dependencies are used - // and b) it ensures that conflicting rlibs are resolved properly. - let host_libs = option_env!("HOST_LIBS") - .map(|p| format!(" -L dependency={}", Path::new(p).join("deps").display())) - .unwrap_or_default(); - config.target_rustcflags = Some(format!( - "--emit=metadata -Dwarnings -Zui-testing -L dependency={}{host_libs}{}", - deps_path.display(), - &*EXTERN_FLAGS, - )); + config.program.args.push("--emit=metadata".into()); + config.program.args.push("-Aunused".into()); + config.program.args.push("-Zui-testing".into()); + config.program.args.push("-Dwarnings".into()); - config.src_base = Path::new("tests").join(test_dir); - config.build_base = profile_path.join("test").join(test_dir); - config.rustc_path = profile_path.join(if cfg!(windows) { + // Normalize away slashes in windows paths. + config.stderr_filter(r#"\\"#, "/"); + + //config.build_base = profile_path.join("test").join(test_dir); + config.program.program = profile_path.join(if cfg!(windows) { "clippy-driver.exe" } else { "clippy-driver" @@ -165,9 +61,23 @@ fn base_config(test_dir: &str) -> compiletest::Config { config } +fn test_filter() -> Box bool> { + if let Ok(filters) = env::var("TESTNAME") { + let filters: Vec<_> = filters.split(',').map(ToString::to_string).collect(); + Box::new(move |path| { + filters.is_empty() + || filters + .iter() + .any(|f| path.file_stem().map_or(false, |stem| stem == f.as_str())) + }) + } else { + Box::new(|_| true) + } +} + fn run_ui() { - let mut config = base_config("ui"); - config.rustfix_coverage = true; + let config = base_config("ui"); + //config.rustfix_coverage = true; // use tests/clippy.toml let _g = VarGuard::set("CARGO_MANIFEST_DIR", fs::canonicalize("tests").unwrap()); let _threads = VarGuard::set( @@ -179,7 +89,19 @@ fn run_ui() { .to_string() }), ); - compiletest::run_tests(&config); + eprintln!(" Compiler: {}", config.program.display()); + + let name = config.root_dir.display().to_string(); + + let test_filter = test_filter(); + + compiletest::run_tests_generic( + config, + move |path| compiletest::default_file_filter(path) && test_filter(path), + compiletest::default_per_file_config, + (status_emitter::Text, status_emitter::Gha:: { name }), + ) + .unwrap(); check_rustfix_coverage(); } @@ -188,177 +110,114 @@ fn run_internal_tests() { if !RUN_INTERNAL_TESTS { return; } - let config = base_config("ui-internal"); - compiletest::run_tests(&config); + let mut config = base_config("ui-internal"); + config.dependency_builder.args.push("--features".into()); + config.dependency_builder.args.push("internal".into()); + compiletest::run_tests(config).unwrap(); } fn run_ui_toml() { - fn run_tests(config: &compiletest::Config, mut tests: Vec) -> Result { - let mut result = true; - let opts = compiletest::test_opts(config); - for dir in fs::read_dir(&config.src_base)? { - let dir = dir?; - if !dir.file_type()?.is_dir() { - continue; - } - let dir_path = dir.path(); - let _g = VarGuard::set("CARGO_MANIFEST_DIR", &dir_path); - for file in fs::read_dir(&dir_path)? { - let file = file?; - let file_path = file.path(); - if file.file_type()?.is_dir() { - continue; - } - if file_path.extension() != Some(OsStr::new("rs")) { - continue; - } - let paths = compiletest::common::TestPaths { - file: file_path, - base: config.src_base.clone(), - relative_dir: dir_path.file_name().unwrap().into(), - }; - let test_name = compiletest::make_test_name(config, &paths); - let index = tests - .iter() - .position(|test| test.desc.name == test_name) - .expect("The test should be in there"); - result &= tester::run_tests_console(&opts, vec![tests.swap_remove(index)])?; - } - } - Ok(result) - } - let mut config = base_config("ui-toml"); - config.src_base = config.src_base.canonicalize().unwrap(); - let tests = compiletest::make_tests(&config); + config.stderr_filter( + ®ex::escape( + &std::path::Path::new(file!()) + .parent() + .unwrap() + .canonicalize() + .unwrap() + .parent() + .unwrap() + .display() + .to_string() + .replace('\\', "/"), + ), + "$$DIR", + ); - let res = run_tests(&config, tests); - match res { - Ok(true) => {}, - Ok(false) => panic!("Some tests failed"), - Err(e) => { - panic!("I/O failure during tests: {e:?}"); + let name = config.root_dir.display().to_string(); + + let test_filter = test_filter(); + + ui_test::run_tests_generic( + config, + |path| test_filter(path) && path.extension() == Some("rs".as_ref()), + |config, path| { + let mut config = config.clone(); + config + .program + .envs + .push(("CLIPPY_CONF_DIR".into(), Some(path.parent().unwrap().into()))); + Some(config) }, - } + (status_emitter::Text, status_emitter::Gha:: { name }), + ) + .unwrap(); } fn run_ui_cargo() { - fn run_tests( - config: &compiletest::Config, - filters: &[String], - mut tests: Vec, - ) -> Result { - let mut result = true; - let opts = compiletest::test_opts(config); - - for dir in fs::read_dir(&config.src_base)? { - let dir = dir?; - if !dir.file_type()?.is_dir() { - continue; - } - - // Use the filter if provided - let dir_path = dir.path(); - for filter in filters { - if !dir_path.ends_with(filter) { - continue; - } - } - - for case in fs::read_dir(&dir_path)? { - let case = case?; - if !case.file_type()?.is_dir() { - continue; - } - - let src_path = case.path().join("src"); - - // When switching between branches, if the previous branch had a test - // that the current branch does not have, the directory is not removed - // because an ignored Cargo.lock file exists. - if !src_path.exists() { - continue; - } - - env::set_current_dir(&src_path)?; - - let cargo_toml_path = case.path().join("Cargo.toml"); - let cargo_content = fs::read(cargo_toml_path)?; - let cargo_parsed: toml::Value = toml::from_str( - std::str::from_utf8(&cargo_content).expect("`Cargo.toml` is not a valid utf-8 file!"), - ) - .expect("Can't parse `Cargo.toml`"); - - let _g = VarGuard::set("CARGO_MANIFEST_DIR", case.path()); - let _h = VarGuard::set( - "CARGO_PKG_RUST_VERSION", - cargo_parsed - .get("package") - .and_then(|p| p.get("rust-version")) - .and_then(toml::Value::as_str) - .unwrap_or(""), - ); - - for file in fs::read_dir(&src_path)? { - let file = file?; - if file.file_type()?.is_dir() { - continue; - } - - // Search for the main file to avoid running a test for each file in the project - let file_path = file.path(); - match file_path.file_name().and_then(OsStr::to_str) { - Some("main.rs") => {}, - _ => continue, - } - let _g = VarGuard::set("CLIPPY_CONF_DIR", case.path()); - let paths = compiletest::common::TestPaths { - file: file_path, - base: config.src_base.clone(), - relative_dir: src_path.strip_prefix(&config.src_base).unwrap().into(), - }; - let test_name = compiletest::make_test_name(config, &paths); - let index = tests - .iter() - .position(|test| test.desc.name == test_name) - .expect("The test should be in there"); - result &= tester::run_tests_console(&opts, vec![tests.swap_remove(index)])?; - } - } - } - Ok(result) - } - if IS_RUSTC_TEST_SUITE { return; } let mut config = base_config("ui-cargo"); - config.src_base = config.src_base.canonicalize().unwrap(); + config.program = CommandBuilder::cargo(); + config.program.args = vec!["clippy".into(), "--color".into(), "never".into(), "--quiet".into()]; + config + .program + .envs + .push(("RUSTFLAGS".into(), Some("-Dwarnings".into()))); + // We need to do this while we still have a rustc in the `program` field. + config.fill_host_and_target().unwrap(); + config.dependencies_crate_manifest_path = None; + config.program.program.set_file_name(if cfg!(windows) { + "cargo-clippy.exe" + } else { + "cargo-clippy" + }); + config.edition = None; - let tests = compiletest::make_tests(&config); + config.stderr_filter( + ®ex::escape( + &std::path::Path::new(file!()) + .parent() + .unwrap() + .canonicalize() + .unwrap() + .parent() + .unwrap() + .display() + .to_string() + .replace('\\', "/"), + ), + "$$DIR", + ); - let current_dir = env::current_dir().unwrap(); - let res = run_tests(&config, &config.filters, tests); - env::set_current_dir(current_dir).unwrap(); + let name = config.root_dir.display().to_string(); - match res { - Ok(true) => {}, - Ok(false) => panic!("Some tests failed"), - Err(e) => { - panic!("I/O failure during tests: {e:?}"); + let test_filter = test_filter(); + + ui_test::run_tests_generic( + config, + |path| test_filter(path) && path.ends_with("Cargo.toml"), + |config, path| { + let mut config = config.clone(); + config.out_dir = PathBuf::from("target/ui_test_cargo/").join(path.parent().unwrap()); + Some(config) }, - } + (status_emitter::Text, status_emitter::Gha:: { name }), + ) + .unwrap(); } -#[test] -fn compile_test() { +fn main() { set_var("CLIPPY_DISABLE_DOCS_LINKS", "true"); run_ui(); run_ui_toml(); run_ui_cargo(); run_internal_tests(); + rustfix_coverage_known_exceptions_accuracy(); + ui_cargo_toml_metadata(); } const RUSTFIX_COVERAGE_KNOWN_EXCEPTIONS: &[&str] = &[ @@ -384,7 +243,6 @@ const RUSTFIX_COVERAGE_KNOWN_EXCEPTIONS: &[&str] = &[ "needless_for_each_unfixable.rs", "nonminimal_bool.rs", "print_literal.rs", - "print_with_newline.rs", "redundant_static_lifetimes_multiple.rs", "ref_binding_to_reference.rs", "repl_uninit.rs", @@ -399,7 +257,6 @@ const RUSTFIX_COVERAGE_KNOWN_EXCEPTIONS: &[&str] = &[ "unnecessary_lazy_eval_unfixable.rs", "write_literal.rs", "write_literal_2.rs", - "write_with_newline.rs", ]; fn check_rustfix_coverage() { @@ -432,25 +289,16 @@ fn check_rustfix_coverage() { } } -#[test] fn rustfix_coverage_known_exceptions_accuracy() { for filename in RUSTFIX_COVERAGE_KNOWN_EXCEPTIONS { let rs_path = Path::new("tests/ui").join(filename); - assert!( - rs_path.exists(), - "`{}` does not exist", - rs_path.strip_prefix(env!("CARGO_MANIFEST_DIR")).unwrap().display() - ); + assert!(rs_path.exists(), "`{}` does not exist", rs_path.display()); let fixed_path = rs_path.with_extension("fixed"); - assert!( - !fixed_path.exists(), - "`{}` exists", - fixed_path.strip_prefix(env!("CARGO_MANIFEST_DIR")).unwrap().display() - ); + println!("{}", fixed_path.display()); + assert!(!fixed_path.exists(), "`{}` exists", fixed_path.display()); } } -#[test] fn ui_cargo_toml_metadata() { let ui_cargo_path = Path::new("tests/ui-cargo"); let cargo_common_metadata_path = ui_cargo_path.join("cargo_common_metadata"); diff --git a/tests/missing-test-files.rs b/tests/missing-test-files.rs index caedd5d76cd..0d35a22cd9a 100644 --- a/tests/missing-test-files.rs +++ b/tests/missing-test-files.rs @@ -41,8 +41,8 @@ fn explore_directory(dir: &Path) -> Vec { x.path().extension().and_then(OsStr::to_str), y.path().extension().and_then(OsStr::to_str), ) { - (Some("rs"), _) => Ordering::Less, - (_, Some("rs")) => Ordering::Greater, + (Some("rs" | "toml"), _) => Ordering::Less, + (_, Some("rs" | "toml")) => Ordering::Greater, _ => Ordering::Equal, } }); @@ -54,7 +54,7 @@ fn explore_directory(dir: &Path) -> Vec { let file_prefix = path.file_prefix().unwrap().to_str().unwrap().to_string(); if let Some(ext) = path.extension() { match ext.to_str().unwrap() { - "rs" => current_file = file_prefix.clone(), + "rs" | "toml" => current_file = file_prefix.clone(), "stderr" | "stdout" => { if file_prefix != current_file { missing_files.push(path.to_str().unwrap().to_string()); diff --git a/util/etc/vscode-tasks.json b/util/etc/vscode-tasks.json index ab98f9b4154..38e31b337a0 100644 --- a/util/etc/vscode-tasks.json +++ b/util/etc/vscode-tasks.json @@ -47,9 +47,9 @@ "group": "test" }, { - "label": "cargo dev bless", + "label": "bless ui tests", "type": "shell", - "command": "cargo dev bless", + "command": "cargo bless", "problemMatcher": [], "group": "none" } From 5bd97ac17a920f03fd1f7dd57ac27729524e31e1 Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Thu, 20 Apr 2023 15:19:36 +0000 Subject: [PATCH 262/310] Update tests --- .../fail/{src/main.stderr => Cargo.stderr} | 7 +- .../{src/main.stderr => Cargo.stderr} | 7 +- .../{src/main.stderr => Cargo.stderr} | 7 +- .../fail_both_diff/Cargo.stderr | 21 + .../fail_both_diff/src/main.stderr | 22 - .../fail_both_same/Cargo.stderr | 19 + .../fail_both_same/src/main.stderr | 20 - .../fail_cargo/Cargo.stderr | 19 + .../fail_cargo/src/main.stderr | 20 - .../fail_clippy/Cargo.stderr | 19 + .../Cargo.stderr} | 15 +- .../fail_file_attr/src/main.stderr | 20 - .../{src/main.stderr => Cargo.stderr} | 2 - .../ui-cargo/duplicate_mod/fail/Cargo.stderr | 52 ++ .../duplicate_mod/fail/src/main.stderr | 53 -- tests/ui-cargo/feature_name/fail/Cargo.stderr | 43 ++ .../feature_name/fail/src/main.stderr | 44 -- .../module_style/fail_mod/Cargo.stderr | 18 + .../module_style/fail_mod/src/main.stderr | 19 - .../module_style/fail_mod_remap/Cargo.stderr | 10 + .../fail_mod_remap/src/main.stderr | 11 - .../module_style/fail_no_mod/Cargo.stderr | 10 + .../module_style/fail_no_mod/src/main.stderr | 11 - .../multiple_config_files/warn/Cargo.stderr | 2 + .../warn/src/main.stderr | 4 - .../multiple_crate_versions/fail/Cargo.stderr | 5 + .../fail/src/main.stderr | 6 - tests/ui-cargo/update-all-references.sh | 2 +- .../wildcard_dependencies/fail/Cargo.stderr | 5 + .../fail/src/main.stderr | 6 - tests/ui-internal/custom_ice_message.stderr | 2 +- tests/ui-toml/bad_toml/conf_bad_toml.rs | 2 + tests/ui-toml/bad_toml/conf_bad_toml.stderr | 2 +- tests/ui-toml/bad_toml_type/conf_bad_type.rs | 2 + .../bad_toml_type/conf_bad_type.stderr | 2 +- .../conf_deprecated_key.stderr | 4 +- .../duplicated_keys/duplicated_keys.rs | 2 + .../duplicated_keys/duplicated_keys.stderr | 2 +- .../duplicated_keys.stderr | 4 +- .../duplicated_keys.stderr | 4 +- .../auxiliary/proc_macros.rs | 4 - .../excessive_nesting/excessive_nesting.rs | 2 +- .../invalid_min_rust_version.rs | 2 + .../ui-toml/lint_decimal_readability/test.rs | 2 +- .../lint_decimal_readability/test.stderr | 10 +- .../index_refutable_slice.rs | 1 + .../min_rust_version/min_rust_version.rs | 4 +- .../auxiliary/proc_macro_derive.rs | 5 - .../conf_nonstandard_macro_braces.fixed | 2 +- .../conf_nonstandard_macro_braces.rs | 2 +- tests/ui-toml/suppress_lint_in_const/test.rs | 3 + .../suppress_lint_in_const/test.stderr | 16 +- tests/ui-toml/toml_trivially_copy/test.rs | 2 +- tests/ui-toml/toml_trivially_copy/test.stderr | 6 +- .../toml_unknown_key/conf_unknown_key.rs | 2 +- .../toml_unknown_key/conf_unknown_key.stderr | 4 +- .../auxiliary/proc_macro_unsafe.rs | 5 - .../undocumented_unsafe_blocks.rs | 2 +- tests/ui-toml/unwrap_used/unwrap_used.rs | 2 +- tests/ui-toml/unwrap_used/unwrap_used.stderr | 6 +- tests/ui-toml/update-all-references.sh | 2 +- tests/ui/allow_attributes.fixed | 2 +- tests/ui/allow_attributes.rs | 2 +- tests/ui/allow_attributes_without_reason.rs | 2 +- tests/ui/almost_complete_range.fixed | 2 +- tests/ui/almost_complete_range.rs | 2 +- tests/ui/arithmetic_side_effects.rs | 2 +- tests/ui/as_conversions.rs | 2 +- tests/ui/asm_syntax.rs | 4 +- tests/ui/auxiliary/macro_use_helper.rs | 2 + tests/ui/auxiliary/proc_macro_attr.rs | 4 - tests/ui/auxiliary/proc_macro_derive.rs | 4 - .../proc_macro_suspicious_else_formatting.rs | 5 - tests/ui/auxiliary/proc_macro_unsafe.rs | 5 - tests/ui/auxiliary/proc_macros.rs | 4 - tests/ui/borrow_deref_ref.fixed | 2 +- tests/ui/borrow_deref_ref.rs | 2 +- .../ui/borrow_interior_mutable_const/enums.rs | 26 +- .../enums.stderr | 24 +- .../borrow_interior_mutable_const/others.rs | 30 +- .../others.stderr | 34 +- .../borrow_interior_mutable_const/traits.rs | 32 +- .../traits.stderr | 36 +- tests/ui/builtin_type_shadow.rs | 2 +- tests/ui/cmp_owned/with_suggestion.fixed | 2 +- tests/ui/cognitive_complexity.stderr | 10 +- .../ui/crashes/auxiliary/proc_macro_crash.rs | 8 - tests/ui/crashes/ice-10148.rs | 2 +- tests/ui/crashes/ice-3741.rs | 2 +- tests/ui/crashes/ice-5497.rs | 2 +- tests/ui/crashes/ice-6250.stderr | 11 +- tests/ui/crashes/ice-6251.stderr | 10 +- tests/ui/crashes/ice-6255.rs | 2 +- tests/ui/crashes/ice-6256.rs | 4 +- tests/ui/crashes/ice-6256.stderr | 2 +- tests/ui/crashes/ice-7410.rs | 4 +- tests/ui/crashes/ice-96721.rs | 2 +- tests/ui/crashes/ice-96721.stderr | 2 +- .../entrypoint_recursion.rs | 2 +- .../entrypoint_recursion.stderr | 11 - .../no_std_main_recursion.rs | 2 +- tests/ui/dbg_macro.rs | 1 - tests/ui/dbg_macro.stderr | 36 +- .../declare_interior_mutable_const/enums.rs | 27 +- .../enums.stderr | 49 +- .../declare_interior_mutable_const/others.rs | 16 +- .../others.stderr | 8 +- .../declare_interior_mutable_const/traits.rs | 22 +- .../traits.stderr | 22 +- tests/ui/def_id_nocore.rs | 2 +- tests/ui/default_numeric_fallback_f64.fixed | 2 +- tests/ui/default_numeric_fallback_f64.rs | 2 +- tests/ui/default_numeric_fallback_i32.fixed | 2 +- tests/ui/default_numeric_fallback_i32.rs | 2 +- tests/ui/default_trait_access.fixed | 2 +- tests/ui/default_trait_access.rs | 2 +- tests/ui/deref_addrof.fixed | 2 +- tests/ui/deref_addrof.rs | 2 +- tests/ui/deref_addrof_macro.rs | 2 +- tests/ui/doc_unsafe.rs | 2 +- tests/ui/else_if_without_else.rs | 4 +- tests/ui/else_if_without_else.stderr | 4 +- tests/ui/empty_line_after_doc_comments.rs | 2 +- tests/ui/empty_line_after_outer_attribute.rs | 2 +- tests/ui/empty_loop.rs | 2 +- tests/ui/empty_loop_no_std.rs | 2 +- tests/ui/enum_clike_unportable_variant.rs | 2 +- tests/ui/eprint_with_newline.rs | 2 +- tests/ui/eprint_with_newline.stderr | 12 +- tests/ui/eq_op.rs | 2 - tests/ui/eq_op.stderr | 56 +- tests/ui/equatable_if_let.fixed | 2 +- tests/ui/equatable_if_let.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/get_unwrap.fixed | 6 +- tests/ui/get_unwrap.rs | 6 +- tests/ui/get_unwrap.stderr | 6 +- tests/ui/if_same_then_else.rs | 10 +- tests/ui/if_same_then_else.stderr | 24 +- tests/ui/if_same_then_else2.rs | 11 +- tests/ui/if_same_then_else2.stderr | 25 +- tests/ui/ifs_same_cond.rs | 7 +- tests/ui/implicit_hasher.rs | 2 +- .../ui/inconsistent_struct_constructor.fixed | 2 +- tests/ui/inconsistent_struct_constructor.rs | 2 +- tests/ui/into_iter_on_ref.fixed | 54 +- tests/ui/into_iter_on_ref.rs | 54 +- tests/ui/into_iter_on_ref.stderr | 54 +- tests/ui/issue-3145.rs | 2 +- tests/ui/issue-3145.stderr | 2 +- .../block_module.stderr | 17 +- tests/ui/large_enum_variant.rs | 2 +- tests/ui/let_underscore_untyped.rs | 2 +- tests/ui/let_with_type_underscore.rs | 2 +- tests/ui/macro_use_imports.fixed | 2 +- tests/ui/macro_use_imports.rs | 2 +- tests/ui/macro_use_imports.stderr | 20 +- tests/ui/macro_use_imports_expect.rs | 2 +- tests/ui/manual_rem_euclid.fixed | 2 +- tests/ui/manual_rem_euclid.rs | 2 +- tests/ui/manual_slice_size_calculation.fixed | 2 +- tests/ui/manual_slice_size_calculation.rs | 2 +- tests/ui/match_same_arms.rs | 20 +- tests/ui/match_same_arms.stderr | 24 +- tests/ui/match_same_arms2.rs | 23 +- tests/ui/match_same_arms2.stderr | 33 +- tests/ui/mem_replace_macro.rs | 2 +- tests/ui/min_ident_chars.rs | 2 +- tests/ui/missing_assert_message.rs | 11 +- tests/ui/missing_assert_message.stderr | 32 +- .../ui/missing_const_for_fn/cant_be_const.rs | 3 +- tests/ui/missing_doc.rs | 2 +- tests/ui/missing_doc_impl.rs | 2 +- tests/ui/missing_inline_proc_macro.rs | 1 - tests/ui/mistyped_literal_suffix.fixed | 2 +- tests/ui/mistyped_literal_suffix.rs | 2 +- tests/ui/multiple_unsafe_ops_per_block.rs | 2 +- tests/ui/must_use_unit.fixed | 2 +- tests/ui/must_use_unit.rs | 2 +- tests/ui/mut_mut.rs | 2 +- .../needless_arbitrary_self_type_unfixable.rs | 2 +- tests/ui/needless_if.fixed | 2 +- tests/ui/needless_if.rs | 2 +- tests/ui/needless_late_init.fixed | 2 +- tests/ui/needless_late_init.rs | 2 +- tests/ui/needless_lifetimes.fixed | 2 +- tests/ui/needless_lifetimes.rs | 2 +- tests/ui/needless_pass_by_value_proc_macro.rs | 1 - tests/ui/non_expressive_names.rs | 12 +- tests/ui/non_expressive_names.stderr | 6 +- tests/ui/non_octal_unix_permissions.fixed | 2 +- tests/ui/non_octal_unix_permissions.rs | 2 +- tests/ui/octal_escapes.stderr | 6 +- tests/ui/option_env_unwrap.rs | 2 +- tests/ui/print_with_newline.fixed | 58 ++ tests/ui/print_with_newline.rs | 2 +- tests/ui/print_with_newline.stderr | 12 +- tests/ui/proc_macro.rs | 1 - tests/ui/proc_macro.stderr | 2 +- tests/ui/ptr_as_ptr.fixed | 2 +- tests/ui/ptr_as_ptr.rs | 2 +- tests/ui/ptr_cast_constness.fixed | 2 +- tests/ui/ptr_cast_constness.rs | 2 +- tests/ui/redundant_pub_crate.fixed | 8 +- tests/ui/redundant_pub_crate.rs | 8 +- tests/ui/redundant_static_lifetimes.fixed | 22 +- tests/ui/redundant_static_lifetimes.rs | 22 +- tests/ui/redundant_static_lifetimes.stderr | 24 +- .../ui/redundant_static_lifetimes_multiple.rs | 6 +- ...redundant_static_lifetimes_multiple.stderr | 12 +- tests/ui/regex.stderr | 4 +- tests/ui/same_functions_in_if_condition.rs | 12 +- .../ui/same_functions_in_if_condition.stderr | 4 +- tests/ui/shadow.rs | 2 +- tests/ui/significant_drop_in_scrutinee.fixed | 627 ++++++++++++++++++ tests/ui/single_call_fn.rs | 3 +- tests/ui/single_call_fn.stderr | 16 +- tests/ui/single_char_pattern.stderr | 4 +- tests/ui/single_match_else.fixed | 2 +- tests/ui/single_match_else.rs | 2 +- tests/ui/single_range_in_vec_init.rs | 6 +- tests/ui/string_add.rs | 2 +- tests/ui/suspicious_else_formatting.rs | 2 +- tests/ui/tests_outside_test_module.rs | 1 - tests/ui/tests_outside_test_module.stderr | 2 +- tests/ui/toplevel_ref_arg.fixed | 2 +- tests/ui/toplevel_ref_arg.rs | 2 +- tests/ui/toplevel_ref_arg_non_rustfix.rs | 2 +- tests/ui/transmute_ptr_to_ptr.rs | 2 +- tests/ui/try_err.fixed | 2 +- tests/ui/try_err.rs | 2 +- tests/ui/undocumented_unsafe_blocks.rs | 2 +- tests/ui/unicode.fixed | 1 - tests/ui/unicode.rs | 1 - tests/ui/unicode.stderr | 20 +- tests/ui/uninlined_format_args.fixed | 2 +- tests/ui/uninlined_format_args.rs | 2 +- tests/ui/unit_arg.rs | 2 +- tests/ui/unnecessary_lazy_eval.fixed | 2 +- tests/ui/unnecessary_lazy_eval.rs | 2 +- tests/ui/unnecessary_unsafety_doc.rs | 2 +- tests/ui/unseparated_prefix_literals.fixed | 2 +- tests/ui/unseparated_prefix_literals.rs | 2 +- tests/ui/update-all-references.sh | 2 +- tests/ui/use_self.fixed | 2 +- tests/ui/use_self.rs | 2 +- tests/ui/used_underscore_binding.rs | 2 +- tests/ui/useless_attribute.fixed | 2 +- tests/ui/useless_attribute.rs | 2 +- tests/ui/wildcard_imports.fixed | 2 +- tests/ui/wildcard_imports.rs | 2 +- tests/ui/wildcard_imports.stderr | 4 +- tests/ui/write_literal_2.stderr | 22 +- tests/ui/write_with_newline.fixed | 63 ++ tests/ui/write_with_newline.stderr | 12 +- 258 files changed, 1740 insertions(+), 1063 deletions(-) rename tests/ui-cargo/cargo_common_metadata/fail/{src/main.stderr => Cargo.stderr} (74%) rename tests/ui-cargo/cargo_common_metadata/fail_publish/{src/main.stderr => Cargo.stderr} (74%) rename tests/ui-cargo/cargo_common_metadata/fail_publish_true/{src/main.stderr => Cargo.stderr} (74%) create mode 100644 tests/ui-cargo/cargo_rust_version/fail_both_diff/Cargo.stderr delete mode 100644 tests/ui-cargo/cargo_rust_version/fail_both_diff/src/main.stderr create mode 100644 tests/ui-cargo/cargo_rust_version/fail_both_same/Cargo.stderr delete mode 100644 tests/ui-cargo/cargo_rust_version/fail_both_same/src/main.stderr create mode 100644 tests/ui-cargo/cargo_rust_version/fail_cargo/Cargo.stderr delete mode 100644 tests/ui-cargo/cargo_rust_version/fail_cargo/src/main.stderr create mode 100644 tests/ui-cargo/cargo_rust_version/fail_clippy/Cargo.stderr rename tests/ui-cargo/cargo_rust_version/{fail_clippy/src/main.stderr => fail_file_attr/Cargo.stderr} (56%) delete mode 100644 tests/ui-cargo/cargo_rust_version/fail_file_attr/src/main.stderr rename tests/ui-cargo/cargo_rust_version/warn_both_diff/{src/main.stderr => Cargo.stderr} (77%) create mode 100644 tests/ui-cargo/duplicate_mod/fail/Cargo.stderr delete mode 100644 tests/ui-cargo/duplicate_mod/fail/src/main.stderr create mode 100644 tests/ui-cargo/feature_name/fail/Cargo.stderr delete mode 100644 tests/ui-cargo/feature_name/fail/src/main.stderr create mode 100644 tests/ui-cargo/module_style/fail_mod/Cargo.stderr delete mode 100644 tests/ui-cargo/module_style/fail_mod/src/main.stderr create mode 100644 tests/ui-cargo/module_style/fail_mod_remap/Cargo.stderr delete mode 100644 tests/ui-cargo/module_style/fail_mod_remap/src/main.stderr create mode 100644 tests/ui-cargo/module_style/fail_no_mod/Cargo.stderr delete mode 100644 tests/ui-cargo/module_style/fail_no_mod/src/main.stderr create mode 100644 tests/ui-cargo/multiple_config_files/warn/Cargo.stderr delete mode 100644 tests/ui-cargo/multiple_config_files/warn/src/main.stderr create mode 100644 tests/ui-cargo/multiple_crate_versions/fail/Cargo.stderr delete mode 100644 tests/ui-cargo/multiple_crate_versions/fail/src/main.stderr create mode 100644 tests/ui-cargo/wildcard_dependencies/fail/Cargo.stderr delete mode 100644 tests/ui-cargo/wildcard_dependencies/fail/src/main.stderr delete mode 100644 tests/ui/crate_level_checks/entrypoint_recursion.stderr create mode 100644 tests/ui/print_with_newline.fixed create mode 100644 tests/ui/significant_drop_in_scrutinee.fixed create mode 100644 tests/ui/write_with_newline.fixed diff --git a/tests/ui-cargo/cargo_common_metadata/fail/src/main.stderr b/tests/ui-cargo/cargo_common_metadata/fail/Cargo.stderr similarity index 74% rename from tests/ui-cargo/cargo_common_metadata/fail/src/main.stderr rename to tests/ui-cargo/cargo_common_metadata/fail/Cargo.stderr index 86953142bef..e161507b533 100644 --- a/tests/ui-cargo/cargo_common_metadata/fail/src/main.stderr +++ b/tests/ui-cargo/cargo_common_metadata/fail/Cargo.stderr @@ -1,6 +1,6 @@ error: package `cargo_common_metadata_fail` is missing `package.description` metadata - | - = note: `-D clippy::cargo-common-metadata` implied by `-D warnings` + | + = note: `-D clippy::cargo-common-metadata` implied by `-D warnings` error: package `cargo_common_metadata_fail` is missing `either package.license or package.license_file` metadata @@ -12,5 +12,4 @@ error: package `cargo_common_metadata_fail` is missing `package.keywords` metada error: package `cargo_common_metadata_fail` is missing `package.categories` metadata -error: aborting due to 6 previous errors - +error: could not compile `cargo_common_metadata_fail` (bin "cargo_common_metadata_fail") due to 6 previous errors diff --git a/tests/ui-cargo/cargo_common_metadata/fail_publish/src/main.stderr b/tests/ui-cargo/cargo_common_metadata/fail_publish/Cargo.stderr similarity index 74% rename from tests/ui-cargo/cargo_common_metadata/fail_publish/src/main.stderr rename to tests/ui-cargo/cargo_common_metadata/fail_publish/Cargo.stderr index ac1b5e8e903..dbf494cc342 100644 --- a/tests/ui-cargo/cargo_common_metadata/fail_publish/src/main.stderr +++ b/tests/ui-cargo/cargo_common_metadata/fail_publish/Cargo.stderr @@ -1,6 +1,6 @@ error: package `cargo_common_metadata_fail_publish` is missing `package.description` metadata - | - = note: `-D clippy::cargo-common-metadata` implied by `-D warnings` + | + = note: `-D clippy::cargo-common-metadata` implied by `-D warnings` error: package `cargo_common_metadata_fail_publish` is missing `either package.license or package.license_file` metadata @@ -12,5 +12,4 @@ error: package `cargo_common_metadata_fail_publish` is missing `package.keywords error: package `cargo_common_metadata_fail_publish` is missing `package.categories` metadata -error: aborting due to 6 previous errors - +error: could not compile `cargo_common_metadata_fail_publish` (bin "cargo_common_metadata_fail_publish") due to 6 previous errors diff --git a/tests/ui-cargo/cargo_common_metadata/fail_publish_true/src/main.stderr b/tests/ui-cargo/cargo_common_metadata/fail_publish_true/Cargo.stderr similarity index 74% rename from tests/ui-cargo/cargo_common_metadata/fail_publish_true/src/main.stderr rename to tests/ui-cargo/cargo_common_metadata/fail_publish_true/Cargo.stderr index be32c0dc418..ae5967406f6 100644 --- a/tests/ui-cargo/cargo_common_metadata/fail_publish_true/src/main.stderr +++ b/tests/ui-cargo/cargo_common_metadata/fail_publish_true/Cargo.stderr @@ -1,6 +1,6 @@ error: package `cargo_common_metadata_fail_publish_true` is missing `package.description` metadata - | - = note: `-D clippy::cargo-common-metadata` implied by `-D warnings` + | + = note: `-D clippy::cargo-common-metadata` implied by `-D warnings` error: package `cargo_common_metadata_fail_publish_true` is missing `either package.license or package.license_file` metadata @@ -12,5 +12,4 @@ error: package `cargo_common_metadata_fail_publish_true` is missing `package.key error: package `cargo_common_metadata_fail_publish_true` is missing `package.categories` metadata -error: aborting due to 6 previous errors - +error: could not compile `cargo_common_metadata_fail_publish_true` (bin "cargo_common_metadata_fail_publish_true") due to 6 previous errors diff --git a/tests/ui-cargo/cargo_rust_version/fail_both_diff/Cargo.stderr b/tests/ui-cargo/cargo_rust_version/fail_both_diff/Cargo.stderr new file mode 100644 index 00000000000..dfbf19d33a5 --- /dev/null +++ b/tests/ui-cargo/cargo_rust_version/fail_both_diff/Cargo.stderr @@ -0,0 +1,21 @@ +warning: the MSRV in `clippy.toml` and `Cargo.toml` differ; using `1.59.0` from `clippy.toml` + +error: unnecessary structure name repetition + --> src/main.rs:6:21 + | +6 | pub fn bar() -> Foo { + | ^^^ help: use the applicable keyword: `Self` + | +note: the lint level is defined here + --> src/main.rs:1:9 + | +1 | #![deny(clippy::use_self)] + | ^^^^^^^^^^^^^^^^ + +error: unnecessary structure name repetition + --> src/main.rs:7:9 + | +7 | Foo + | ^^^ help: use the applicable keyword: `Self` + +error: could not compile `fail-both-diff` (bin "fail-both-diff") due to 2 previous errors; 1 warning emitted diff --git a/tests/ui-cargo/cargo_rust_version/fail_both_diff/src/main.stderr b/tests/ui-cargo/cargo_rust_version/fail_both_diff/src/main.stderr deleted file mode 100644 index 163f8bb35e7..00000000000 --- a/tests/ui-cargo/cargo_rust_version/fail_both_diff/src/main.stderr +++ /dev/null @@ -1,22 +0,0 @@ -warning: the MSRV in `clippy.toml` and `Cargo.toml` differ; using `1.59.0` from `clippy.toml` - -error: unnecessary structure name repetition - --> $DIR/main.rs:6:21 - | -LL | pub fn bar() -> Foo { - | ^^^ help: use the applicable keyword: `Self` - | -note: the lint level is defined here - --> $DIR/main.rs:1:9 - | -LL | #![deny(clippy::use_self)] - | ^^^^^^^^^^^^^^^^ - -error: unnecessary structure name repetition - --> $DIR/main.rs:7:9 - | -LL | Foo - | ^^^ help: use the applicable keyword: `Self` - -error: aborting due to 2 previous errors; 1 warning emitted - diff --git a/tests/ui-cargo/cargo_rust_version/fail_both_same/Cargo.stderr b/tests/ui-cargo/cargo_rust_version/fail_both_same/Cargo.stderr new file mode 100644 index 00000000000..407a9055de8 --- /dev/null +++ b/tests/ui-cargo/cargo_rust_version/fail_both_same/Cargo.stderr @@ -0,0 +1,19 @@ +error: unnecessary structure name repetition + --> src/main.rs:6:21 + | +6 | pub fn bar() -> Foo { + | ^^^ help: use the applicable keyword: `Self` + | +note: the lint level is defined here + --> src/main.rs:1:9 + | +1 | #![deny(clippy::use_self)] + | ^^^^^^^^^^^^^^^^ + +error: unnecessary structure name repetition + --> src/main.rs:7:9 + | +7 | Foo + | ^^^ help: use the applicable keyword: `Self` + +error: could not compile `fail-both-same` (bin "fail-both-same") due to 2 previous errors diff --git a/tests/ui-cargo/cargo_rust_version/fail_both_same/src/main.stderr b/tests/ui-cargo/cargo_rust_version/fail_both_same/src/main.stderr deleted file mode 100644 index 259d39b1252..00000000000 --- a/tests/ui-cargo/cargo_rust_version/fail_both_same/src/main.stderr +++ /dev/null @@ -1,20 +0,0 @@ -error: unnecessary structure name repetition - --> $DIR/main.rs:6:21 - | -LL | pub fn bar() -> Foo { - | ^^^ help: use the applicable keyword: `Self` - | -note: the lint level is defined here - --> $DIR/main.rs:1:9 - | -LL | #![deny(clippy::use_self)] - | ^^^^^^^^^^^^^^^^ - -error: unnecessary structure name repetition - --> $DIR/main.rs:7:9 - | -LL | Foo - | ^^^ help: use the applicable keyword: `Self` - -error: aborting due to 2 previous errors - diff --git a/tests/ui-cargo/cargo_rust_version/fail_cargo/Cargo.stderr b/tests/ui-cargo/cargo_rust_version/fail_cargo/Cargo.stderr new file mode 100644 index 00000000000..566f5a68689 --- /dev/null +++ b/tests/ui-cargo/cargo_rust_version/fail_cargo/Cargo.stderr @@ -0,0 +1,19 @@ +error: unnecessary structure name repetition + --> src/main.rs:6:21 + | +6 | pub fn bar() -> Foo { + | ^^^ help: use the applicable keyword: `Self` + | +note: the lint level is defined here + --> src/main.rs:1:9 + | +1 | #![deny(clippy::use_self)] + | ^^^^^^^^^^^^^^^^ + +error: unnecessary structure name repetition + --> src/main.rs:7:9 + | +7 | Foo + | ^^^ help: use the applicable keyword: `Self` + +error: could not compile `fail-cargo` (bin "fail-cargo") due to 2 previous errors diff --git a/tests/ui-cargo/cargo_rust_version/fail_cargo/src/main.stderr b/tests/ui-cargo/cargo_rust_version/fail_cargo/src/main.stderr deleted file mode 100644 index 259d39b1252..00000000000 --- a/tests/ui-cargo/cargo_rust_version/fail_cargo/src/main.stderr +++ /dev/null @@ -1,20 +0,0 @@ -error: unnecessary structure name repetition - --> $DIR/main.rs:6:21 - | -LL | pub fn bar() -> Foo { - | ^^^ help: use the applicable keyword: `Self` - | -note: the lint level is defined here - --> $DIR/main.rs:1:9 - | -LL | #![deny(clippy::use_self)] - | ^^^^^^^^^^^^^^^^ - -error: unnecessary structure name repetition - --> $DIR/main.rs:7:9 - | -LL | Foo - | ^^^ help: use the applicable keyword: `Self` - -error: aborting due to 2 previous errors - diff --git a/tests/ui-cargo/cargo_rust_version/fail_clippy/Cargo.stderr b/tests/ui-cargo/cargo_rust_version/fail_clippy/Cargo.stderr new file mode 100644 index 00000000000..83d4be3bae4 --- /dev/null +++ b/tests/ui-cargo/cargo_rust_version/fail_clippy/Cargo.stderr @@ -0,0 +1,19 @@ +error: unnecessary structure name repetition + --> src/main.rs:6:21 + | +6 | pub fn bar() -> Foo { + | ^^^ help: use the applicable keyword: `Self` + | +note: the lint level is defined here + --> src/main.rs:1:9 + | +1 | #![deny(clippy::use_self)] + | ^^^^^^^^^^^^^^^^ + +error: unnecessary structure name repetition + --> src/main.rs:7:9 + | +7 | Foo + | ^^^ help: use the applicable keyword: `Self` + +error: could not compile `fail-clippy` (bin "fail-clippy") due to 2 previous errors diff --git a/tests/ui-cargo/cargo_rust_version/fail_clippy/src/main.stderr b/tests/ui-cargo/cargo_rust_version/fail_file_attr/Cargo.stderr similarity index 56% rename from tests/ui-cargo/cargo_rust_version/fail_clippy/src/main.stderr rename to tests/ui-cargo/cargo_rust_version/fail_file_attr/Cargo.stderr index 259d39b1252..14a6b5047b1 100644 --- a/tests/ui-cargo/cargo_rust_version/fail_clippy/src/main.stderr +++ b/tests/ui-cargo/cargo_rust_version/fail_file_attr/Cargo.stderr @@ -1,20 +1,19 @@ error: unnecessary structure name repetition - --> $DIR/main.rs:6:21 + --> src/main.rs:11:21 | -LL | pub fn bar() -> Foo { +11 | pub fn bar() -> Foo { | ^^^ help: use the applicable keyword: `Self` | note: the lint level is defined here - --> $DIR/main.rs:1:9 + --> src/main.rs:6:9 | -LL | #![deny(clippy::use_self)] +6 | #![deny(clippy::use_self)] | ^^^^^^^^^^^^^^^^ error: unnecessary structure name repetition - --> $DIR/main.rs:7:9 + --> src/main.rs:12:9 | -LL | Foo +12 | Foo | ^^^ help: use the applicable keyword: `Self` -error: aborting due to 2 previous errors - +error: could not compile `fail-file-attr` (bin "fail-file-attr") due to 2 previous errors diff --git a/tests/ui-cargo/cargo_rust_version/fail_file_attr/src/main.stderr b/tests/ui-cargo/cargo_rust_version/fail_file_attr/src/main.stderr deleted file mode 100644 index 97e6c3d5a55..00000000000 --- a/tests/ui-cargo/cargo_rust_version/fail_file_attr/src/main.stderr +++ /dev/null @@ -1,20 +0,0 @@ -error: unnecessary structure name repetition - --> $DIR/main.rs:11:21 - | -LL | pub fn bar() -> Foo { - | ^^^ help: use the applicable keyword: `Self` - | -note: the lint level is defined here - --> $DIR/main.rs:6:9 - | -LL | #![deny(clippy::use_self)] - | ^^^^^^^^^^^^^^^^ - -error: unnecessary structure name repetition - --> $DIR/main.rs:12:9 - | -LL | Foo - | ^^^ help: use the applicable keyword: `Self` - -error: aborting due to 2 previous errors - diff --git a/tests/ui-cargo/cargo_rust_version/warn_both_diff/src/main.stderr b/tests/ui-cargo/cargo_rust_version/warn_both_diff/Cargo.stderr similarity index 77% rename from tests/ui-cargo/cargo_rust_version/warn_both_diff/src/main.stderr rename to tests/ui-cargo/cargo_rust_version/warn_both_diff/Cargo.stderr index eeae5b7b275..e89388b501b 100644 --- a/tests/ui-cargo/cargo_rust_version/warn_both_diff/src/main.stderr +++ b/tests/ui-cargo/cargo_rust_version/warn_both_diff/Cargo.stderr @@ -1,4 +1,2 @@ warning: the MSRV in `clippy.toml` and `Cargo.toml` differ; using `1.13.0` from `clippy.toml` -warning: 1 warning emitted - diff --git a/tests/ui-cargo/duplicate_mod/fail/Cargo.stderr b/tests/ui-cargo/duplicate_mod/fail/Cargo.stderr new file mode 100644 index 00000000000..fde3a1e6599 --- /dev/null +++ b/tests/ui-cargo/duplicate_mod/fail/Cargo.stderr @@ -0,0 +1,52 @@ +error: file is loaded as a module multiple times: `src/b.rs` + --> src/main.rs:5:1 + | +5 | mod b; + | ^^^^^^ first loaded here +6 | / #[path = "b.rs"] +7 | | mod b2; + | |_______^ loaded again here + | + = help: replace all but one `mod` item with `use` items + = note: `-D clippy::duplicate-mod` implied by `-D warnings` + +error: file is loaded as a module multiple times: `src/c.rs` + --> src/main.rs:9:1 + | +9 | mod c; + | ^^^^^^ first loaded here +10 | / #[path = "c.rs"] +11 | | mod c2; + | |_______^ loaded again here +12 | / #[path = "c.rs"] +13 | | mod c3; + | |_______^ loaded again here + | + = help: replace all but one `mod` item with `use` items + +error: file is loaded as a module multiple times: `src/d.rs` + --> src/main.rs:18:1 + | +18 | mod d; + | ^^^^^^ first loaded here +19 | / #[path = "d.rs"] +20 | | mod d2; + | |_______^ loaded again here + | + = help: replace all but one `mod` item with `use` items + +error: file is loaded as a module multiple times: `src/from_other_module.rs` + --> src/main.rs:15:1 + | +15 | mod from_other_module; + | ^^^^^^^^^^^^^^^^^^^^^^ first loaded here + | + ::: src/other_module/mod.rs:1:1 + | +1 | / #[path = "../from_other_module.rs"] +2 | | mod m; + | |______^ loaded again here + | + = help: replace all but one `mod` item with `use` items + +error: could not compile `duplicate_mod` (bin "duplicate_mod") due to 4 previous errors diff --git a/tests/ui-cargo/duplicate_mod/fail/src/main.stderr b/tests/ui-cargo/duplicate_mod/fail/src/main.stderr deleted file mode 100644 index 3b80d89a686..00000000000 --- a/tests/ui-cargo/duplicate_mod/fail/src/main.stderr +++ /dev/null @@ -1,53 +0,0 @@ -error: file is loaded as a module multiple times: `$DIR/b.rs` - --> $DIR/main.rs:5:1 - | -LL | mod b; - | ^^^^^^ first loaded here -LL | / #[path = "b.rs"] -LL | | mod b2; - | |_______^ loaded again here - | - = help: replace all but one `mod` item with `use` items - = note: `-D clippy::duplicate-mod` implied by `-D warnings` - -error: file is loaded as a module multiple times: `$DIR/c.rs` - --> $DIR/main.rs:9:1 - | -LL | mod c; - | ^^^^^^ first loaded here -LL | / #[path = "c.rs"] -LL | | mod c2; - | |_______^ loaded again here -LL | / #[path = "c.rs"] -LL | | mod c3; - | |_______^ loaded again here - | - = help: replace all but one `mod` item with `use` items - -error: file is loaded as a module multiple times: `$DIR/d.rs` - --> $DIR/main.rs:18:1 - | -LL | mod d; - | ^^^^^^ first loaded here -LL | / #[path = "d.rs"] -LL | | mod d2; - | |_______^ loaded again here - | - = help: replace all but one `mod` item with `use` items - -error: file is loaded as a module multiple times: `$DIR/from_other_module.rs` - --> $DIR/main.rs:15:1 - | -LL | mod from_other_module; - | ^^^^^^^^^^^^^^^^^^^^^^ first loaded here - | - ::: $DIR/other_module/mod.rs:1:1 - | -LL | / #[path = "../from_other_module.rs"] -LL | | mod m; - | |______^ loaded again here - | - = help: replace all but one `mod` item with `use` items - -error: aborting due to 4 previous errors - diff --git a/tests/ui-cargo/feature_name/fail/Cargo.stderr b/tests/ui-cargo/feature_name/fail/Cargo.stderr new file mode 100644 index 00000000000..da2db45d3b8 --- /dev/null +++ b/tests/ui-cargo/feature_name/fail/Cargo.stderr @@ -0,0 +1,43 @@ +error: the "no-" prefix in the feature name "no-qaq" is negative + | + = help: consider renaming the feature to "qaq", but make sure the feature adds functionality + = note: `-D clippy::negative-feature-names` implied by `-D warnings` + +error: the "no_" prefix in the feature name "no_qaq" is negative + | + = help: consider renaming the feature to "qaq", but make sure the feature adds functionality + +error: the "not-" prefix in the feature name "not-orz" is negative + | + = help: consider renaming the feature to "orz", but make sure the feature adds functionality + +error: the "not_" prefix in the feature name "not_orz" is negative + | + = help: consider renaming the feature to "orz", but make sure the feature adds functionality + +error: the "-support" suffix in the feature name "qvq-support" is redundant + | + = help: consider renaming the feature to "qvq" + = note: `-D clippy::redundant-feature-names` implied by `-D warnings` + +error: the "_support" suffix in the feature name "qvq_support" is redundant + | + = help: consider renaming the feature to "qvq" + +error: the "use-" prefix in the feature name "use-qwq" is redundant + | + = help: consider renaming the feature to "qwq" + +error: the "use_" prefix in the feature name "use_qwq" is redundant + | + = help: consider renaming the feature to "qwq" + +error: the "with-" prefix in the feature name "with-owo" is redundant + | + = help: consider renaming the feature to "owo" + +error: the "with_" prefix in the feature name "with_owo" is redundant + | + = help: consider renaming the feature to "owo" + +error: could not compile `feature_name` (bin "feature_name") due to 10 previous errors diff --git a/tests/ui-cargo/feature_name/fail/src/main.stderr b/tests/ui-cargo/feature_name/fail/src/main.stderr deleted file mode 100644 index c6a11fa93eb..00000000000 --- a/tests/ui-cargo/feature_name/fail/src/main.stderr +++ /dev/null @@ -1,44 +0,0 @@ -error: the "no-" prefix in the feature name "no-qaq" is negative - | - = help: consider renaming the feature to "qaq", but make sure the feature adds functionality - = note: `-D clippy::negative-feature-names` implied by `-D warnings` - -error: the "no_" prefix in the feature name "no_qaq" is negative - | - = help: consider renaming the feature to "qaq", but make sure the feature adds functionality - -error: the "not-" prefix in the feature name "not-orz" is negative - | - = help: consider renaming the feature to "orz", but make sure the feature adds functionality - -error: the "not_" prefix in the feature name "not_orz" is negative - | - = help: consider renaming the feature to "orz", but make sure the feature adds functionality - -error: the "-support" suffix in the feature name "qvq-support" is redundant - | - = help: consider renaming the feature to "qvq" - = note: `-D clippy::redundant-feature-names` implied by `-D warnings` - -error: the "_support" suffix in the feature name "qvq_support" is redundant - | - = help: consider renaming the feature to "qvq" - -error: the "use-" prefix in the feature name "use-qwq" is redundant - | - = help: consider renaming the feature to "qwq" - -error: the "use_" prefix in the feature name "use_qwq" is redundant - | - = help: consider renaming the feature to "qwq" - -error: the "with-" prefix in the feature name "with-owo" is redundant - | - = help: consider renaming the feature to "owo" - -error: the "with_" prefix in the feature name "with_owo" is redundant - | - = help: consider renaming the feature to "owo" - -error: aborting due to 10 previous errors - diff --git a/tests/ui-cargo/module_style/fail_mod/Cargo.stderr b/tests/ui-cargo/module_style/fail_mod/Cargo.stderr new file mode 100644 index 00000000000..c2907f319e6 --- /dev/null +++ b/tests/ui-cargo/module_style/fail_mod/Cargo.stderr @@ -0,0 +1,18 @@ +error: `mod.rs` files are required, found `src/bad/inner.rs` + --> src/bad/inner.rs:1:1 + | +1 | pub mod stuff; + | ^ + | + = help: move `src/bad/inner.rs` to `src/bad/inner/mod.rs` + = note: `-D clippy::self-named-module-files` implied by `-D warnings` + +error: `mod.rs` files are required, found `src/bad/inner/stuff.rs` + --> src/bad/inner/stuff.rs:1:1 + | +1 | pub mod most; + | ^ + | + = help: move `src/bad/inner/stuff.rs` to `src/bad/inner/stuff/mod.rs` + +error: could not compile `fail-mod` (bin "fail-mod") due to 2 previous errors diff --git a/tests/ui-cargo/module_style/fail_mod/src/main.stderr b/tests/ui-cargo/module_style/fail_mod/src/main.stderr deleted file mode 100644 index 697c8b57c4a..00000000000 --- a/tests/ui-cargo/module_style/fail_mod/src/main.stderr +++ /dev/null @@ -1,19 +0,0 @@ -error: `mod.rs` files are required, found `bad/inner.rs` - --> $DIR/bad/inner.rs:1:1 - | -LL | pub mod stuff; - | ^ - | - = help: move `bad/inner.rs` to `bad/inner/mod.rs` - = note: `-D clippy::self-named-module-files` implied by `-D warnings` - -error: `mod.rs` files are required, found `bad/inner/stuff.rs` - --> $DIR/bad/inner/stuff.rs:1:1 - | -LL | pub mod most; - | ^ - | - = help: move `bad/inner/stuff.rs` to `bad/inner/stuff/mod.rs` - -error: aborting due to 2 previous errors - diff --git a/tests/ui-cargo/module_style/fail_mod_remap/Cargo.stderr b/tests/ui-cargo/module_style/fail_mod_remap/Cargo.stderr new file mode 100644 index 00000000000..fcf1a3c5e66 --- /dev/null +++ b/tests/ui-cargo/module_style/fail_mod_remap/Cargo.stderr @@ -0,0 +1,10 @@ +error: `mod.rs` files are required, found `src/bad.rs` + --> src/bad.rs:1:1 + | +1 | pub mod inner; + | ^ + | + = help: move `src/bad.rs` to `src/bad/mod.rs` + = note: `-D clippy::self-named-module-files` implied by `-D warnings` + +error: could not compile `fail-mod-remap` (bin "fail-mod-remap") due to previous error diff --git a/tests/ui-cargo/module_style/fail_mod_remap/src/main.stderr b/tests/ui-cargo/module_style/fail_mod_remap/src/main.stderr deleted file mode 100644 index ea6ea98064a..00000000000 --- a/tests/ui-cargo/module_style/fail_mod_remap/src/main.stderr +++ /dev/null @@ -1,11 +0,0 @@ -error: `mod.rs` files are required, found `bad.rs` - --> /remapped/module_style/fail_mod_remap/src/bad.rs:1:1 - | -LL | pub mod inner; - | ^ - | - = help: move `bad.rs` to `bad/mod.rs` - = note: `-D clippy::self-named-module-files` implied by `-D warnings` - -error: aborting due to previous error - diff --git a/tests/ui-cargo/module_style/fail_no_mod/Cargo.stderr b/tests/ui-cargo/module_style/fail_no_mod/Cargo.stderr new file mode 100644 index 00000000000..f61642ca2ef --- /dev/null +++ b/tests/ui-cargo/module_style/fail_no_mod/Cargo.stderr @@ -0,0 +1,10 @@ +error: `mod.rs` files are not allowed, found `src/bad/mod.rs` + --> src/bad/mod.rs:1:1 + | +1 | pub struct Thing; + | ^ + | + = help: move `src/bad/mod.rs` to `src/bad.rs` + = note: `-D clippy::mod-module-files` implied by `-D warnings` + +error: could not compile `fail-no-mod` (bin "fail-no-mod") due to previous error diff --git a/tests/ui-cargo/module_style/fail_no_mod/src/main.stderr b/tests/ui-cargo/module_style/fail_no_mod/src/main.stderr deleted file mode 100644 index f40ceea234b..00000000000 --- a/tests/ui-cargo/module_style/fail_no_mod/src/main.stderr +++ /dev/null @@ -1,11 +0,0 @@ -error: `mod.rs` files are not allowed, found `bad/mod.rs` - --> $DIR/bad/mod.rs:1:1 - | -LL | pub struct Thing; - | ^ - | - = help: move `bad/mod.rs` to `bad.rs` - = note: `-D clippy::mod-module-files` implied by `-D warnings` - -error: aborting due to previous error - diff --git a/tests/ui-cargo/multiple_config_files/warn/Cargo.stderr b/tests/ui-cargo/multiple_config_files/warn/Cargo.stderr new file mode 100644 index 00000000000..d82b9e73f78 --- /dev/null +++ b/tests/ui-cargo/multiple_config_files/warn/Cargo.stderr @@ -0,0 +1,2 @@ +warning: using config file `$DIR/$DIR/.clippy.toml`, `$DIR/$DIR/clippy.toml` will be ignored + diff --git a/tests/ui-cargo/multiple_config_files/warn/src/main.stderr b/tests/ui-cargo/multiple_config_files/warn/src/main.stderr deleted file mode 100644 index aa1b3c638a0..00000000000 --- a/tests/ui-cargo/multiple_config_files/warn/src/main.stderr +++ /dev/null @@ -1,4 +0,0 @@ -warning: using config file `$SRC_DIR/.clippy.toml`, `$SRC_DIR/clippy.toml` will be ignored - -warning: 1 warning emitted - diff --git a/tests/ui-cargo/multiple_crate_versions/fail/Cargo.stderr b/tests/ui-cargo/multiple_crate_versions/fail/Cargo.stderr new file mode 100644 index 00000000000..5bcce920455 --- /dev/null +++ b/tests/ui-cargo/multiple_crate_versions/fail/Cargo.stderr @@ -0,0 +1,5 @@ +error: multiple versions for dependency `winapi`: 0.2.8, 0.3.9 + | + = note: `-D clippy::multiple-crate-versions` implied by `-D warnings` + +error: could not compile `multiple_crate_versions` (bin "multiple_crate_versions") due to previous error diff --git a/tests/ui-cargo/multiple_crate_versions/fail/src/main.stderr b/tests/ui-cargo/multiple_crate_versions/fail/src/main.stderr deleted file mode 100644 index f3113e09365..00000000000 --- a/tests/ui-cargo/multiple_crate_versions/fail/src/main.stderr +++ /dev/null @@ -1,6 +0,0 @@ -error: multiple versions for dependency `winapi`: 0.2.8, 0.3.9 - | - = note: `-D clippy::multiple-crate-versions` implied by `-D warnings` - -error: aborting due to previous error - diff --git a/tests/ui-cargo/update-all-references.sh b/tests/ui-cargo/update-all-references.sh index 4391499a1e1..d4204307026 100755 --- a/tests/ui-cargo/update-all-references.sh +++ b/tests/ui-cargo/update-all-references.sh @@ -1,3 +1,3 @@ #!/bin/bash -echo "Please use 'cargo dev bless' instead." +echo "Please use 'cargo bless' instead." diff --git a/tests/ui-cargo/wildcard_dependencies/fail/Cargo.stderr b/tests/ui-cargo/wildcard_dependencies/fail/Cargo.stderr new file mode 100644 index 00000000000..b1578c9f324 --- /dev/null +++ b/tests/ui-cargo/wildcard_dependencies/fail/Cargo.stderr @@ -0,0 +1,5 @@ +error: wildcard dependency for `regex` + | + = note: `-D clippy::wildcard-dependencies` implied by `-D warnings` + +error: could not compile `wildcard_dependencies` (bin "wildcard_dependencies") due to previous error diff --git a/tests/ui-cargo/wildcard_dependencies/fail/src/main.stderr b/tests/ui-cargo/wildcard_dependencies/fail/src/main.stderr deleted file mode 100644 index 9e65d2f9942..00000000000 --- a/tests/ui-cargo/wildcard_dependencies/fail/src/main.stderr +++ /dev/null @@ -1,6 +0,0 @@ -error: wildcard dependency for `regex` - | - = note: `-D clippy::wildcard-dependencies` implied by `-D warnings` - -error: aborting due to previous error - diff --git a/tests/ui-internal/custom_ice_message.stderr b/tests/ui-internal/custom_ice_message.stderr index b9ea5a64de7..19904318575 100644 --- a/tests/ui-internal/custom_ice_message.stderr +++ b/tests/ui-internal/custom_ice_message.stderr @@ -7,7 +7,7 @@ note: we would appreciate a bug report: https://github.com/rust-lang/rust-clippy note: rustc running on -note: compiler flags: -C prefer-dynamic -Z ui-testing +note: compiler flags: -Z ui-testing query stack during panic: thread panicked while processing panic. aborting. diff --git a/tests/ui-toml/bad_toml/conf_bad_toml.rs b/tests/ui-toml/bad_toml/conf_bad_toml.rs index f328e4d9d04..c69fcd30033 100644 --- a/tests/ui-toml/bad_toml/conf_bad_toml.rs +++ b/tests/ui-toml/bad_toml/conf_bad_toml.rs @@ -1 +1,3 @@ +//@error-in-other-file: error reading Clippy's configuration file: expected `.`, `=` + fn main() {} diff --git a/tests/ui-toml/bad_toml/conf_bad_toml.stderr b/tests/ui-toml/bad_toml/conf_bad_toml.stderr index 5b7e8c0db74..f7d53763a43 100644 --- a/tests/ui-toml/bad_toml/conf_bad_toml.stderr +++ b/tests/ui-toml/bad_toml/conf_bad_toml.stderr @@ -1,5 +1,5 @@ error: error reading Clippy's configuration file: expected `.`, `=` - --> $DIR/clippy.toml:1:4 + --> $DIR/$DIR/clippy.toml:1:4 | LL | fn this_is_obviously(not: a, toml: file) { | ^ diff --git a/tests/ui-toml/bad_toml_type/conf_bad_type.rs b/tests/ui-toml/bad_toml_type/conf_bad_type.rs index f328e4d9d04..688c92d8717 100644 --- a/tests/ui-toml/bad_toml_type/conf_bad_type.rs +++ b/tests/ui-toml/bad_toml_type/conf_bad_type.rs @@ -1 +1,3 @@ +//@error-in-other-file: invalid type: integer `42`, expected a sequence + fn main() {} diff --git a/tests/ui-toml/bad_toml_type/conf_bad_type.stderr b/tests/ui-toml/bad_toml_type/conf_bad_type.stderr index 386e1135df9..fb0a1408152 100644 --- a/tests/ui-toml/bad_toml_type/conf_bad_type.stderr +++ b/tests/ui-toml/bad_toml_type/conf_bad_type.stderr @@ -1,5 +1,5 @@ error: error reading Clippy's configuration file: invalid type: integer `42`, expected a sequence - --> $DIR/clippy.toml:1:20 + --> $DIR/$DIR/clippy.toml:1:20 | LL | disallowed-names = 42 | ^^ diff --git a/tests/ui-toml/conf_deprecated_key/conf_deprecated_key.stderr b/tests/ui-toml/conf_deprecated_key/conf_deprecated_key.stderr index 123ad94dd09..89d84eb2455 100644 --- a/tests/ui-toml/conf_deprecated_key/conf_deprecated_key.stderr +++ b/tests/ui-toml/conf_deprecated_key/conf_deprecated_key.stderr @@ -1,11 +1,11 @@ warning: error reading Clippy's configuration file: deprecated field `cyclomatic-complexity-threshold`. Please use `cognitive-complexity-threshold` instead - --> $DIR/clippy.toml:2:1 + --> $DIR/$DIR/clippy.toml:2:1 | LL | cyclomatic-complexity-threshold = 2 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ warning: error reading Clippy's configuration file: deprecated field `blacklisted-names`. Please use `disallowed-names` instead - --> $DIR/clippy.toml:3:1 + --> $DIR/$DIR/clippy.toml:3:1 | LL | blacklisted-names = [ "..", "wibble" ] | ^^^^^^^^^^^^^^^^^ diff --git a/tests/ui-toml/duplicated_keys/duplicated_keys.rs b/tests/ui-toml/duplicated_keys/duplicated_keys.rs index f328e4d9d04..187775545ed 100644 --- a/tests/ui-toml/duplicated_keys/duplicated_keys.rs +++ b/tests/ui-toml/duplicated_keys/duplicated_keys.rs @@ -1 +1,3 @@ +//@error-in-other-file: duplicate key `cognitive-complexity-threshold` + fn main() {} diff --git a/tests/ui-toml/duplicated_keys/duplicated_keys.stderr b/tests/ui-toml/duplicated_keys/duplicated_keys.stderr index 54997735274..7c56dfdb948 100644 --- a/tests/ui-toml/duplicated_keys/duplicated_keys.stderr +++ b/tests/ui-toml/duplicated_keys/duplicated_keys.stderr @@ -1,5 +1,5 @@ error: error reading Clippy's configuration file: duplicate key `cognitive-complexity-threshold` in document root - --> $DIR/clippy.toml:2:1 + --> $DIR/$DIR/clippy.toml:2:1 | LL | cognitive-complexity-threshold = 4 | ^ diff --git a/tests/ui-toml/duplicated_keys_deprecated/duplicated_keys.stderr b/tests/ui-toml/duplicated_keys_deprecated/duplicated_keys.stderr index 2ae7848f183..0af8c0add6c 100644 --- a/tests/ui-toml/duplicated_keys_deprecated/duplicated_keys.stderr +++ b/tests/ui-toml/duplicated_keys_deprecated/duplicated_keys.stderr @@ -1,11 +1,11 @@ error: error reading Clippy's configuration file: duplicate field `cognitive_complexity_threshold` (provided as `cyclomatic_complexity_threshold`) - --> $DIR/clippy.toml:3:1 + --> $DIR/$DIR/clippy.toml:3:1 | LL | cyclomatic-complexity-threshold = 3 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ warning: error reading Clippy's configuration file: deprecated field `cyclomatic-complexity-threshold`. Please use `cognitive-complexity-threshold` instead - --> $DIR/clippy.toml:3:1 + --> $DIR/$DIR/clippy.toml:3:1 | LL | cyclomatic-complexity-threshold = 3 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui-toml/duplicated_keys_deprecated_2/duplicated_keys.stderr b/tests/ui-toml/duplicated_keys_deprecated_2/duplicated_keys.stderr index 53ad4271246..a4b1e9c335c 100644 --- a/tests/ui-toml/duplicated_keys_deprecated_2/duplicated_keys.stderr +++ b/tests/ui-toml/duplicated_keys_deprecated_2/duplicated_keys.stderr @@ -1,11 +1,11 @@ error: error reading Clippy's configuration file: duplicate field `cognitive-complexity-threshold` - --> $DIR/clippy.toml:4:1 + --> $DIR/$DIR/clippy.toml:4:1 | LL | cognitive-complexity-threshold = 4 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ warning: error reading Clippy's configuration file: deprecated field `cyclomatic-complexity-threshold`. Please use `cognitive-complexity-threshold` instead - --> $DIR/clippy.toml:2:1 + --> $DIR/$DIR/clippy.toml:2:1 | LL | cyclomatic-complexity-threshold = 3 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui-toml/excessive_nesting/auxiliary/proc_macros.rs b/tests/ui-toml/excessive_nesting/auxiliary/proc_macros.rs index df17974de03..ebadd4e440a 100644 --- a/tests/ui-toml/excessive_nesting/auxiliary/proc_macros.rs +++ b/tests/ui-toml/excessive_nesting/auxiliary/proc_macros.rs @@ -1,9 +1,5 @@ -//@compile-flags: --emit=link -//@no-prefer-dynamic - // NOTE: Copied from `ui/auxiliary/proc_macros.rs`, couldn't get `../` to work for some reason -#![crate_type = "proc-macro"] #![feature(let_chains)] #![feature(proc_macro_span)] #![allow(clippy::excessive_nesting, dead_code)] diff --git a/tests/ui-toml/excessive_nesting/excessive_nesting.rs b/tests/ui-toml/excessive_nesting/excessive_nesting.rs index 25f0d0d6230..c28220b973e 100644 --- a/tests/ui-toml/excessive_nesting/excessive_nesting.rs +++ b/tests/ui-toml/excessive_nesting/excessive_nesting.rs @@ -1,4 +1,4 @@ -//@aux-build:proc_macros.rs +//@aux-build:proc_macros.rs:proc-macro #![rustfmt::skip] #![feature(custom_inner_attributes)] #![allow(unused)] diff --git a/tests/ui-toml/invalid_min_rust_version/invalid_min_rust_version.rs b/tests/ui-toml/invalid_min_rust_version/invalid_min_rust_version.rs index 2ebf28645e5..03fa719975b 100644 --- a/tests/ui-toml/invalid_min_rust_version/invalid_min_rust_version.rs +++ b/tests/ui-toml/invalid_min_rust_version/invalid_min_rust_version.rs @@ -1,3 +1,5 @@ +//@error-in-other-file: `invalid.version` is not a valid Rust version + #![allow(clippy::redundant_clone)] fn main() {} diff --git a/tests/ui-toml/lint_decimal_readability/test.rs b/tests/ui-toml/lint_decimal_readability/test.rs index 2498672d77f..bd5110138c8 100644 --- a/tests/ui-toml/lint_decimal_readability/test.rs +++ b/tests/ui-toml/lint_decimal_readability/test.rs @@ -1,5 +1,5 @@ #![allow(clippy::excessive_precision)] -#[deny(clippy::unreadable_literal)] +#![warn(clippy::unreadable_literal)] fn allow_inconsistent_digit_grouping() { #![allow(clippy::inconsistent_digit_grouping)] diff --git a/tests/ui-toml/lint_decimal_readability/test.stderr b/tests/ui-toml/lint_decimal_readability/test.stderr index be505bda479..ac9d89d0cbe 100644 --- a/tests/ui-toml/lint_decimal_readability/test.stderr +++ b/tests/ui-toml/lint_decimal_readability/test.stderr @@ -6,5 +6,13 @@ LL | let _fail1 = 100_200_300.123456789; | = note: `-D clippy::inconsistent-digit-grouping` implied by `-D warnings` -error: aborting due to previous error +error: long literal lacking separators + --> $DIR/test.rs:22:18 + | +LL | let _fail2 = 100200300.300200100; + | ^^^^^^^^^^^^^^^^^^^ help: consider: `100_200_300.300_200_100` + | + = note: `-D clippy::unreadable-literal` implied by `-D warnings` + +error: aborting due to 2 previous errors diff --git a/tests/ui-toml/max_suggested_slice_pattern_length/index_refutable_slice.rs b/tests/ui-toml/max_suggested_slice_pattern_length/index_refutable_slice.rs index 21849a14fa9..da76bb20fd9 100644 --- a/tests/ui-toml/max_suggested_slice_pattern_length/index_refutable_slice.rs +++ b/tests/ui-toml/max_suggested_slice_pattern_length/index_refutable_slice.rs @@ -3,6 +3,7 @@ fn below_limit() { let slice: Option<&[u32]> = Some(&[1, 2, 3]); if let Some(slice) = slice { + //~^ ERROR: binding can be a slice pattern // This would usually not be linted but is included now due to the // index limit in the config file println!("{}", slice[7]); diff --git a/tests/ui-toml/min_rust_version/min_rust_version.rs b/tests/ui-toml/min_rust_version/min_rust_version.rs index 1e3ec123a3c..e1dc3f4389c 100644 --- a/tests/ui-toml/min_rust_version/min_rust_version.rs +++ b/tests/ui-toml/min_rust_version/min_rust_version.rs @@ -41,7 +41,7 @@ fn match_like_matches() { fn match_same_arms() { match (1, 2, 3) { (1, .., 3) => 42, - (.., 3) => 42, //~ ERROR match arms have same body + (.., 3) => 42, _ => 0, }; } @@ -49,7 +49,7 @@ fn match_same_arms() { fn match_same_arms2() { let _ = match Some(42) { Some(_) => 24, - None => 24, //~ ERROR match arms have same body + None => 24, }; } 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 f5761c6afeb..e7ac05dd3c6 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,8 +1,3 @@ -//@compile-flags: --emit=link -//@no-prefer-dynamic - -#![crate_type = "proc-macro"] - extern crate proc_macro; use proc_macro::TokenStream; 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 e4747bedddb..054db5d9330 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,4 +1,4 @@ -//@aux-build:proc_macro_derive.rs +//@aux-build:proc_macro_derive.rs:proc-macro //@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 54edded99f4..95d1a2297e5 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,4 +1,4 @@ -//@aux-build:proc_macro_derive.rs +//@aux-build:proc_macro_derive.rs:proc-macro //@run-rustfix #![warn(clippy::nonstandard_macro_braces)] diff --git a/tests/ui-toml/suppress_lint_in_const/test.rs b/tests/ui-toml/suppress_lint_in_const/test.rs index 068b47bd09d..17c1b03d88c 100644 --- a/tests/ui-toml/suppress_lint_in_const/test.rs +++ b/tests/ui-toml/suppress_lint_in_const/test.rs @@ -13,6 +13,7 @@ const ARR: [i32; 2] = [1, 2]; const REF: &i32 = &ARR[idx()]; // Ok, should not produce stderr, since `suppress-restriction-lint-in-const` is set true. const REF_ERR: &i32 = &ARR[idx4()]; // Ok, let rustc handle const contexts. +//~^ ERROR: failed const fn idx() -> usize { 1 @@ -34,6 +35,8 @@ fn main() { x[const { idx4() }]; // Ok, let rustc's `unconditional_panic` lint handle `usize` indexing on arrays. const { &ARR[idx()] }; // Ok, should not produce stderr, since `suppress-restriction-lint-in-const` is set true. const { &ARR[idx4()] }; // Ok, should not produce stderr, since `suppress-restriction-lint-in-const` is set true. + // + //~^^ ERROR: failed let y = &x; y[0]; // Ok, referencing shouldn't affect this lint. See the issue 6021 diff --git a/tests/ui-toml/suppress_lint_in_const/test.stderr b/tests/ui-toml/suppress_lint_in_const/test.stderr index db88b1cbecb..14e13194427 100644 --- a/tests/ui-toml/suppress_lint_in_const/test.stderr +++ b/tests/ui-toml/suppress_lint_in_const/test.stderr @@ -1,17 +1,17 @@ error[E0080]: evaluation of `main::{constant#3}` failed - --> $DIR/test.rs:36:14 + --> $DIR/test.rs:37:14 | LL | const { &ARR[idx4()] }; // Ok, should not produce stderr, since `suppress-restriction-lint-in-const` is set true. | ^^^^^^^^^^^ index out of bounds: the length is 2 but the index is 4 note: erroneous constant used - --> $DIR/test.rs:36:5 + --> $DIR/test.rs:37:5 | LL | const { &ARR[idx4()] }; // Ok, should not produce stderr, since `suppress-restriction-lint-in-const` is set true. | ^^^^^^^^^^^^^^^^^^^^^^ error: indexing may panic - --> $DIR/test.rs:27:5 + --> $DIR/test.rs:28:5 | LL | x[index]; | ^^^^^^^^ @@ -20,7 +20,7 @@ LL | x[index]; = note: `-D clippy::indexing-slicing` implied by `-D warnings` error: indexing may panic - --> $DIR/test.rs:43:5 + --> $DIR/test.rs:46:5 | LL | v[0]; | ^^^^ @@ -28,7 +28,7 @@ LL | v[0]; = help: consider using `.get(n)` or `.get_mut(n)` instead error: indexing may panic - --> $DIR/test.rs:44:5 + --> $DIR/test.rs:47:5 | LL | v[10]; | ^^^^^ @@ -36,7 +36,7 @@ LL | v[10]; = help: consider using `.get(n)` or `.get_mut(n)` instead error: indexing may panic - --> $DIR/test.rs:45:5 + --> $DIR/test.rs:48:5 | LL | v[1 << 3]; | ^^^^^^^^^ @@ -44,7 +44,7 @@ LL | v[1 << 3]; = help: consider using `.get(n)` or `.get_mut(n)` instead error: indexing may panic - --> $DIR/test.rs:51:5 + --> $DIR/test.rs:54:5 | LL | v[N]; | ^^^^ @@ -52,7 +52,7 @@ LL | v[N]; = help: consider using `.get(n)` or `.get_mut(n)` instead error: indexing may panic - --> $DIR/test.rs:52:5 + --> $DIR/test.rs:55:5 | LL | v[M]; | ^^^^ diff --git a/tests/ui-toml/toml_trivially_copy/test.rs b/tests/ui-toml/toml_trivially_copy/test.rs index 179b1266169..f267a67f40e 100644 --- a/tests/ui-toml/toml_trivially_copy/test.rs +++ b/tests/ui-toml/toml_trivially_copy/test.rs @@ -1,7 +1,7 @@ //@normalize-stderr-test: "\(\d+ byte\)" -> "(N byte)" //@normalize-stderr-test: "\(limit: \d+ byte\)" -> "(limit: N byte)" -#![deny(clippy::trivially_copy_pass_by_ref)] +#![warn(clippy::trivially_copy_pass_by_ref)] #[derive(Copy, Clone)] struct Foo(u8); diff --git a/tests/ui-toml/toml_trivially_copy/test.stderr b/tests/ui-toml/toml_trivially_copy/test.stderr index b3ef5928e8e..d2b55eff16d 100644 --- a/tests/ui-toml/toml_trivially_copy/test.stderr +++ b/tests/ui-toml/toml_trivially_copy/test.stderr @@ -4,11 +4,7 @@ error: this argument (N byte) is passed by reference, but would be more efficien LL | fn bad(x: &u16, y: &Foo) {} | ^^^^ help: consider passing by value instead: `u16` | -note: the lint level is defined here - --> $DIR/test.rs:4:9 - | -LL | #![deny(clippy::trivially_copy_pass_by_ref)] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + = note: `-D clippy::trivially-copy-pass-by-ref` implied by `-D warnings` error: this argument (N byte) is passed by reference, but would be more efficient if passed by value (limit: N byte) --> $DIR/test.rs:14:20 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 569fd2c3553..38009627757 100644 --- a/tests/ui-toml/toml_unknown_key/conf_unknown_key.rs +++ b/tests/ui-toml/toml_unknown_key/conf_unknown_key.rs @@ -1,3 +1,3 @@ -//@error-pattern: unknown field `foobar`, expected one of +//@error-in-other-file: 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 475b15a2414..69678057917 100644 --- a/tests/ui-toml/toml_unknown_key/conf_unknown_key.stderr +++ b/tests/ui-toml/toml_unknown_key/conf_unknown_key.stderr @@ -61,7 +61,7 @@ error: error reading Clippy's configuration file: unknown field `foobar`, expect vec-box-size-threshold verbose-bit-mask-threshold warn-on-all-wildcard-imports - --> $DIR/clippy.toml:2:1 + --> $DIR/$DIR/clippy.toml:2:1 | LL | foobar = 42 | ^^^^^^ @@ -129,7 +129,7 @@ error: error reading Clippy's configuration file: unknown field `barfoo`, expect vec-box-size-threshold verbose-bit-mask-threshold warn-on-all-wildcard-imports - --> $DIR/clippy.toml:4:1 + --> $DIR/$DIR/clippy.toml:4:1 | LL | barfoo = 53 | ^^^^^^ diff --git a/tests/ui-toml/undocumented_unsafe_blocks/auxiliary/proc_macro_unsafe.rs b/tests/ui-toml/undocumented_unsafe_blocks/auxiliary/proc_macro_unsafe.rs index c2326678d0d..1c591fc76f3 100644 --- a/tests/ui-toml/undocumented_unsafe_blocks/auxiliary/proc_macro_unsafe.rs +++ b/tests/ui-toml/undocumented_unsafe_blocks/auxiliary/proc_macro_unsafe.rs @@ -1,8 +1,3 @@ -//@compile-flags: --emit=link -//@no-prefer-dynamic - -#![crate_type = "proc-macro"] - extern crate proc_macro; use proc_macro::{Delimiter, Group, Ident, TokenStream, TokenTree}; diff --git a/tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs b/tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs index c0976f0d600..33d63670958 100644 --- a/tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs +++ b/tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs @@ -1,4 +1,4 @@ -//@aux-build:proc_macro_unsafe.rs +//@aux-build:proc_macro_unsafe.rs:proc-macro #![warn(clippy::undocumented_unsafe_blocks, clippy::unnecessary_safety_comment)] #![allow(deref_nullptr, clippy::let_unit_value, clippy::missing_safety_doc)] diff --git a/tests/ui-toml/unwrap_used/unwrap_used.rs b/tests/ui-toml/unwrap_used/unwrap_used.rs index 9f4d0ef1bf9..dde1c6d7c37 100644 --- a/tests/ui-toml/unwrap_used/unwrap_used.rs +++ b/tests/ui-toml/unwrap_used/unwrap_used.rs @@ -7,7 +7,7 @@ clippy::useless_vec )] #![warn(clippy::unwrap_used)] -#![deny(clippy::get_unwrap)] +#![warn(clippy::get_unwrap)] use std::collections::BTreeMap; use std::collections::HashMap; diff --git a/tests/ui-toml/unwrap_used/unwrap_used.stderr b/tests/ui-toml/unwrap_used/unwrap_used.stderr index 706f9a89cbb..eb66a5cf50b 100644 --- a/tests/ui-toml/unwrap_used/unwrap_used.stderr +++ b/tests/ui-toml/unwrap_used/unwrap_used.stderr @@ -4,11 +4,7 @@ error: called `.get().unwrap()` on a slice. Using `[]` is more clear and more co LL | let _ = boxed_slice.get(1).unwrap(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `&boxed_slice[1]` | -note: the lint level is defined here - --> $DIR/unwrap_used.rs:10:9 - | -LL | #![deny(clippy::get_unwrap)] - | ^^^^^^^^^^^^^^^^^^ + = note: `-D clippy::get-unwrap` implied by `-D warnings` error: used `unwrap()` on an `Option` value --> $DIR/unwrap_used.rs:40:17 diff --git a/tests/ui-toml/update-all-references.sh b/tests/ui-toml/update-all-references.sh index 4391499a1e1..d4204307026 100755 --- a/tests/ui-toml/update-all-references.sh +++ b/tests/ui-toml/update-all-references.sh @@ -1,3 +1,3 @@ #!/bin/bash -echo "Please use 'cargo dev bless' instead." +echo "Please use 'cargo bless' instead." diff --git a/tests/ui/allow_attributes.fixed b/tests/ui/allow_attributes.fixed index fa04f53ca91..cc95a06817d 100644 --- a/tests/ui/allow_attributes.fixed +++ b/tests/ui/allow_attributes.fixed @@ -1,5 +1,5 @@ //@run-rustfix -//@aux-build:proc_macros.rs +//@aux-build:proc_macros.rs:proc-macro #![allow(unused)] #![warn(clippy::allow_attributes)] #![feature(lint_reasons)] diff --git a/tests/ui/allow_attributes.rs b/tests/ui/allow_attributes.rs index 10d2ed1a8a9..2eb6ad304ea 100644 --- a/tests/ui/allow_attributes.rs +++ b/tests/ui/allow_attributes.rs @@ -1,5 +1,5 @@ //@run-rustfix -//@aux-build:proc_macros.rs +//@aux-build:proc_macros.rs:proc-macro #![allow(unused)] #![warn(clippy::allow_attributes)] #![feature(lint_reasons)] diff --git a/tests/ui/allow_attributes_without_reason.rs b/tests/ui/allow_attributes_without_reason.rs index 663c2eb2c37..d223d564221 100644 --- a/tests/ui/allow_attributes_without_reason.rs +++ b/tests/ui/allow_attributes_without_reason.rs @@ -1,4 +1,4 @@ -//@aux-build:proc_macros.rs +//@aux-build:proc_macros.rs:proc-macro #![feature(lint_reasons)] #![deny(clippy::allow_attributes_without_reason)] #![allow(unfulfilled_lint_expectations)] diff --git a/tests/ui/almost_complete_range.fixed b/tests/ui/almost_complete_range.fixed index 5cd0dcce6f7..50a13f16b44 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 +//@aux-build:proc_macros.rs:proc-macro #![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 db0bfc8afc3..fd8223a2309 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 +//@aux-build:proc_macros.rs:proc-macro #![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 7dd14e3824d..4f38e50c81d 100644 --- a/tests/ui/arithmetic_side_effects.rs +++ b/tests/ui/arithmetic_side_effects.rs @@ -1,4 +1,4 @@ -//@aux-build:proc_macro_derive.rs +//@aux-build:proc_macro_derive.rs:proc-macro #![allow( clippy::assign_op_pattern, diff --git a/tests/ui/as_conversions.rs b/tests/ui/as_conversions.rs index 48ca2f6d143..427842a51d9 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:proc-macro #![warn(clippy::as_conversions)] #![allow(clippy::borrow_as_ptr, unused)] diff --git a/tests/ui/asm_syntax.rs b/tests/ui/asm_syntax.rs index c93995f939a..af02e202b17 100644 --- a/tests/ui/asm_syntax.rs +++ b/tests/ui/asm_syntax.rs @@ -1,5 +1,5 @@ -//@only-x86_64 -//@ignore-aarch64 +//@only-target-x86_64 +//@ignore-target-aarch64 #[warn(clippy::inline_asm_x86_intel_syntax)] mod warn_intel { diff --git a/tests/ui/auxiliary/macro_use_helper.rs b/tests/ui/auxiliary/macro_use_helper.rs index 7ed8a28dbd9..cab216b51ac 100644 --- a/tests/ui/auxiliary/macro_use_helper.rs +++ b/tests/ui/auxiliary/macro_use_helper.rs @@ -1,3 +1,5 @@ +//@aux-build:macro_rules.rs + extern crate macro_rules; // STMT diff --git a/tests/ui/auxiliary/proc_macro_attr.rs b/tests/ui/auxiliary/proc_macro_attr.rs index d164dd0e545..fdfe5fc4181 100644 --- a/tests/ui/auxiliary/proc_macro_attr.rs +++ b/tests/ui/auxiliary/proc_macro_attr.rs @@ -1,7 +1,3 @@ -//@compile-flags: --emit=link -//@no-prefer-dynamic - -#![crate_type = "proc-macro"] #![feature(repr128, proc_macro_hygiene, proc_macro_quote, box_patterns)] #![allow(incomplete_features)] #![allow(clippy::useless_conversion, clippy::uninlined_format_args)] diff --git a/tests/ui/auxiliary/proc_macro_derive.rs b/tests/ui/auxiliary/proc_macro_derive.rs index 5ea86a9ff37..37f0ec2b37d 100644 --- a/tests/ui/auxiliary/proc_macro_derive.rs +++ b/tests/ui/auxiliary/proc_macro_derive.rs @@ -1,7 +1,3 @@ -//@compile-flags: --emit=link -//@no-prefer-dynamic - -#![crate_type = "proc-macro"] #![feature(repr128, proc_macro_quote)] #![allow(incomplete_features)] #![allow(clippy::field_reassign_with_default)] diff --git a/tests/ui/auxiliary/proc_macro_suspicious_else_formatting.rs b/tests/ui/auxiliary/proc_macro_suspicious_else_formatting.rs index f13b76e44b0..79e8eff3aa1 100644 --- a/tests/ui/auxiliary/proc_macro_suspicious_else_formatting.rs +++ b/tests/ui/auxiliary/proc_macro_suspicious_else_formatting.rs @@ -1,8 +1,3 @@ -//@compile-flags: --emit=link -//@no-prefer-dynamic - -#![crate_type = "proc-macro"] - extern crate proc_macro; use proc_macro::{token_stream, Delimiter, Group, Ident, Span, TokenStream, TokenTree}; diff --git a/tests/ui/auxiliary/proc_macro_unsafe.rs b/tests/ui/auxiliary/proc_macro_unsafe.rs index c2326678d0d..1c591fc76f3 100644 --- a/tests/ui/auxiliary/proc_macro_unsafe.rs +++ b/tests/ui/auxiliary/proc_macro_unsafe.rs @@ -1,8 +1,3 @@ -//@compile-flags: --emit=link -//@no-prefer-dynamic - -#![crate_type = "proc-macro"] - extern crate proc_macro; use proc_macro::{Delimiter, Group, Ident, TokenStream, TokenTree}; diff --git a/tests/ui/auxiliary/proc_macros.rs b/tests/ui/auxiliary/proc_macros.rs index 5d849bfcf81..4d008c8cb59 100644 --- a/tests/ui/auxiliary/proc_macros.rs +++ b/tests/ui/auxiliary/proc_macros.rs @@ -1,7 +1,3 @@ -//@compile-flags: --emit=link -//@no-prefer-dynamic - -#![crate_type = "proc-macro"] #![feature(let_chains)] #![feature(proc_macro_span)] #![allow(clippy::needless_if, dead_code)] diff --git a/tests/ui/borrow_deref_ref.fixed b/tests/ui/borrow_deref_ref.fixed index 75526461792..b951ba04c37 100644 --- a/tests/ui/borrow_deref_ref.fixed +++ b/tests/ui/borrow_deref_ref.fixed @@ -1,5 +1,5 @@ //@run-rustfix -//@aux-build: proc_macros.rs +//@aux-build: proc_macros.rs:proc-macro #![allow(dead_code, unused_variables)] diff --git a/tests/ui/borrow_deref_ref.rs b/tests/ui/borrow_deref_ref.rs index e319d365f7e..52980e55fbe 100644 --- a/tests/ui/borrow_deref_ref.rs +++ b/tests/ui/borrow_deref_ref.rs @@ -1,5 +1,5 @@ //@run-rustfix -//@aux-build: proc_macros.rs +//@aux-build: proc_macros.rs:proc-macro #![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 29b08ab3643..da940a4cfb5 100644 --- a/tests/ui/borrow_interior_mutable_const/enums.rs +++ b/tests/ui/borrow_interior_mutable_const/enums.rs @@ -1,6 +1,6 @@ //@aux-build:helper.rs -#![warn(clippy::borrow_interior_mutable_const)] +#![deny(clippy::borrow_interior_mutable_const)] #![allow(clippy::declare_interior_mutable_const)] // this file (mostly) replicates its `declare` counterpart. Please see it for more discussions. @@ -19,7 +19,7 @@ const UNFROZEN_VARIANT: OptionalCell = OptionalCell::Unfrozen(Cell::new(true)); const FROZEN_VARIANT: OptionalCell = OptionalCell::Frozen; fn borrow_optional_cell() { - let _ = &UNFROZEN_VARIANT; //~ ERROR interior mutability + let _ = &UNFROZEN_VARIANT; //~ ERROR: interior mutability let _ = &FROZEN_VARIANT; } @@ -34,11 +34,11 @@ trait AssocConsts { // This is the "suboptimal behavior" mentioned in `is_value_unfrozen` // caused by a similar reason to unfrozen types without any default values // get linted even if it has frozen variants'. - let _ = &Self::TO_BE_FROZEN_VARIANT; //~ ERROR interior mutable + let _ = &Self::TO_BE_FROZEN_VARIANT; //~ ERROR: interior mutability // The lint ignores default values because an impl of this trait can set // an unfrozen variant to `DEFAULTED_ON_FROZEN_VARIANT` and use the default impl for `function`. - let _ = &Self::DEFAULTED_ON_FROZEN_VARIANT; //~ ERROR interior mutable + let _ = &Self::DEFAULTED_ON_FROZEN_VARIANT; //~ ERROR: interior mutability } } @@ -47,9 +47,9 @@ impl AssocConsts for u64 { const TO_BE_FROZEN_VARIANT: OptionalCell = OptionalCell::Frozen; fn function() { - let _ = &::TO_BE_UNFROZEN_VARIANT; //~ ERROR interior mutable + let _ = &::TO_BE_UNFROZEN_VARIANT; //~ ERROR: interior mutability let _ = &::TO_BE_FROZEN_VARIANT; - let _ = &Self::DEFAULTED_ON_UNFROZEN_VARIANT; //~ ERROR interior mutable + let _ = &Self::DEFAULTED_ON_UNFROZEN_VARIANT; //~ ERROR: interior mutability let _ = &Self::DEFAULTED_ON_FROZEN_VARIANT; } } @@ -67,11 +67,11 @@ trait AssocTypes { impl AssocTypes for u64 { type ToBeUnfrozen = AtomicUsize; - const TO_BE_UNFROZEN_VARIANT: Option = Some(Self::ToBeUnfrozen::new(4)); //~ ERROR interior mutable + const TO_BE_UNFROZEN_VARIANT: Option = Some(Self::ToBeUnfrozen::new(4)); const TO_BE_FROZEN_VARIANT: Option = None; fn function() { - let _ = &::TO_BE_UNFROZEN_VARIANT; //~ ERROR interior mutable + let _ = &::TO_BE_UNFROZEN_VARIANT; //~ ERROR: interior mutability let _ = &::TO_BE_FROZEN_VARIANT; } } @@ -83,19 +83,19 @@ enum BothOfCellAndGeneric { } impl BothOfCellAndGeneric { - const UNFROZEN_VARIANT: BothOfCellAndGeneric = BothOfCellAndGeneric::Unfrozen(Cell::new(std::ptr::null())); //~ ERROR interior mutable - const GENERIC_VARIANT: BothOfCellAndGeneric = BothOfCellAndGeneric::Generic(std::ptr::null()); //~ ERROR interior mutable + const UNFROZEN_VARIANT: BothOfCellAndGeneric = BothOfCellAndGeneric::Unfrozen(Cell::new(std::ptr::null())); + const GENERIC_VARIANT: BothOfCellAndGeneric = BothOfCellAndGeneric::Generic(std::ptr::null()); const FROZEN_VARIANT: BothOfCellAndGeneric = BothOfCellAndGeneric::Frozen(5); fn function() { - let _ = &Self::UNFROZEN_VARIANT; //~ ERROR interior mutability - let _ = &Self::GENERIC_VARIANT; //~ ERROR interior mutability + let _ = &Self::UNFROZEN_VARIANT; //~ ERROR: interior mutability + let _ = &Self::GENERIC_VARIANT; //~ ERROR: interior mutability let _ = &Self::FROZEN_VARIANT; } } fn main() { // constants defined in foreign crates - let _ = &helper::WRAPPED_PRIVATE_UNFROZEN_VARIANT; //~ ERROR interior mutability + let _ = &helper::WRAPPED_PRIVATE_UNFROZEN_VARIANT; //~ ERROR: interior mutability let _ = &helper::WRAPPED_PRIVATE_FROZEN_VARIANT; } diff --git a/tests/ui/borrow_interior_mutable_const/enums.stderr b/tests/ui/borrow_interior_mutable_const/enums.stderr index b0cab977a03..b753ec92608 100644 --- a/tests/ui/borrow_interior_mutable_const/enums.stderr +++ b/tests/ui/borrow_interior_mutable_const/enums.stderr @@ -1,16 +1,20 @@ error: a `const` item with interior mutability should not be borrowed --> $DIR/enums.rs:22:14 | -LL | let _ = &UNFROZEN_VARIANT; //~ ERROR interior mutability +LL | let _ = &UNFROZEN_VARIANT; | ^^^^^^^^^^^^^^^^ | = help: assign this const to a local or static variable, and use the variable here - = note: `-D clippy::borrow-interior-mutable-const` implied by `-D warnings` +note: the lint level is defined here + --> $DIR/enums.rs:3:9 + | +LL | #![deny(clippy::borrow_interior_mutable_const)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: a `const` item with interior mutability should not be borrowed --> $DIR/enums.rs:37:18 | -LL | let _ = &Self::TO_BE_FROZEN_VARIANT; //~ ERROR interior mutable +LL | let _ = &Self::TO_BE_FROZEN_VARIANT; | ^^^^^^^^^^^^^^^^^^^^^^^^^^ | = help: assign this const to a local or static variable, and use the variable here @@ -18,7 +22,7 @@ LL | let _ = &Self::TO_BE_FROZEN_VARIANT; //~ ERROR interior mutable error: a `const` item with interior mutability should not be borrowed --> $DIR/enums.rs:41:18 | -LL | let _ = &Self::DEFAULTED_ON_FROZEN_VARIANT; //~ ERROR interior mutable +LL | let _ = &Self::DEFAULTED_ON_FROZEN_VARIANT; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = help: assign this const to a local or static variable, and use the variable here @@ -26,7 +30,7 @@ LL | let _ = &Self::DEFAULTED_ON_FROZEN_VARIANT; //~ ERROR interior muta error: a `const` item with interior mutability should not be borrowed --> $DIR/enums.rs:50:18 | -LL | let _ = &::TO_BE_UNFROZEN_VARIANT; //~ ERROR interior mutable +LL | let _ = &::TO_BE_UNFROZEN_VARIANT; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = help: assign this const to a local or static variable, and use the variable here @@ -34,7 +38,7 @@ LL | let _ = &::TO_BE_UNFROZEN_VARIANT; //~ ERROR i error: a `const` item with interior mutability should not be borrowed --> $DIR/enums.rs:52:18 | -LL | let _ = &Self::DEFAULTED_ON_UNFROZEN_VARIANT; //~ ERROR interior mutable +LL | let _ = &Self::DEFAULTED_ON_UNFROZEN_VARIANT; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = help: assign this const to a local or static variable, and use the variable here @@ -42,7 +46,7 @@ LL | let _ = &Self::DEFAULTED_ON_UNFROZEN_VARIANT; //~ ERROR interior mu error: a `const` item with interior mutability should not be borrowed --> $DIR/enums.rs:74:18 | -LL | let _ = &::TO_BE_UNFROZEN_VARIANT; //~ ERROR interior mutable +LL | let _ = &::TO_BE_UNFROZEN_VARIANT; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = help: assign this const to a local or static variable, and use the variable here @@ -50,7 +54,7 @@ LL | let _ = &::TO_BE_UNFROZEN_VARIANT; //~ ERROR in error: a `const` item with interior mutability should not be borrowed --> $DIR/enums.rs:91:18 | -LL | let _ = &Self::UNFROZEN_VARIANT; //~ ERROR interior mutability +LL | let _ = &Self::UNFROZEN_VARIANT; | ^^^^^^^^^^^^^^^^^^^^^^ | = help: assign this const to a local or static variable, and use the variable here @@ -58,7 +62,7 @@ LL | let _ = &Self::UNFROZEN_VARIANT; //~ ERROR interior mutability error: a `const` item with interior mutability should not be borrowed --> $DIR/enums.rs:92:18 | -LL | let _ = &Self::GENERIC_VARIANT; //~ ERROR interior mutability +LL | let _ = &Self::GENERIC_VARIANT; | ^^^^^^^^^^^^^^^^^^^^^ | = help: assign this const to a local or static variable, and use the variable here @@ -66,7 +70,7 @@ LL | let _ = &Self::GENERIC_VARIANT; //~ ERROR interior mutability error: a `const` item with interior mutability should not be borrowed --> $DIR/enums.rs:99:14 | -LL | let _ = &helper::WRAPPED_PRIVATE_UNFROZEN_VARIANT; //~ ERROR interior mutability +LL | let _ = &helper::WRAPPED_PRIVATE_UNFROZEN_VARIANT; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = help: assign this const to a local or static variable, and use the variable here diff --git a/tests/ui/borrow_interior_mutable_const/others.rs b/tests/ui/borrow_interior_mutable_const/others.rs index 7c57864245a..0ea93dd8462 100644 --- a/tests/ui/borrow_interior_mutable_const/others.rs +++ b/tests/ui/borrow_interior_mutable_const/others.rs @@ -1,4 +1,4 @@ -#![warn(clippy::borrow_interior_mutable_const)] +#![deny(clippy::borrow_interior_mutable_const)] #![allow(clippy::declare_interior_mutable_const, clippy::needless_borrow)] #![allow(const_item_mutation)] @@ -51,14 +51,14 @@ impl std::ops::Deref for StaticRef { const CELL_REF: StaticRef<(UnsafeCell,)> = unsafe { StaticRef::new(std::ptr::null()) }; fn main() { - ATOMIC.store(1, Ordering::SeqCst); //~ ERROR interior mutability - assert_eq!(ATOMIC.load(Ordering::SeqCst), 5); //~ ERROR interior mutability + ATOMIC.store(1, Ordering::SeqCst); //~ ERROR: interior mutability + assert_eq!(ATOMIC.load(Ordering::SeqCst), 5); //~ ERROR: interior mutability let _once = ONCE_INIT; - let _once_ref = &ONCE_INIT; //~ ERROR interior mutability - let _once_ref_2 = &&ONCE_INIT; //~ ERROR interior mutability - let _once_ref_4 = &&&&ONCE_INIT; //~ ERROR interior mutability - let _once_mut = &mut ONCE_INIT; //~ ERROR interior mutability + let _once_ref = &ONCE_INIT; //~ ERROR: interior mutability + let _once_ref_2 = &&ONCE_INIT; //~ ERROR: interior mutability + let _once_ref_4 = &&&&ONCE_INIT; //~ ERROR: interior mutability + let _once_mut = &mut ONCE_INIT; //~ ERROR: interior mutability let _atomic_into_inner = ATOMIC.into_inner(); // these should be all fine. let _twice = (ONCE_INIT, ONCE_INIT); @@ -69,23 +69,23 @@ fn main() { let _ref_array_once = &[ONCE_INIT, ONCE_INIT][0]; // referencing projection is still bad. - let _ = &ATOMIC_TUPLE; //~ ERROR interior mutability - let _ = &ATOMIC_TUPLE.0; //~ ERROR interior mutability - let _ = &(&&&&ATOMIC_TUPLE).0; //~ ERROR interior mutability - let _ = &ATOMIC_TUPLE.0[0]; //~ ERROR interior mutability - let _ = ATOMIC_TUPLE.0[0].load(Ordering::SeqCst); //~ ERROR interior mutability + let _ = &ATOMIC_TUPLE; //~ ERROR: interior mutability + let _ = &ATOMIC_TUPLE.0; //~ ERROR: interior mutability + let _ = &(&&&&ATOMIC_TUPLE).0; //~ ERROR: interior mutability + let _ = &ATOMIC_TUPLE.0[0]; //~ ERROR: interior mutability + let _ = ATOMIC_TUPLE.0[0].load(Ordering::SeqCst); //~ ERROR: interior mutability let _ = &*ATOMIC_TUPLE.1; let _ = &ATOMIC_TUPLE.2; let _ = (&&&&ATOMIC_TUPLE).0; let _ = (&&&&ATOMIC_TUPLE).2; let _ = ATOMIC_TUPLE.0; - let _ = ATOMIC_TUPLE.0[0]; //~ ERROR interior mutability + let _ = ATOMIC_TUPLE.0[0]; //~ ERROR: interior mutability let _ = ATOMIC_TUPLE.1.into_iter(); let _ = ATOMIC_TUPLE.2; let _ = &{ ATOMIC_TUPLE }; - CELL.set(2); //~ ERROR interior mutability - assert_eq!(CELL.get(), 6); //~ ERROR interior mutability + CELL.set(2); //~ ERROR: interior mutability + assert_eq!(CELL.get(), 6); //~ ERROR: interior mutability assert_eq!(INTEGER, 8); assert!(STRING.is_empty()); diff --git a/tests/ui/borrow_interior_mutable_const/others.stderr b/tests/ui/borrow_interior_mutable_const/others.stderr index c87ad206c2a..200e04b8f6b 100644 --- a/tests/ui/borrow_interior_mutable_const/others.stderr +++ b/tests/ui/borrow_interior_mutable_const/others.stderr @@ -1,16 +1,20 @@ error: a `const` item with interior mutability should not be borrowed --> $DIR/others.rs:54:5 | -LL | ATOMIC.store(1, Ordering::SeqCst); //~ ERROR interior mutability +LL | ATOMIC.store(1, Ordering::SeqCst); | ^^^^^^ | = help: assign this const to a local or static variable, and use the variable here - = note: `-D clippy::borrow-interior-mutable-const` implied by `-D warnings` +note: the lint level is defined here + --> $DIR/others.rs:1:9 + | +LL | #![deny(clippy::borrow_interior_mutable_const)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: a `const` item with interior mutability should not be borrowed --> $DIR/others.rs:55:16 | -LL | assert_eq!(ATOMIC.load(Ordering::SeqCst), 5); //~ ERROR interior mutability +LL | assert_eq!(ATOMIC.load(Ordering::SeqCst), 5); | ^^^^^^ | = help: assign this const to a local or static variable, and use the variable here @@ -18,7 +22,7 @@ LL | assert_eq!(ATOMIC.load(Ordering::SeqCst), 5); //~ ERROR interior mutabi error: a `const` item with interior mutability should not be borrowed --> $DIR/others.rs:58:22 | -LL | let _once_ref = &ONCE_INIT; //~ ERROR interior mutability +LL | let _once_ref = &ONCE_INIT; | ^^^^^^^^^ | = help: assign this const to a local or static variable, and use the variable here @@ -26,7 +30,7 @@ LL | let _once_ref = &ONCE_INIT; //~ ERROR interior mutability error: a `const` item with interior mutability should not be borrowed --> $DIR/others.rs:59:25 | -LL | let _once_ref_2 = &&ONCE_INIT; //~ ERROR interior mutability +LL | let _once_ref_2 = &&ONCE_INIT; | ^^^^^^^^^ | = help: assign this const to a local or static variable, and use the variable here @@ -34,7 +38,7 @@ LL | let _once_ref_2 = &&ONCE_INIT; //~ ERROR interior mutability error: a `const` item with interior mutability should not be borrowed --> $DIR/others.rs:60:27 | -LL | let _once_ref_4 = &&&&ONCE_INIT; //~ ERROR interior mutability +LL | let _once_ref_4 = &&&&ONCE_INIT; | ^^^^^^^^^ | = help: assign this const to a local or static variable, and use the variable here @@ -42,7 +46,7 @@ LL | let _once_ref_4 = &&&&ONCE_INIT; //~ ERROR interior mutability error: a `const` item with interior mutability should not be borrowed --> $DIR/others.rs:61:26 | -LL | let _once_mut = &mut ONCE_INIT; //~ ERROR interior mutability +LL | let _once_mut = &mut ONCE_INIT; | ^^^^^^^^^ | = help: assign this const to a local or static variable, and use the variable here @@ -50,7 +54,7 @@ LL | let _once_mut = &mut ONCE_INIT; //~ ERROR interior mutability error: a `const` item with interior mutability should not be borrowed --> $DIR/others.rs:72:14 | -LL | let _ = &ATOMIC_TUPLE; //~ ERROR interior mutability +LL | let _ = &ATOMIC_TUPLE; | ^^^^^^^^^^^^ | = help: assign this const to a local or static variable, and use the variable here @@ -58,7 +62,7 @@ LL | let _ = &ATOMIC_TUPLE; //~ ERROR interior mutability error: a `const` item with interior mutability should not be borrowed --> $DIR/others.rs:73:14 | -LL | let _ = &ATOMIC_TUPLE.0; //~ ERROR interior mutability +LL | let _ = &ATOMIC_TUPLE.0; | ^^^^^^^^^^^^ | = help: assign this const to a local or static variable, and use the variable here @@ -66,7 +70,7 @@ LL | let _ = &ATOMIC_TUPLE.0; //~ ERROR interior mutability error: a `const` item with interior mutability should not be borrowed --> $DIR/others.rs:74:19 | -LL | let _ = &(&&&&ATOMIC_TUPLE).0; //~ ERROR interior mutability +LL | let _ = &(&&&&ATOMIC_TUPLE).0; | ^^^^^^^^^^^^ | = help: assign this const to a local or static variable, and use the variable here @@ -74,7 +78,7 @@ LL | let _ = &(&&&&ATOMIC_TUPLE).0; //~ ERROR interior mutability error: a `const` item with interior mutability should not be borrowed --> $DIR/others.rs:75:14 | -LL | let _ = &ATOMIC_TUPLE.0[0]; //~ ERROR interior mutability +LL | let _ = &ATOMIC_TUPLE.0[0]; | ^^^^^^^^^^^^ | = help: assign this const to a local or static variable, and use the variable here @@ -82,7 +86,7 @@ LL | let _ = &ATOMIC_TUPLE.0[0]; //~ ERROR interior mutability error: a `const` item with interior mutability should not be borrowed --> $DIR/others.rs:76:13 | -LL | let _ = ATOMIC_TUPLE.0[0].load(Ordering::SeqCst); //~ ERROR interior mutability +LL | let _ = ATOMIC_TUPLE.0[0].load(Ordering::SeqCst); | ^^^^^^^^^^^^ | = help: assign this const to a local or static variable, and use the variable here @@ -90,7 +94,7 @@ LL | let _ = ATOMIC_TUPLE.0[0].load(Ordering::SeqCst); //~ ERROR interior mu error: a `const` item with interior mutability should not be borrowed --> $DIR/others.rs:82:13 | -LL | let _ = ATOMIC_TUPLE.0[0]; //~ ERROR interior mutability +LL | let _ = ATOMIC_TUPLE.0[0]; | ^^^^^^^^^^^^ | = help: assign this const to a local or static variable, and use the variable here @@ -98,7 +102,7 @@ LL | let _ = ATOMIC_TUPLE.0[0]; //~ ERROR interior mutability error: a `const` item with interior mutability should not be borrowed --> $DIR/others.rs:87:5 | -LL | CELL.set(2); //~ ERROR interior mutability +LL | CELL.set(2); | ^^^^ | = help: assign this const to a local or static variable, and use the variable here @@ -106,7 +110,7 @@ LL | CELL.set(2); //~ ERROR interior mutability error: a `const` item with interior mutability should not be borrowed --> $DIR/others.rs:88:16 | -LL | assert_eq!(CELL.get(), 6); //~ ERROR interior mutability +LL | assert_eq!(CELL.get(), 6); | ^^^^ | = help: assign this const to a local or static variable, and use the variable here diff --git a/tests/ui/borrow_interior_mutable_const/traits.rs b/tests/ui/borrow_interior_mutable_const/traits.rs index 06b5d62e8f9..4da3833cbf5 100644 --- a/tests/ui/borrow_interior_mutable_const/traits.rs +++ b/tests/ui/borrow_interior_mutable_const/traits.rs @@ -1,4 +1,4 @@ -#![warn(clippy::borrow_interior_mutable_const)] +#![deny(clippy::borrow_interior_mutable_const)] #![allow(clippy::declare_interior_mutable_const)] // this file replicates its `declare` counterpart. Please see it for more discussions. @@ -12,7 +12,7 @@ trait ConcreteTypes { const STRING: String; fn function() { - let _ = &Self::ATOMIC; //~ ERROR interior mutable + let _ = &Self::ATOMIC; //~ ERROR: interior mutability let _ = &Self::STRING; } } @@ -23,7 +23,7 @@ impl ConcreteTypes for u64 { fn function() { // Lint this again since implementers can choose not to borrow it. - let _ = &Self::ATOMIC; //~ ERROR interior mutable + let _ = &Self::ATOMIC; //~ ERROR: interior mutability let _ = &Self::STRING; } } @@ -48,7 +48,7 @@ impl GenericTypes for Vec { fn function() { let _ = &Self::TO_REMAIN_GENERIC; - let _ = &Self::TO_BE_CONCRETE; //~ ERROR interior mutable + let _ = &Self::TO_BE_CONCRETE; //~ ERROR: interior mutability } } @@ -83,8 +83,8 @@ impl AssocTypes for Vec { fn function() { let _ = &Self::TO_BE_FROZEN; - let _ = &Self::TO_BE_UNFROZEN; //~ ERROR interior mutable - let _ = &Self::WRAPPED_TO_BE_UNFROZEN; //~ ERROR interior mutable + let _ = &Self::TO_BE_UNFROZEN; //~ ERROR: interior mutability + let _ = &Self::WRAPPED_TO_BE_UNFROZEN; //~ ERROR: interior mutability let _ = &Self::WRAPPED_TO_BE_GENERIC_PARAM; } } @@ -106,7 +106,7 @@ where fn function() { let _ = &Self::NOT_BOUNDED; - let _ = &Self::BOUNDED; //~ ERROR interior mutable + let _ = &Self::BOUNDED; //~ ERROR: interior mutability } } @@ -119,7 +119,7 @@ where fn function() { let _ = &Self::NOT_BOUNDED; - let _ = &Self::BOUNDED; //~ ERROR interior mutable + let _ = &Self::BOUNDED; //~ ERROR: interior mutability } } @@ -148,8 +148,8 @@ impl SelfType for AtomicUsize { const WRAPPED_SELF: Option = Some(AtomicUsize::new(21)); fn function() { - let _ = &Self::SELF; //~ ERROR interior mutable - let _ = &Self::WRAPPED_SELF; //~ ERROR interior mutable + let _ = &Self::SELF; //~ ERROR: interior mutability + let _ = &Self::WRAPPED_SELF; //~ ERROR: interior mutability } } @@ -159,7 +159,7 @@ trait BothOfCellAndGeneric { fn function() { let _ = &Self::DIRECT; - let _ = &Self::INDIRECT; //~ ERROR interior mutable + let _ = &Self::INDIRECT; //~ ERROR: interior mutability } } @@ -169,7 +169,7 @@ impl BothOfCellAndGeneric for Vec { fn function() { let _ = &Self::DIRECT; - let _ = &Self::INDIRECT; //~ ERROR interior mutable + let _ = &Self::INDIRECT; //~ ERROR: interior mutability } } @@ -188,15 +188,15 @@ where const BOUNDED_ASSOC_TYPE: T::ToBeBounded = AtomicUsize::new(19); fn function() { - let _ = &Self::ATOMIC; //~ ERROR interior mutable + let _ = &Self::ATOMIC; //~ ERROR: interior mutability let _ = &Self::COW; let _ = &Self::GENERIC_TYPE; let _ = &Self::ASSOC_TYPE; - let _ = &Self::BOUNDED_ASSOC_TYPE; //~ ERROR interior mutable + let _ = &Self::BOUNDED_ASSOC_TYPE; //~ ERROR: interior mutability } } fn main() { - u64::ATOMIC.store(5, Ordering::SeqCst); //~ ERROR interior mutability - assert_eq!(u64::ATOMIC.load(Ordering::SeqCst), 9); //~ ERROR interior mutability + u64::ATOMIC.store(5, Ordering::SeqCst); //~ ERROR: interior mutability + assert_eq!(u64::ATOMIC.load(Ordering::SeqCst), 9); //~ ERROR: interior mutability } diff --git a/tests/ui/borrow_interior_mutable_const/traits.stderr b/tests/ui/borrow_interior_mutable_const/traits.stderr index f34ae8814c3..add223acd68 100644 --- a/tests/ui/borrow_interior_mutable_const/traits.stderr +++ b/tests/ui/borrow_interior_mutable_const/traits.stderr @@ -1,16 +1,20 @@ error: a `const` item with interior mutability should not be borrowed --> $DIR/traits.rs:15:18 | -LL | let _ = &Self::ATOMIC; //~ ERROR interior mutable +LL | let _ = &Self::ATOMIC; | ^^^^^^^^^^^^ | = help: assign this const to a local or static variable, and use the variable here - = note: `-D clippy::borrow-interior-mutable-const` implied by `-D warnings` +note: the lint level is defined here + --> $DIR/traits.rs:1:9 + | +LL | #![deny(clippy::borrow_interior_mutable_const)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: a `const` item with interior mutability should not be borrowed --> $DIR/traits.rs:26:18 | -LL | let _ = &Self::ATOMIC; //~ ERROR interior mutable +LL | let _ = &Self::ATOMIC; | ^^^^^^^^^^^^ | = help: assign this const to a local or static variable, and use the variable here @@ -18,7 +22,7 @@ LL | let _ = &Self::ATOMIC; //~ ERROR interior mutable error: a `const` item with interior mutability should not be borrowed --> $DIR/traits.rs:51:18 | -LL | let _ = &Self::TO_BE_CONCRETE; //~ ERROR interior mutable +LL | let _ = &Self::TO_BE_CONCRETE; | ^^^^^^^^^^^^^^^^^^^^ | = help: assign this const to a local or static variable, and use the variable here @@ -26,7 +30,7 @@ LL | let _ = &Self::TO_BE_CONCRETE; //~ ERROR interior mutable error: a `const` item with interior mutability should not be borrowed --> $DIR/traits.rs:86:18 | -LL | let _ = &Self::TO_BE_UNFROZEN; //~ ERROR interior mutable +LL | let _ = &Self::TO_BE_UNFROZEN; | ^^^^^^^^^^^^^^^^^^^^ | = help: assign this const to a local or static variable, and use the variable here @@ -34,7 +38,7 @@ LL | let _ = &Self::TO_BE_UNFROZEN; //~ ERROR interior mutable error: a `const` item with interior mutability should not be borrowed --> $DIR/traits.rs:87:18 | -LL | let _ = &Self::WRAPPED_TO_BE_UNFROZEN; //~ ERROR interior mutable +LL | let _ = &Self::WRAPPED_TO_BE_UNFROZEN; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = help: assign this const to a local or static variable, and use the variable here @@ -42,7 +46,7 @@ LL | let _ = &Self::WRAPPED_TO_BE_UNFROZEN; //~ ERROR interior mutable error: a `const` item with interior mutability should not be borrowed --> $DIR/traits.rs:109:18 | -LL | let _ = &Self::BOUNDED; //~ ERROR interior mutable +LL | let _ = &Self::BOUNDED; | ^^^^^^^^^^^^^ | = help: assign this const to a local or static variable, and use the variable here @@ -50,7 +54,7 @@ LL | let _ = &Self::BOUNDED; //~ ERROR interior mutable error: a `const` item with interior mutability should not be borrowed --> $DIR/traits.rs:122:18 | -LL | let _ = &Self::BOUNDED; //~ ERROR interior mutable +LL | let _ = &Self::BOUNDED; | ^^^^^^^^^^^^^ | = help: assign this const to a local or static variable, and use the variable here @@ -58,7 +62,7 @@ LL | let _ = &Self::BOUNDED; //~ ERROR interior mutable error: a `const` item with interior mutability should not be borrowed --> $DIR/traits.rs:151:18 | -LL | let _ = &Self::SELF; //~ ERROR interior mutable +LL | let _ = &Self::SELF; | ^^^^^^^^^^ | = help: assign this const to a local or static variable, and use the variable here @@ -66,7 +70,7 @@ LL | let _ = &Self::SELF; //~ ERROR interior mutable error: a `const` item with interior mutability should not be borrowed --> $DIR/traits.rs:152:18 | -LL | let _ = &Self::WRAPPED_SELF; //~ ERROR interior mutable +LL | let _ = &Self::WRAPPED_SELF; | ^^^^^^^^^^^^^^^^^^ | = help: assign this const to a local or static variable, and use the variable here @@ -74,7 +78,7 @@ LL | let _ = &Self::WRAPPED_SELF; //~ ERROR interior mutable error: a `const` item with interior mutability should not be borrowed --> $DIR/traits.rs:162:18 | -LL | let _ = &Self::INDIRECT; //~ ERROR interior mutable +LL | let _ = &Self::INDIRECT; | ^^^^^^^^^^^^^^ | = help: assign this const to a local or static variable, and use the variable here @@ -82,7 +86,7 @@ LL | let _ = &Self::INDIRECT; //~ ERROR interior mutable error: a `const` item with interior mutability should not be borrowed --> $DIR/traits.rs:172:18 | -LL | let _ = &Self::INDIRECT; //~ ERROR interior mutable +LL | let _ = &Self::INDIRECT; | ^^^^^^^^^^^^^^ | = help: assign this const to a local or static variable, and use the variable here @@ -90,7 +94,7 @@ LL | let _ = &Self::INDIRECT; //~ ERROR interior mutable error: a `const` item with interior mutability should not be borrowed --> $DIR/traits.rs:191:18 | -LL | let _ = &Self::ATOMIC; //~ ERROR interior mutable +LL | let _ = &Self::ATOMIC; | ^^^^^^^^^^^^ | = help: assign this const to a local or static variable, and use the variable here @@ -98,7 +102,7 @@ LL | let _ = &Self::ATOMIC; //~ ERROR interior mutable error: a `const` item with interior mutability should not be borrowed --> $DIR/traits.rs:195:18 | -LL | let _ = &Self::BOUNDED_ASSOC_TYPE; //~ ERROR interior mutable +LL | let _ = &Self::BOUNDED_ASSOC_TYPE; | ^^^^^^^^^^^^^^^^^^^^^^^^ | = help: assign this const to a local or static variable, and use the variable here @@ -106,7 +110,7 @@ LL | let _ = &Self::BOUNDED_ASSOC_TYPE; //~ ERROR interior mutable error: a `const` item with interior mutability should not be borrowed --> $DIR/traits.rs:200:5 | -LL | u64::ATOMIC.store(5, Ordering::SeqCst); //~ ERROR interior mutability +LL | u64::ATOMIC.store(5, Ordering::SeqCst); | ^^^^^^^^^^^ | = help: assign this const to a local or static variable, and use the variable here @@ -114,7 +118,7 @@ LL | u64::ATOMIC.store(5, Ordering::SeqCst); //~ ERROR interior mutability error: a `const` item with interior mutability should not be borrowed --> $DIR/traits.rs:201:16 | -LL | assert_eq!(u64::ATOMIC.load(Ordering::SeqCst), 9); //~ ERROR interior mutability +LL | assert_eq!(u64::ATOMIC.load(Ordering::SeqCst), 9); | ^^^^^^^^^^^ | = help: assign this const to a local or static variable, and use the variable here diff --git a/tests/ui/builtin_type_shadow.rs b/tests/ui/builtin_type_shadow.rs index 69b8b6a0e68..c5addd53434 100644 --- a/tests/ui/builtin_type_shadow.rs +++ b/tests/ui/builtin_type_shadow.rs @@ -3,7 +3,7 @@ fn foo(a: u32) -> u32 { 42 - // ^ rustc's type error + //~^ ERROR: mismatched types } fn main() {} diff --git a/tests/ui/cmp_owned/with_suggestion.fixed b/tests/ui/cmp_owned/with_suggestion.fixed index 76f90ab2a9d..bf1a58588a8 100644 --- a/tests/ui/cmp_owned/with_suggestion.fixed +++ b/tests/ui/cmp_owned/with_suggestion.fixed @@ -31,7 +31,7 @@ struct Foo; impl PartialEq for Foo { // Allow this here, because it emits the lint // without a suggestion. This is tested in - // `tests/ui/cmp_owned/without_suggestion.rs` + // `$DIR/without_suggestion.rs` #[allow(clippy::cmp_owned)] fn eq(&self, other: &Self) -> bool { self.to_owned() == *other diff --git a/tests/ui/cognitive_complexity.stderr b/tests/ui/cognitive_complexity.stderr index 5824631fa83..d867246301a 100644 --- a/tests/ui/cognitive_complexity.stderr +++ b/tests/ui/cognitive_complexity.stderr @@ -39,6 +39,14 @@ LL | fn bar() { | = help: you could split it up into multiple smaller functions +error: the function has a cognitive complexity of (2/1) + --> $DIR/cognitive_complexity.rs:178:4 + | +LL | fn dont_warn_on_tests() { + | ^^^^^^^^^^^^^^^^^^ + | + = help: you could split it up into multiple smaller functions + error: the function has a cognitive complexity of (2/1) --> $DIR/cognitive_complexity.rs:186:4 | @@ -151,5 +159,5 @@ LL | pub async fn async_method() { | = help: you could split it up into multiple smaller functions -error: aborting due to 19 previous errors +error: aborting due to 20 previous errors diff --git a/tests/ui/crashes/auxiliary/proc_macro_crash.rs b/tests/ui/crashes/auxiliary/proc_macro_crash.rs index 66419656a32..5dffddc119a 100644 --- a/tests/ui/crashes/auxiliary/proc_macro_crash.rs +++ b/tests/ui/crashes/auxiliary/proc_macro_crash.rs @@ -1,13 +1,5 @@ -//@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 -// contain a proc-macro. - #![feature(repr128)] #![allow(incomplete_features)] -#![crate_type = "proc-macro"] extern crate proc_macro; diff --git a/tests/ui/crashes/ice-10148.rs b/tests/ui/crashes/ice-10148.rs index c7f0224820e..0df22f41374 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:proc-macro extern crate proc_macros; diff --git a/tests/ui/crashes/ice-3741.rs b/tests/ui/crashes/ice-3741.rs index 3106a2e7216..268c5ba0ad0 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:proc-macro #![warn(clippy::suspicious_else_formatting)] diff --git a/tests/ui/crashes/ice-5497.rs b/tests/ui/crashes/ice-5497.rs index 0769bce5fc8..f77f691c192 100644 --- a/tests/ui/crashes/ice-5497.rs +++ b/tests/ui/crashes/ice-5497.rs @@ -7,5 +7,5 @@ pub trait Foo { impl Foo for Vec { const OOB: i32 = [1][1] + T::OOB; - //~^ ERROR operation will panic + //~^ ERROR: operation will panic } diff --git a/tests/ui/crashes/ice-6250.stderr b/tests/ui/crashes/ice-6250.stderr index 4506d1550bd..b72037b7d4a 100644 --- a/tests/ui/crashes/ice-6250.stderr +++ b/tests/ui/crashes/ice-6250.stderr @@ -1,9 +1,3 @@ -error[E0601]: `main` function not found in crate `ice_6250` - --> $DIR/ice-6250.rs:16:2 - | -LL | } - | ^ consider adding a `main` function to `$DIR/ice-6250.rs` - error[E0308]: mismatched types --> $DIR/ice-6250.rs:12:14 | @@ -29,7 +23,6 @@ help: consider adding `let` LL | let Some(reference) = cache.data.get(key) { | +++ -error: aborting due to 3 previous errors +error: aborting due to 2 previous errors -Some errors have detailed explanations: E0308, E0601. -For more information about an error, try `rustc --explain E0308`. +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/crashes/ice-6251.stderr b/tests/ui/crashes/ice-6251.stderr index 8da2965c635..68a5766c90c 100644 --- a/tests/ui/crashes/ice-6251.stderr +++ b/tests/ui/crashes/ice-6251.stderr @@ -1,9 +1,3 @@ -error[E0601]: `main` function not found in crate `ice_6251` - --> $DIR/ice-6251.rs:6:2 - | -LL | } - | ^ consider adding a `main` function to `$DIR/ice-6251.rs` - error[E0277]: the size for values of type `[u8]` cannot be known at compilation time --> $DIR/ice-6251.rs:4:45 | @@ -35,7 +29,7 @@ LL | fn bug() -> impl Iterator { = note: expected type `usize` found closure `[closure@$DIR/ice-6251.rs:4:44: 4:53]` -error: aborting due to 4 previous errors +error: aborting due to 3 previous errors -Some errors have detailed explanations: E0277, E0308, E0601. +Some errors have detailed explanations: E0277, E0308. For more information about an error, try `rustc --explain E0277`. diff --git a/tests/ui/crashes/ice-6255.rs b/tests/ui/crashes/ice-6255.rs index ccde6aa2b0f..b6555ac5c40 100644 --- a/tests/ui/crashes/ice-6255.rs +++ b/tests/ui/crashes/ice-6255.rs @@ -4,7 +4,6 @@ macro_rules! define_other_core { ( ) => { extern crate std as core; - //~^ ERROR macro-expanded `extern crate` items cannot shadow names passed with `--extern` }; } @@ -13,3 +12,4 @@ fn main() { } define_other_core!(); +//~^ ERROR: macro-expanded `extern crate` items cannot shadow names passed with `--extern` diff --git a/tests/ui/crashes/ice-6256.rs b/tests/ui/crashes/ice-6256.rs index f9ee3e058c1..1d336b3cdc0 100644 --- a/tests/ui/crashes/ice-6256.rs +++ b/tests/ui/crashes/ice-6256.rs @@ -10,6 +10,6 @@ impl dyn TT { #[rustfmt::skip] fn main() { - let f = |x: &dyn TT| x.func(); //[default]~ ERROR: mismatched types - //[nll]~^ ERROR: borrowed data escapes outside of closure + let f = |x: &dyn TT| x.func(); + //~^ ERROR: borrowed data escapes outside of closure } diff --git a/tests/ui/crashes/ice-6256.stderr b/tests/ui/crashes/ice-6256.stderr index 9cfcccf1e3c..671933157c8 100644 --- a/tests/ui/crashes/ice-6256.stderr +++ b/tests/ui/crashes/ice-6256.stderr @@ -1,7 +1,7 @@ error[E0521]: borrowed data escapes outside of closure --> $DIR/ice-6256.rs:13:26 | -LL | let f = |x: &dyn TT| x.func(); //[default]~ ERROR: mismatched types +LL | let f = |x: &dyn TT| x.func(); | - - ^^^^^^^^ | | | | | | | `x` escapes the closure body here diff --git a/tests/ui/crashes/ice-7410.rs b/tests/ui/crashes/ice-7410.rs index a5373cdcae1..a2683b3ce34 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 +//@ignore-target-apple +//@ignore-target-windows #![feature(lang_items, start, libc)] #![no_std] diff --git a/tests/ui/crashes/ice-96721.rs b/tests/ui/crashes/ice-96721.rs index 4b3fb764010..ca68ba3d03a 100644 --- a/tests/ui/crashes/ice-96721.rs +++ b/tests/ui/crashes/ice-96721.rs @@ -4,7 +4,7 @@ macro_rules! foo { }; } -#[path = foo!()] //~ ERROR malformed `path` attribute +#[path = foo!()] //~ ERROR: malformed `path` attribute mod abc {} fn main() {} diff --git a/tests/ui/crashes/ice-96721.stderr b/tests/ui/crashes/ice-96721.stderr index 78c567b8e77..712bd14c685 100644 --- a/tests/ui/crashes/ice-96721.stderr +++ b/tests/ui/crashes/ice-96721.stderr @@ -1,7 +1,7 @@ error: malformed `path` attribute input --> $DIR/ice-96721.rs:7:1 | -LL | #[path = foo!()] //~ ERROR malformed `path` attribute +LL | #[path = foo!()] | ^^^^^^^^^^^^^^^^ help: must be of the form: `#[path = "file"]` error: aborting due to previous error diff --git a/tests/ui/crate_level_checks/entrypoint_recursion.rs b/tests/ui/crate_level_checks/entrypoint_recursion.rs index d6cd594d7c9..aa76688d801 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-target-apple #![feature(rustc_attrs)] diff --git a/tests/ui/crate_level_checks/entrypoint_recursion.stderr b/tests/ui/crate_level_checks/entrypoint_recursion.stderr deleted file mode 100644 index 3d79a115cb3..00000000000 --- a/tests/ui/crate_level_checks/entrypoint_recursion.stderr +++ /dev/null @@ -1,11 +0,0 @@ -error: recursing into entrypoint `a` - --> $DIR/entrypoint_recursion.rs:10:5 - | -LL | a(); - | ^ - | - = help: consider using another function for this recursion - = note: `-D clippy::main-recursion` implied by `-D warnings` - -error: aborting due to previous error - 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 a382135bb69..32eba969592 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 +//@ignore-target-apple #![feature(lang_items, start, libc)] #![no_std] diff --git a/tests/ui/dbg_macro.rs b/tests/ui/dbg_macro.rs index 10788d40481..6c63c098916 100644 --- a/tests/ui/dbg_macro.rs +++ b/tests/ui/dbg_macro.rs @@ -1,4 +1,3 @@ -//@compile-flags: --test #![warn(clippy::dbg_macro)] fn foo(n: u32) -> u32 { diff --git a/tests/ui/dbg_macro.stderr b/tests/ui/dbg_macro.stderr index 530e7663317..3d292625959 100644 --- a/tests/ui/dbg_macro.stderr +++ b/tests/ui/dbg_macro.stderr @@ -1,5 +1,5 @@ error: the `dbg!` macro is intended as a debugging tool - --> $DIR/dbg_macro.rs:5:22 + --> $DIR/dbg_macro.rs:4:22 | LL | if let Some(n) = dbg!(n.checked_sub(4)) { n } else { n } | ^^^^^^^^^^^^^^^^^^^^^^ @@ -11,7 +11,7 @@ LL | if let Some(n) = n.checked_sub(4) { n } else { n } | ~~~~~~~~~~~~~~~~ error: the `dbg!` macro is intended as a debugging tool - --> $DIR/dbg_macro.rs:10:8 + --> $DIR/dbg_macro.rs:9:8 | LL | if dbg!(n <= 1) { | ^^^^^^^^^^^^ @@ -22,7 +22,7 @@ LL | if n <= 1 { | ~~~~~~ error: the `dbg!` macro is intended as a debugging tool - --> $DIR/dbg_macro.rs:11:9 + --> $DIR/dbg_macro.rs:10:9 | LL | dbg!(1) | ^^^^^^^ @@ -33,7 +33,7 @@ LL | 1 | error: the `dbg!` macro is intended as a debugging tool - --> $DIR/dbg_macro.rs:13:9 + --> $DIR/dbg_macro.rs:12:9 | LL | dbg!(n * factorial(n - 1)) | ^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -44,7 +44,7 @@ LL | n * factorial(n - 1) | error: the `dbg!` macro is intended as a debugging tool - --> $DIR/dbg_macro.rs:18:5 + --> $DIR/dbg_macro.rs:17:5 | LL | dbg!(42); | ^^^^^^^^ @@ -55,7 +55,7 @@ LL | 42; | ~~ error: the `dbg!` macro is intended as a debugging tool - --> $DIR/dbg_macro.rs:19:5 + --> $DIR/dbg_macro.rs:18:5 | LL | dbg!(dbg!(dbg!(42))); | ^^^^^^^^^^^^^^^^^^^^ @@ -66,7 +66,7 @@ LL | dbg!(dbg!(42)); | ~~~~~~~~~~~~~~ error: the `dbg!` macro is intended as a debugging tool - --> $DIR/dbg_macro.rs:20:14 + --> $DIR/dbg_macro.rs:19:14 | LL | foo(3) + dbg!(factorial(4)); | ^^^^^^^^^^^^^^^^^^ @@ -77,7 +77,7 @@ LL | foo(3) + factorial(4); | ~~~~~~~~~~~~ error: the `dbg!` macro is intended as a debugging tool - --> $DIR/dbg_macro.rs:21:5 + --> $DIR/dbg_macro.rs:20:5 | LL | dbg!(1, 2, dbg!(3, 4)); | ^^^^^^^^^^^^^^^^^^^^^^ @@ -88,7 +88,7 @@ LL | (1, 2, dbg!(3, 4)); | ~~~~~~~~~~~~~~~~~~ error: the `dbg!` macro is intended as a debugging tool - --> $DIR/dbg_macro.rs:22:5 + --> $DIR/dbg_macro.rs:21:5 | LL | dbg!(1, 2, 3, 4, 5); | ^^^^^^^^^^^^^^^^^^^ @@ -99,7 +99,7 @@ LL | (1, 2, 3, 4, 5); | ~~~~~~~~~~~~~~~ error: the `dbg!` macro is intended as a debugging tool - --> $DIR/dbg_macro.rs:42:5 + --> $DIR/dbg_macro.rs:41:5 | LL | dbg!(); | ^^^^^^^ @@ -111,7 +111,7 @@ LL + | error: the `dbg!` macro is intended as a debugging tool - --> $DIR/dbg_macro.rs:44:13 + --> $DIR/dbg_macro.rs:43:13 | LL | let _ = dbg!(); | ^^^^^^ @@ -122,7 +122,7 @@ LL | let _ = (); | ~~ error: the `dbg!` macro is intended as a debugging tool - --> $DIR/dbg_macro.rs:45:9 + --> $DIR/dbg_macro.rs:44:9 | LL | bar(dbg!()); | ^^^^^^ @@ -133,7 +133,7 @@ LL | bar(()); | ~~ error: the `dbg!` macro is intended as a debugging tool - --> $DIR/dbg_macro.rs:46:10 + --> $DIR/dbg_macro.rs:45:10 | LL | foo!(dbg!()); | ^^^^^^ @@ -144,7 +144,7 @@ LL | foo!(()); | ~~ error: the `dbg!` macro is intended as a debugging tool - --> $DIR/dbg_macro.rs:47:16 + --> $DIR/dbg_macro.rs:46:16 | LL | foo2!(foo!(dbg!())); | ^^^^^^ @@ -155,7 +155,7 @@ LL | foo2!(foo!(())); | ~~ error: the `dbg!` macro is intended as a debugging tool - --> $DIR/dbg_macro.rs:68:9 + --> $DIR/dbg_macro.rs:67:9 | LL | dbg!(2); | ^^^^^^^ @@ -166,7 +166,7 @@ LL | 2; | ~ error: the `dbg!` macro is intended as a debugging tool - --> $DIR/dbg_macro.rs:74:5 + --> $DIR/dbg_macro.rs:73:5 | LL | dbg!(1); | ^^^^^^^ @@ -177,7 +177,7 @@ LL | 1; | ~ error: the `dbg!` macro is intended as a debugging tool - --> $DIR/dbg_macro.rs:79:5 + --> $DIR/dbg_macro.rs:78:5 | LL | dbg!(1); | ^^^^^^^ @@ -188,7 +188,7 @@ LL | 1; | ~ error: the `dbg!` macro is intended as a debugging tool - --> $DIR/dbg_macro.rs:85:9 + --> $DIR/dbg_macro.rs:84:9 | LL | dbg!(1); | ^^^^^^^ diff --git a/tests/ui/declare_interior_mutable_const/enums.rs b/tests/ui/declare_interior_mutable_const/enums.rs index f44518694b8..a88bf7b21b8 100644 --- a/tests/ui/declare_interior_mutable_const/enums.rs +++ b/tests/ui/declare_interior_mutable_const/enums.rs @@ -9,7 +9,7 @@ enum OptionalCell { } // a constant with enums should be linted only when the used variant is unfrozen (#3962). -const UNFROZEN_VARIANT: OptionalCell = OptionalCell::Unfrozen(Cell::new(true)); //~ ERROR interior mutable +const UNFROZEN_VARIANT: OptionalCell = OptionalCell::Unfrozen(Cell::new(true)); //~ ERROR: interior mutable const FROZEN_VARIANT: OptionalCell = OptionalCell::Frozen; const fn unfrozen_variant() -> OptionalCell { @@ -20,7 +20,7 @@ const fn frozen_variant() -> OptionalCell { OptionalCell::Frozen } -const UNFROZEN_VARIANT_FROM_FN: OptionalCell = unfrozen_variant(); //~ ERROR interior mutable +const UNFROZEN_VARIANT_FROM_FN: OptionalCell = unfrozen_variant(); //~ ERROR: interior mutable const FROZEN_VARIANT_FROM_FN: OptionalCell = frozen_variant(); enum NestedInnermost { @@ -43,10 +43,11 @@ struct NestedOutermost { // a constant with enums should be linted according to its value, no matter how structs involve. const NESTED_UNFROZEN_VARIANT: NestedOutermost = NestedOutermost { + //~^ ERROR: interior mutable outer: NestedOuter::NestedInner(NestedInner { inner: NestedInnermost::Unfrozen(AtomicUsize::new(2)), }), -}; //~ ERROR interior mutable +}; const NESTED_FROZEN_VARIANT: NestedOutermost = NestedOutermost { outer: NestedOuter::NestedInner(NestedInner { inner: NestedInnermost::Frozen, @@ -56,11 +57,11 @@ const NESTED_FROZEN_VARIANT: NestedOutermost = NestedOutermost { trait AssocConsts { // When there's no default value, lint it only according to its type. // Further details are on the corresponding code (`NonCopyConst::check_trait_item`). - const TO_BE_UNFROZEN_VARIANT: OptionalCell; //~ ERROR interior mutable - const TO_BE_FROZEN_VARIANT: OptionalCell; //~ ERROR interior mutable + const TO_BE_UNFROZEN_VARIANT: OptionalCell; //~ ERROR: interior mutable + const TO_BE_FROZEN_VARIANT: OptionalCell; //~ ERROR: interior mutable // Lint default values accordingly. - const DEFAULTED_ON_UNFROZEN_VARIANT: OptionalCell = OptionalCell::Unfrozen(Cell::new(false)); //~ ERROR interior mutable + const DEFAULTED_ON_UNFROZEN_VARIANT: OptionalCell = OptionalCell::Unfrozen(Cell::new(false)); //~ ERROR: interior mutable const DEFAULTED_ON_FROZEN_VARIANT: OptionalCell = OptionalCell::Frozen; } @@ -86,7 +87,7 @@ trait AssocTypes { impl AssocTypes for u64 { type ToBeUnfrozen = AtomicUsize; - const TO_BE_UNFROZEN_VARIANT: Option = Some(Self::ToBeUnfrozen::new(4)); //~ ERROR interior mutable + const TO_BE_UNFROZEN_VARIANT: Option = Some(Self::ToBeUnfrozen::new(4)); //~ ERROR: interior mutable const TO_BE_FROZEN_VARIANT: Option = None; } @@ -98,25 +99,25 @@ enum BothOfCellAndGeneric { } impl BothOfCellAndGeneric { - const UNFROZEN_VARIANT: BothOfCellAndGeneric = BothOfCellAndGeneric::Unfrozen(Cell::new(std::ptr::null())); //~ ERROR interior mutable + const UNFROZEN_VARIANT: BothOfCellAndGeneric = BothOfCellAndGeneric::Unfrozen(Cell::new(std::ptr::null())); //~ ERROR: interior mutable // This is a false positive. The argument about this is on `is_value_unfrozen_raw` - const GENERIC_VARIANT: BothOfCellAndGeneric = BothOfCellAndGeneric::Generic(std::ptr::null()); //~ ERROR interior mutable + const GENERIC_VARIANT: BothOfCellAndGeneric = BothOfCellAndGeneric::Generic(std::ptr::null()); //~ ERROR: interior mutable const FROZEN_VARIANT: BothOfCellAndGeneric = BothOfCellAndGeneric::Frozen(5); // This is what is likely to be a false negative when one tries to fix // the `GENERIC_VARIANT` false positive. - const NO_ENUM: Cell<*const T> = Cell::new(std::ptr::null()); //~ ERROR interior mutable + const NO_ENUM: Cell<*const T> = Cell::new(std::ptr::null()); //~ ERROR: interior mutable } // associated types here is basically the same as the one above. trait BothOfCellAndGenericWithAssocType { type AssocType; - const UNFROZEN_VARIANT: BothOfCellAndGeneric = - BothOfCellAndGeneric::Unfrozen(Cell::new(std::ptr::null())); //~ ERROR interior mutable - const GENERIC_VARIANT: BothOfCellAndGeneric = BothOfCellAndGeneric::Generic(std::ptr::null()); //~ ERROR interior mutable + const UNFROZEN_VARIANT: BothOfCellAndGeneric = //~ ERROR: interior mutable + BothOfCellAndGeneric::Unfrozen(Cell::new(std::ptr::null())); + const GENERIC_VARIANT: BothOfCellAndGeneric = BothOfCellAndGeneric::Generic(std::ptr::null()); //~ ERROR: interior mutable const FROZEN_VARIANT: BothOfCellAndGeneric = BothOfCellAndGeneric::Frozen(5); } diff --git a/tests/ui/declare_interior_mutable_const/enums.stderr b/tests/ui/declare_interior_mutable_const/enums.stderr index 84198d54615..6070df749ca 100644 --- a/tests/ui/declare_interior_mutable_const/enums.stderr +++ b/tests/ui/declare_interior_mutable_const/enums.stderr @@ -1,7 +1,7 @@ error: a `const` item should never be interior mutable --> $DIR/enums.rs:12:1 | -LL | const UNFROZEN_VARIANT: OptionalCell = OptionalCell::Unfrozen(Cell::new(true)); //~ ERROR interior mutable +LL | const UNFROZEN_VARIANT: OptionalCell = OptionalCell::Unfrozen(Cell::new(true)); | -----^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | | | make this a static item (maybe with lazy_static) @@ -11,7 +11,7 @@ LL | const UNFROZEN_VARIANT: OptionalCell = OptionalCell::Unfrozen(Cell::new(tru error: a `const` item should never be interior mutable --> $DIR/enums.rs:23:1 | -LL | const UNFROZEN_VARIANT_FROM_FN: OptionalCell = unfrozen_variant(); //~ ERROR interior mutable +LL | const UNFROZEN_VARIANT_FROM_FN: OptionalCell = unfrozen_variant(); | -----^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | | | make this a static item (maybe with lazy_static) @@ -24,65 +24,66 @@ LL | const NESTED_UNFROZEN_VARIANT: NestedOutermost = NestedOutermost { | | | _make this a static item (maybe with lazy_static) | | +LL | | LL | | outer: NestedOuter::NestedInner(NestedInner { LL | | inner: NestedInnermost::Unfrozen(AtomicUsize::new(2)), LL | | }), -LL | | }; //~ ERROR interior mutable +LL | | }; | |__^ -error: a `const` item should never be interior mutable - --> $DIR/enums.rs:59:5 - | -LL | const TO_BE_UNFROZEN_VARIANT: OptionalCell; //~ ERROR interior mutable - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - error: a `const` item should never be interior mutable --> $DIR/enums.rs:60:5 | -LL | const TO_BE_FROZEN_VARIANT: OptionalCell; //~ ERROR interior mutable +LL | const TO_BE_UNFROZEN_VARIANT: OptionalCell; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: a `const` item should never be interior mutable + --> $DIR/enums.rs:61:5 + | +LL | const TO_BE_FROZEN_VARIANT: OptionalCell; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: a `const` item should never be interior mutable - --> $DIR/enums.rs:63:5 + --> $DIR/enums.rs:64:5 | -LL | const DEFAULTED_ON_UNFROZEN_VARIANT: OptionalCell = OptionalCell::Unfrozen(Cell::new(false)); //~ ERROR interior mutable +LL | const DEFAULTED_ON_UNFROZEN_VARIANT: OptionalCell = OptionalCell::Unfrozen(Cell::new(false)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: a `const` item should never be interior mutable - --> $DIR/enums.rs:89:5 + --> $DIR/enums.rs:90:5 | -LL | const TO_BE_UNFROZEN_VARIANT: Option = Some(Self::ToBeUnfrozen::new(4)); //~ ERROR interior mutable +LL | const TO_BE_UNFROZEN_VARIANT: Option = Some(Self::ToBeUnfrozen::new(4)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: a `const` item should never be interior mutable - --> $DIR/enums.rs:101:5 + --> $DIR/enums.rs:102:5 | -LL | const UNFROZEN_VARIANT: BothOfCellAndGeneric = BothOfCellAndGeneric::Unfrozen(Cell::new(std::ptr::null())); //~ ERROR interior mut... +LL | const UNFROZEN_VARIANT: BothOfCellAndGeneric = BothOfCellAndGeneric::Unfrozen(Cell::new(std::ptr::null())); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: a `const` item should never be interior mutable - --> $DIR/enums.rs:104:5 + --> $DIR/enums.rs:105:5 | -LL | const GENERIC_VARIANT: BothOfCellAndGeneric = BothOfCellAndGeneric::Generic(std::ptr::null()); //~ ERROR interior mutable +LL | const GENERIC_VARIANT: BothOfCellAndGeneric = BothOfCellAndGeneric::Generic(std::ptr::null()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: a `const` item should never be interior mutable - --> $DIR/enums.rs:110:5 + --> $DIR/enums.rs:111:5 | -LL | const NO_ENUM: Cell<*const T> = Cell::new(std::ptr::null()); //~ ERROR interior mutable +LL | const NO_ENUM: Cell<*const T> = Cell::new(std::ptr::null()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: a `const` item should never be interior mutable - --> $DIR/enums.rs:117:5 + --> $DIR/enums.rs:118:5 | LL | / const UNFROZEN_VARIANT: BothOfCellAndGeneric = -LL | | BothOfCellAndGeneric::Unfrozen(Cell::new(std::ptr::null())); //~ ERROR interior mutable +LL | | BothOfCellAndGeneric::Unfrozen(Cell::new(std::ptr::null())); | |____________________________________________________________________^ error: a `const` item should never be interior mutable - --> $DIR/enums.rs:119:5 + --> $DIR/enums.rs:120:5 | -LL | const GENERIC_VARIANT: BothOfCellAndGeneric = BothOfCellAndGeneric::Generic(std::ptr::null()); //~ ERROR interior mu... +LL | const GENERIC_VARIANT: BothOfCellAndGeneric = BothOfCellAndGeneric::Generic(std::ptr::null()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to 12 previous errors diff --git a/tests/ui/declare_interior_mutable_const/others.rs b/tests/ui/declare_interior_mutable_const/others.rs index 896596b5679..1cec2980652 100644 --- a/tests/ui/declare_interior_mutable_const/others.rs +++ b/tests/ui/declare_interior_mutable_const/others.rs @@ -6,17 +6,17 @@ use std::fmt::Display; use std::sync::atomic::AtomicUsize; use std::sync::Once; -const ATOMIC: AtomicUsize = AtomicUsize::new(5); //~ ERROR interior mutable -const CELL: Cell = Cell::new(6); //~ ERROR interior mutable +const ATOMIC: AtomicUsize = AtomicUsize::new(5); //~ ERROR: interior mutable +const CELL: Cell = Cell::new(6); //~ ERROR: interior mutable const ATOMIC_TUPLE: ([AtomicUsize; 1], Vec, u8) = ([ATOMIC], Vec::new(), 7); -//~^ ERROR interior mutable +//~^ ERROR: interior mutable macro_rules! declare_const { ($name:ident: $ty:ty = $e:expr) => { const $name: $ty = $e; }; } -declare_const!(_ONCE: Once = Once::new()); //~ ERROR interior mutable +declare_const!(_ONCE: Once = Once::new()); //~ ERROR: interior mutable // const ATOMIC_REF: &AtomicUsize = &AtomicUsize::new(7); // This will simply trigger E0492. @@ -24,12 +24,12 @@ const INTEGER: u8 = 8; const STRING: String = String::new(); const STR: &str = "012345"; const COW: Cow = Cow::Borrowed("abcdef"); -//^ note: a const item of Cow is used in the `postgres` package. +// note: a const item of Cow is used in the `postgres` package. const NO_ANN: &dyn Display = &70; static STATIC_TUPLE: (AtomicUsize, String) = (ATOMIC, STRING); -//^ there should be no lints on this line +// there should be no lints on the line above line mod issue_8493 { use std::cell::Cell; @@ -40,7 +40,7 @@ mod issue_8493 { macro_rules! issue_8493 { () => { - const _BAZ: Cell = Cell::new(0); //~ ERROR interior mutable + const _BAZ: Cell = Cell::new(0); static _FOOBAR: () = { thread_local! { static _VAR: Cell = const { Cell::new(0) }; @@ -49,7 +49,7 @@ mod issue_8493 { }; } - issue_8493!(); + issue_8493!(); //~ ERROR: interior mutable } fn main() {} diff --git a/tests/ui/declare_interior_mutable_const/others.stderr b/tests/ui/declare_interior_mutable_const/others.stderr index 1fd6d7322a7..0259f6a4a28 100644 --- a/tests/ui/declare_interior_mutable_const/others.stderr +++ b/tests/ui/declare_interior_mutable_const/others.stderr @@ -1,7 +1,7 @@ error: a `const` item should never be interior mutable --> $DIR/others.rs:9:1 | -LL | const ATOMIC: AtomicUsize = AtomicUsize::new(5); //~ ERROR interior mutable +LL | const ATOMIC: AtomicUsize = AtomicUsize::new(5); | -----^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | | | make this a static item (maybe with lazy_static) @@ -11,7 +11,7 @@ LL | const ATOMIC: AtomicUsize = AtomicUsize::new(5); //~ ERROR interior mutable error: a `const` item should never be interior mutable --> $DIR/others.rs:10:1 | -LL | const CELL: Cell = Cell::new(6); //~ ERROR interior mutable +LL | const CELL: Cell = Cell::new(6); | -----^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | | | make this a static item (maybe with lazy_static) @@ -30,7 +30,7 @@ error: a `const` item should never be interior mutable LL | const $name: $ty = $e; | ^^^^^^^^^^^^^^^^^^^^^^ ... -LL | declare_const!(_ONCE: Once = Once::new()); //~ ERROR interior mutable +LL | declare_const!(_ONCE: Once = Once::new()); | ----------------------------------------- in this macro invocation | = note: this error originates in the macro `declare_const` (in Nightly builds, run with -Z macro-backtrace for more info) @@ -38,7 +38,7 @@ LL | declare_const!(_ONCE: Once = Once::new()); //~ ERROR interior mutable error: a `const` item should never be interior mutable --> $DIR/others.rs:43:13 | -LL | const _BAZ: Cell = Cell::new(0); //~ ERROR interior mutable +LL | const _BAZ: Cell = Cell::new(0); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ... LL | issue_8493!(); diff --git a/tests/ui/declare_interior_mutable_const/traits.rs b/tests/ui/declare_interior_mutable_const/traits.rs index 256a336db82..a6ccdd27079 100644 --- a/tests/ui/declare_interior_mutable_const/traits.rs +++ b/tests/ui/declare_interior_mutable_const/traits.rs @@ -12,10 +12,10 @@ macro_rules! declare_const { // a constant whose type is a concrete type should be linted at the definition site. trait ConcreteTypes { - const ATOMIC: AtomicUsize; //~ ERROR interior mutable + const ATOMIC: AtomicUsize; //~ ERROR: interior mutable const INTEGER: u64; const STRING: String; - declare_const!(ANOTHER_ATOMIC: AtomicUsize = Self::ATOMIC); //~ ERROR interior mutable + declare_const!(ANOTHER_ATOMIC: AtomicUsize = Self::ATOMIC); //~ ERROR: interior mutable } impl ConcreteTypes for u64 { @@ -40,7 +40,7 @@ trait GenericTypes { impl GenericTypes for u64 { const TO_REMAIN_GENERIC: T = T::DEFAULT; - const TO_BE_CONCRETE: AtomicUsize = AtomicUsize::new(11); //~ ERROR interior mutable + const TO_BE_CONCRETE: AtomicUsize = AtomicUsize::new(11); //~ ERROR: interior mutable } // a helper type used below @@ -65,8 +65,8 @@ impl AssocTypes for Vec { type ToBeGenericParam = T; const TO_BE_FROZEN: Self::ToBeFrozen = 12; - const TO_BE_UNFROZEN: Self::ToBeUnfrozen = AtomicUsize::new(13); //~ ERROR interior mutable - const WRAPPED_TO_BE_UNFROZEN: Wrapper = Wrapper(AtomicUsize::new(14)); //~ ERROR interior mutable + const TO_BE_UNFROZEN: Self::ToBeUnfrozen = AtomicUsize::new(13); //~ ERROR: interior mutable + const WRAPPED_TO_BE_UNFROZEN: Wrapper = Wrapper(AtomicUsize::new(14)); //~ ERROR: interior mutable const WRAPPED_TO_BE_GENERIC_PARAM: Wrapper = Wrapper(T::DEFAULT); } @@ -85,7 +85,7 @@ where T: AssocTypesHelper, { const NOT_BOUNDED: T::NotToBeBounded; - const BOUNDED: T::ToBeBounded; //~ ERROR interior mutable + const BOUNDED: T::ToBeBounded; //~ ERROR: interior mutable } impl AssocTypesFromGenericParam for u64 @@ -113,8 +113,8 @@ impl SelfType for u64 { impl SelfType for AtomicUsize { // this (interior mutable `Self` const) exists in `parking_lot`. // `const_trait_impl` will replace it in the future, hopefully. - const SELF: Self = AtomicUsize::new(17); //~ ERROR interior mutable - const WRAPPED_SELF: Option = Some(AtomicUsize::new(21)); //~ ERROR interior mutable + const SELF: Self = AtomicUsize::new(17); //~ ERROR: interior mutable + const WRAPPED_SELF: Option = Some(AtomicUsize::new(21)); //~ ERROR: interior mutable } // Even though a constant contains a generic type, if it also have an interior mutable type, @@ -122,7 +122,7 @@ impl SelfType for AtomicUsize { trait BothOfCellAndGeneric { // this is a false negative in the current implementation. const DIRECT: Cell; - const INDIRECT: Cell<*const T>; //~ ERROR interior mutable + const INDIRECT: Cell<*const T>; //~ ERROR: interior mutable } impl BothOfCellAndGeneric for u64 { @@ -138,13 +138,13 @@ impl Local where T: ConstDefault + AssocTypesHelper, { - const ATOMIC: AtomicUsize = AtomicUsize::new(18); //~ ERROR interior mutable + const ATOMIC: AtomicUsize = AtomicUsize::new(18); //~ ERROR: interior mutable const COW: Cow<'static, str> = Cow::Borrowed("tuvwxy"); const GENERIC_TYPE: T = T::DEFAULT; const ASSOC_TYPE: T::NotToBeBounded = T::NOT_TO_BE_BOUNDED; - const BOUNDED_ASSOC_TYPE: T::ToBeBounded = AtomicUsize::new(19); //~ ERROR interior mutable + const BOUNDED_ASSOC_TYPE: T::ToBeBounded = AtomicUsize::new(19); //~ ERROR: interior mutable } fn main() {} diff --git a/tests/ui/declare_interior_mutable_const/traits.stderr b/tests/ui/declare_interior_mutable_const/traits.stderr index 7debe059ff4..ef62919dfea 100644 --- a/tests/ui/declare_interior_mutable_const/traits.stderr +++ b/tests/ui/declare_interior_mutable_const/traits.stderr @@ -1,7 +1,7 @@ error: a `const` item should never be interior mutable --> $DIR/traits.rs:15:5 | -LL | const ATOMIC: AtomicUsize; //~ ERROR interior mutable +LL | const ATOMIC: AtomicUsize; | ^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: `-D clippy::declare-interior-mutable-const` implied by `-D warnings` @@ -12,7 +12,7 @@ error: a `const` item should never be interior mutable LL | const $name: $ty = $e; | ^^^^^^^^^^^^^^^^^^^^^^ ... -LL | declare_const!(ANOTHER_ATOMIC: AtomicUsize = Self::ATOMIC); //~ ERROR interior mutable +LL | declare_const!(ANOTHER_ATOMIC: AtomicUsize = Self::ATOMIC); | ---------------------------------------------------------- in this macro invocation | = note: this error originates in the macro `declare_const` (in Nightly builds, run with -Z macro-backtrace for more info) @@ -20,55 +20,55 @@ LL | declare_const!(ANOTHER_ATOMIC: AtomicUsize = Self::ATOMIC); //~ ERROR i error: a `const` item should never be interior mutable --> $DIR/traits.rs:43:5 | -LL | const TO_BE_CONCRETE: AtomicUsize = AtomicUsize::new(11); //~ ERROR interior mutable +LL | const TO_BE_CONCRETE: AtomicUsize = AtomicUsize::new(11); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: a `const` item should never be interior mutable --> $DIR/traits.rs:68:5 | -LL | const TO_BE_UNFROZEN: Self::ToBeUnfrozen = AtomicUsize::new(13); //~ ERROR interior mutable +LL | const TO_BE_UNFROZEN: Self::ToBeUnfrozen = AtomicUsize::new(13); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: a `const` item should never be interior mutable --> $DIR/traits.rs:69:5 | -LL | const WRAPPED_TO_BE_UNFROZEN: Wrapper = Wrapper(AtomicUsize::new(14)); //~ ERROR interior mutable +LL | const WRAPPED_TO_BE_UNFROZEN: Wrapper = Wrapper(AtomicUsize::new(14)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: a `const` item should never be interior mutable --> $DIR/traits.rs:88:5 | -LL | const BOUNDED: T::ToBeBounded; //~ ERROR interior mutable +LL | const BOUNDED: T::ToBeBounded; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: a `const` item should never be interior mutable --> $DIR/traits.rs:116:5 | -LL | const SELF: Self = AtomicUsize::new(17); //~ ERROR interior mutable +LL | const SELF: Self = AtomicUsize::new(17); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: a `const` item should never be interior mutable --> $DIR/traits.rs:117:5 | -LL | const WRAPPED_SELF: Option = Some(AtomicUsize::new(21)); //~ ERROR interior mutable +LL | const WRAPPED_SELF: Option = Some(AtomicUsize::new(21)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: a `const` item should never be interior mutable --> $DIR/traits.rs:125:5 | -LL | const INDIRECT: Cell<*const T>; //~ ERROR interior mutable +LL | const INDIRECT: Cell<*const T>; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: a `const` item should never be interior mutable --> $DIR/traits.rs:141:5 | -LL | const ATOMIC: AtomicUsize = AtomicUsize::new(18); //~ ERROR interior mutable +LL | const ATOMIC: AtomicUsize = AtomicUsize::new(18); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: a `const` item should never be interior mutable --> $DIR/traits.rs:147:5 | -LL | const BOUNDED_ASSOC_TYPE: T::ToBeBounded = AtomicUsize::new(19); //~ ERROR interior mutable +LL | const BOUNDED_ASSOC_TYPE: T::ToBeBounded = AtomicUsize::new(19); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to 11 previous errors diff --git a/tests/ui/def_id_nocore.rs b/tests/ui/def_id_nocore.rs index f7819068ac5..da0816830b8 100644 --- a/tests/ui/def_id_nocore.rs +++ b/tests/ui/def_id_nocore.rs @@ -1,4 +1,4 @@ -//@ignore-macos +//@ignore-target-apple #![feature(no_core, lang_items, start)] #![no_core] diff --git a/tests/ui/default_numeric_fallback_f64.fixed b/tests/ui/default_numeric_fallback_f64.fixed index 9520efe6329..02eb7806013 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 +//@aux-build:proc_macros.rs:proc-macro #![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 cacbdb4a95b..79a9669833f 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 +//@aux-build:proc_macros.rs:proc-macro #![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 fbabb8bcf8e..23272d07eec 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 +//@aux-build:proc_macros.rs:proc-macro #![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 7bfc390e4bf..fb149141609 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 +//@aux-build:proc_macros.rs:proc-macro #![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 bf5dca97641..14eb6d572cf 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 +//@aux-build: proc_macros.rs:proc-macro #![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 5e8e9ce85b1..aa2ced0a7f0 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 +//@aux-build: proc_macros.rs:proc-macro #![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 0bf739fe2d1..0ecca1b8ffa 100644 --- a/tests/ui/deref_addrof.fixed +++ b/tests/ui/deref_addrof.fixed @@ -1,5 +1,5 @@ //@run-rustfix -//@aux-build:proc_macros.rs +//@aux-build:proc_macros.rs:proc-macro #![allow(clippy::return_self_not_must_use, clippy::useless_vec)] #![warn(clippy::deref_addrof)] diff --git a/tests/ui/deref_addrof.rs b/tests/ui/deref_addrof.rs index 2d796a24fec..9f91310e61f 100644 --- a/tests/ui/deref_addrof.rs +++ b/tests/ui/deref_addrof.rs @@ -1,5 +1,5 @@ //@run-rustfix -//@aux-build:proc_macros.rs +//@aux-build:proc_macros.rs:proc-macro #![allow(clippy::return_self_not_must_use, clippy::useless_vec)] #![warn(clippy::deref_addrof)] diff --git a/tests/ui/deref_addrof_macro.rs b/tests/ui/deref_addrof_macro.rs index c7e60f36506..ce4b94a73bd 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:proc-macro #![warn(clippy::deref_addrof)] diff --git a/tests/ui/doc_unsafe.rs b/tests/ui/doc_unsafe.rs index 0c8eac5ccff..d21b046f167 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:proc-macro #![allow(clippy::let_unit_value)] diff --git a/tests/ui/else_if_without_else.rs b/tests/ui/else_if_without_else.rs index 879b3ac398e..eb5e2266540 100644 --- a/tests/ui/else_if_without_else.rs +++ b/tests/ui/else_if_without_else.rs @@ -43,7 +43,7 @@ fn main() { if bla1() { println!("if"); } else if bla2() { - //~ ERROR else if without else + //~^ ERROR: `if` expression with an `else if`, but without a final `else` println!("else if"); } @@ -52,7 +52,7 @@ fn main() { } else if bla2() { println!("else if 1"); } else if bla3() { - //~ ERROR else if without else + //~^ ERROR: `if` expression with an `else if`, but without a final `else` println!("else if 2"); } } diff --git a/tests/ui/else_if_without_else.stderr b/tests/ui/else_if_without_else.stderr index 90ccfb4fad6..11baf75441a 100644 --- a/tests/ui/else_if_without_else.stderr +++ b/tests/ui/else_if_without_else.stderr @@ -3,7 +3,7 @@ error: `if` expression with an `else if`, but without a final `else` | LL | } else if bla2() { | ____________^ -LL | | //~ ERROR else if without else +LL | | LL | | println!("else if"); LL | | } | |_____^ @@ -16,7 +16,7 @@ error: `if` expression with an `else if`, but without a final `else` | LL | } else if bla3() { | ____________^ -LL | | //~ ERROR else if without else +LL | | LL | | println!("else if 2"); LL | | } | |_____^ diff --git a/tests/ui/empty_line_after_doc_comments.rs b/tests/ui/empty_line_after_doc_comments.rs index e843770f578..83db2a07d33 100644 --- a/tests/ui/empty_line_after_doc_comments.rs +++ b/tests/ui/empty_line_after_doc_comments.rs @@ -1,4 +1,4 @@ -//@aux-build:proc_macro_attr.rs +//@aux-build:proc_macro_attr.rs:proc-macro #![warn(clippy::empty_line_after_doc_comments)] #![allow(clippy::assertions_on_constants)] #![feature(custom_inner_attributes)] diff --git a/tests/ui/empty_line_after_outer_attribute.rs b/tests/ui/empty_line_after_outer_attribute.rs index 269e66ea0a8..b2d7ddae427 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:proc-macro #![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 54e8fb4907c..f1a55415c8d 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:proc-macro #![warn(clippy::empty_loop)] diff --git a/tests/ui/empty_loop_no_std.rs b/tests/ui/empty_loop_no_std.rs index d564b2d24f5..f9ab443dfd9 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 +//@ignore-target-apple #![warn(clippy::empty_loop)] #![feature(lang_items, start, libc)] diff --git a/tests/ui/enum_clike_unportable_variant.rs b/tests/ui/enum_clike_unportable_variant.rs index f17556ea907..abe42a2305f 100644 --- a/tests/ui/enum_clike_unportable_variant.rs +++ b/tests/ui/enum_clike_unportable_variant.rs @@ -1,4 +1,4 @@ -//@ignore-x86 +//@ignore-target-x86 #![warn(clippy::enum_clike_unportable_variant)] #![allow(unused, non_upper_case_globals)] diff --git a/tests/ui/eprint_with_newline.rs b/tests/ui/eprint_with_newline.rs index de5e121be87..8389806c838 100644 --- a/tests/ui/eprint_with_newline.rs +++ b/tests/ui/eprint_with_newline.rs @@ -44,7 +44,7 @@ fn main() { // Don't warn on CRLF (#4208) eprint!("\r\n"); eprint!("foo\r\n"); - eprint!("\\r\n"); //~ ERROR + eprint!("\\r\n"); eprint!("foo\rbar\n"); // Ignore expanded format strings diff --git a/tests/ui/eprint_with_newline.stderr b/tests/ui/eprint_with_newline.stderr index 0eefb9f0ca9..0a6bdf15df8 100644 --- a/tests/ui/eprint_with_newline.stderr +++ b/tests/ui/eprint_with_newline.stderr @@ -62,13 +62,13 @@ LL + eprintln!(); error: using `eprint!()` with a format string that ends in a single newline --> $DIR/eprint_with_newline.rs:28:5 | -LL | eprint!("//n"); // should fail +LL | eprint!("///n"); // should fail | ^^^^^^^^^^^^^^^ | help: use `eprintln!` instead | -LL - eprint!("//n"); // should fail -LL + eprintln!("/"); // should fail +LL - eprint!("///n"); // should fail +LL + eprintln!("//"); // should fail | error: using `eprint!()` with a format string that ends in a single newline @@ -104,13 +104,13 @@ LL ~ error: using `eprint!()` with a format string that ends in a single newline --> $DIR/eprint_with_newline.rs:47:5 | -LL | eprint!("/r/n"); //~ ERROR +LL | eprint!("//r/n"); | ^^^^^^^^^^^^^^^^ | help: use `eprintln!` instead | -LL - eprint!("/r/n"); //~ ERROR -LL + eprintln!("/r"); //~ ERROR +LL - eprint!("//r/n"); +LL + eprintln!("//r"); | error: aborting due to 9 previous errors diff --git a/tests/ui/eq_op.rs b/tests/ui/eq_op.rs index cdd33ebe582..38372378168 100644 --- a/tests/ui/eq_op.rs +++ b/tests/ui/eq_op.rs @@ -1,5 +1,3 @@ -//@compile-flags: --test - #![warn(clippy::eq_op)] #![allow(clippy::double_parens, clippy::identity_op, clippy::nonminimal_bool)] #![allow(clippy::suspicious_xor_used_as_pow)] diff --git a/tests/ui/eq_op.stderr b/tests/ui/eq_op.stderr index d365ab27edc..2c013b6b6fe 100644 --- a/tests/ui/eq_op.stderr +++ b/tests/ui/eq_op.stderr @@ -1,5 +1,5 @@ error: equal expressions as operands to `==` - --> $DIR/eq_op.rs:9:13 + --> $DIR/eq_op.rs:7:13 | LL | let _ = 1 == 1; | ^^^^^^ @@ -7,163 +7,163 @@ LL | let _ = 1 == 1; = note: `-D clippy::eq-op` implied by `-D warnings` error: equal expressions as operands to `==` - --> $DIR/eq_op.rs:10:13 + --> $DIR/eq_op.rs:8:13 | LL | let _ = "no" == "no"; | ^^^^^^^^^^^^ error: equal expressions as operands to `!=` - --> $DIR/eq_op.rs:12:13 + --> $DIR/eq_op.rs:10:13 | LL | let _ = false != false; | ^^^^^^^^^^^^^^ error: equal expressions as operands to `<` - --> $DIR/eq_op.rs:13:13 + --> $DIR/eq_op.rs:11:13 | LL | let _ = 1.5 < 1.5; | ^^^^^^^^^ error: equal expressions as operands to `>=` - --> $DIR/eq_op.rs:14:13 + --> $DIR/eq_op.rs:12:13 | LL | let _ = 1u64 >= 1u64; | ^^^^^^^^^^^^ error: equal expressions as operands to `&` - --> $DIR/eq_op.rs:17:13 + --> $DIR/eq_op.rs:15:13 | LL | let _ = (1u32 as u64) & (1u32 as u64); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: equal expressions as operands to `^` - --> $DIR/eq_op.rs:20:17 + --> $DIR/eq_op.rs:18:17 | LL | let _ = 1 ^ ((((((1)))))); | ^^^^^^^^^^^^^^^^^ error: equal expressions as operands to `<` - --> $DIR/eq_op.rs:24:13 + --> $DIR/eq_op.rs:22:13 | LL | let _ = (-(2) < -(2)); | ^^^^^^^^^^^^^ error: equal expressions as operands to `==` - --> $DIR/eq_op.rs:25:13 + --> $DIR/eq_op.rs:23:13 | LL | let _ = ((1 + 1) & (1 + 1) == (1 + 1) & (1 + 1)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: equal expressions as operands to `&` - --> $DIR/eq_op.rs:25:14 + --> $DIR/eq_op.rs:23:14 | LL | let _ = ((1 + 1) & (1 + 1) == (1 + 1) & (1 + 1)); | ^^^^^^^^^^^^^^^^^ error: equal expressions as operands to `&` - --> $DIR/eq_op.rs:25:35 + --> $DIR/eq_op.rs:23:35 | LL | let _ = ((1 + 1) & (1 + 1) == (1 + 1) & (1 + 1)); | ^^^^^^^^^^^^^^^^^ error: equal expressions as operands to `==` - --> $DIR/eq_op.rs:26:13 + --> $DIR/eq_op.rs:24:13 | LL | let _ = (1 * 2) + (3 * 4) == 1 * 2 + 3 * 4; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: equal expressions as operands to `!=` - --> $DIR/eq_op.rs:29:13 + --> $DIR/eq_op.rs:27:13 | LL | let _ = ([1] != [1]); | ^^^^^^^^^^^^ error: equal expressions as operands to `!=` - --> $DIR/eq_op.rs:30:13 + --> $DIR/eq_op.rs:28:13 | LL | let _ = ((1, 2) != (1, 2)); | ^^^^^^^^^^^^^^^^^^ error: equal expressions as operands to `==` - --> $DIR/eq_op.rs:34:13 + --> $DIR/eq_op.rs:32:13 | LL | let _ = 1 + 1 == 2; | ^^^^^^^^^^ error: equal expressions as operands to `==` - --> $DIR/eq_op.rs:35:13 + --> $DIR/eq_op.rs:33:13 | LL | let _ = 1 - 1 == 0; | ^^^^^^^^^^ error: equal expressions as operands to `-` - --> $DIR/eq_op.rs:35:13 + --> $DIR/eq_op.rs:33:13 | LL | let _ = 1 - 1 == 0; | ^^^^^ error: equal expressions as operands to `-` - --> $DIR/eq_op.rs:37:13 + --> $DIR/eq_op.rs:35:13 | LL | let _ = 1 - 1; | ^^^^^ error: equal expressions as operands to `/` - --> $DIR/eq_op.rs:38:13 + --> $DIR/eq_op.rs:36:13 | LL | let _ = 1 / 1; | ^^^^^ error: equal expressions as operands to `&&` - --> $DIR/eq_op.rs:39:13 + --> $DIR/eq_op.rs:37:13 | LL | let _ = true && true; | ^^^^^^^^^^^^ error: equal expressions as operands to `||` - --> $DIR/eq_op.rs:41:13 + --> $DIR/eq_op.rs:39:13 | LL | let _ = true || true; | ^^^^^^^^^^^^ error: equal expressions as operands to `&&` - --> $DIR/eq_op.rs:46:13 + --> $DIR/eq_op.rs:44:13 | LL | let _ = a == b && b == a; | ^^^^^^^^^^^^^^^^ error: equal expressions as operands to `&&` - --> $DIR/eq_op.rs:47:13 + --> $DIR/eq_op.rs:45:13 | LL | let _ = a != b && b != a; | ^^^^^^^^^^^^^^^^ error: equal expressions as operands to `&&` - --> $DIR/eq_op.rs:48:13 + --> $DIR/eq_op.rs:46:13 | LL | let _ = a < b && b > a; | ^^^^^^^^^^^^^^ error: equal expressions as operands to `&&` - --> $DIR/eq_op.rs:49:13 + --> $DIR/eq_op.rs:47:13 | LL | let _ = a <= b && b >= a; | ^^^^^^^^^^^^^^^^ error: equal expressions as operands to `==` - --> $DIR/eq_op.rs:52:13 + --> $DIR/eq_op.rs:50:13 | LL | let _ = a == a; | ^^^^^^ error: equal expressions as operands to `/` - --> $DIR/eq_op.rs:62:20 + --> $DIR/eq_op.rs:60:20 | LL | const D: u32 = A / A; | ^^^^^ error: equal expressions as operands to `==` - --> $DIR/eq_op.rs:93:5 + --> $DIR/eq_op.rs:91:5 | LL | (n1.inner.0).0 == (n1.inner.0).0 && (n1.inner.1).0 == (n2.inner.1).0 && (n1.inner.2).0 == (n2.inner.2).0 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/equatable_if_let.fixed b/tests/ui/equatable_if_let.fixed index 1869301d224..6cc070fb552 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 +//@aux-build:proc_macros.rs:proc-macro #![allow( unused_variables, diff --git a/tests/ui/equatable_if_let.rs b/tests/ui/equatable_if_let.rs index a78aec74a7b..f00a129bef1 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 +//@aux-build:proc_macros.rs:proc-macro #![allow( unused_variables, diff --git a/tests/ui/extra_unused_lifetimes.rs b/tests/ui/extra_unused_lifetimes.rs index cdfaf8d3afe..50abe89da89 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:proc-macro #![allow( unused, diff --git a/tests/ui/extra_unused_type_parameters.fixed b/tests/ui/extra_unused_type_parameters.fixed index 03ac9abf498..8420df6634d 100644 --- a/tests/ui/extra_unused_type_parameters.fixed +++ b/tests/ui/extra_unused_type_parameters.fixed @@ -1,5 +1,5 @@ //@run-rustfix -//@aux-build:proc_macros.rs +//@aux-build:proc_macros.rs:proc-macro #![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 731c89c18dc..f63535d7ae6 100644 --- a/tests/ui/extra_unused_type_parameters.rs +++ b/tests/ui/extra_unused_type_parameters.rs @@ -1,5 +1,5 @@ //@run-rustfix -//@aux-build:proc_macros.rs +//@aux-build:proc_macros.rs:proc-macro #![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 2045b1eebcd..d6df114b8d2 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:proc-macro +//@aux-build:proc_macros.rs:proc-macro #![warn(clippy::field_reassign_with_default)] diff --git a/tests/ui/get_unwrap.fixed b/tests/ui/get_unwrap.fixed index f0d28dd9349..56ee37f02d2 100644 --- a/tests/ui/get_unwrap.fixed +++ b/tests/ui/get_unwrap.fixed @@ -76,14 +76,14 @@ mod issue9909 { fn reduced() { let f = &[1, 2, 3]; + // include a borrow in the suggestion, even if the argument is not just a numeric literal let _x: &i32 = &f[1 + 2]; - // ^ include a borrow in the suggestion, even if the argument is not just a numeric literal + // don't include a borrow here let _x = f[1 + 2].to_string(); - // ^ don't include a borrow here + // don't include a borrow here let _x = f[1 + 2].abs(); - // ^ don't include a borrow here } // original code: diff --git a/tests/ui/get_unwrap.rs b/tests/ui/get_unwrap.rs index 21c1ecb0af2..af3a619adc5 100644 --- a/tests/ui/get_unwrap.rs +++ b/tests/ui/get_unwrap.rs @@ -76,14 +76,14 @@ mod issue9909 { fn reduced() { let f = &[1, 2, 3]; + // include a borrow in the suggestion, even if the argument is not just a numeric literal let _x: &i32 = f.get(1 + 2).unwrap(); - // ^ include a borrow in the suggestion, even if the argument is not just a numeric literal + // don't include a borrow here let _x = f.get(1 + 2).unwrap().to_string(); - // ^ don't include a borrow here + // don't include a borrow here let _x = f.get(1 + 2).unwrap().abs(); - // ^ don't include a borrow here } // original code: diff --git a/tests/ui/get_unwrap.stderr b/tests/ui/get_unwrap.stderr index 154083ea654..fd961420dc4 100644 --- a/tests/ui/get_unwrap.stderr +++ b/tests/ui/get_unwrap.stderr @@ -188,19 +188,19 @@ LL | let _ = some_vec.get_mut(0..1).unwrap().to_vec(); = help: if you don't want to handle the `None` case gracefully, consider using `expect()` to provide a better panic message error: called `.get().unwrap()` on a slice. Using `[]` is more clear and more concise - --> $DIR/get_unwrap.rs:79:24 + --> $DIR/get_unwrap.rs:80:24 | LL | let _x: &i32 = f.get(1 + 2).unwrap(); | ^^^^^^^^^^^^^^^^^^^^^ help: try this: `&f[1 + 2]` error: called `.get().unwrap()` on a slice. Using `[]` is more clear and more concise - --> $DIR/get_unwrap.rs:82:18 + --> $DIR/get_unwrap.rs:83:18 | LL | let _x = f.get(1 + 2).unwrap().to_string(); | ^^^^^^^^^^^^^^^^^^^^^ help: try this: `f[1 + 2]` error: called `.get().unwrap()` on a slice. Using `[]` is more clear and more concise - --> $DIR/get_unwrap.rs:85:18 + --> $DIR/get_unwrap.rs:86:18 | LL | let _x = f.get(1 + 2).unwrap().abs(); | ^^^^^^^^^^^^^^^^^^^^^ help: try this: `f[1 + 2]` diff --git a/tests/ui/if_same_then_else.rs b/tests/ui/if_same_then_else.rs index 07d2002eb27..dad4543f84c 100644 --- a/tests/ui/if_same_then_else.rs +++ b/tests/ui/if_same_then_else.rs @@ -21,6 +21,7 @@ fn foo() -> bool { fn if_same_then_else() { if true { + //~^ ERROR: this `if` has identical blocks Foo { bar: 42 }; 0..10; ..; @@ -29,7 +30,6 @@ fn if_same_then_else() { 0..=10; foo(); } else { - //~ ERROR same body as `if` block Foo { bar: 42 }; 0..10; ..; @@ -65,16 +65,16 @@ fn if_same_then_else() { } let _ = if true { + //~^ ERROR: this `if` has identical blocks 0.0 } else { - //~ ERROR same body as `if` block 0.0 }; let _ = if true { + //~^ ERROR: this `if` has identical blocks -0.0 } else { - //~ ERROR same body as `if` block -0.0 }; @@ -88,13 +88,14 @@ fn if_same_then_else() { } let _ = if true { + //~^ ERROR: this `if` has identical blocks 42 } else { - //~ ERROR same body as `if` block 42 }; if true { + //~^ ERROR: this `if` has identical blocks let bar = if true { 42 } else { 43 }; while foo() { @@ -102,7 +103,6 @@ fn if_same_then_else() { } bar + 1; } else { - //~ ERROR same body as `if` block let bar = if true { 42 } else { 43 }; while foo() { diff --git a/tests/ui/if_same_then_else.stderr b/tests/ui/if_same_then_else.stderr index fb23b81d36d..a34fc565590 100644 --- a/tests/ui/if_same_then_else.stderr +++ b/tests/ui/if_same_then_else.stderr @@ -3,22 +3,22 @@ error: this `if` has identical blocks | LL | if true { | _____________^ +LL | | LL | | Foo { bar: 42 }; LL | | 0..10; -LL | | ..; ... | LL | | foo(); LL | | } else { | |_____^ | note: same as this - --> $DIR/if_same_then_else.rs:31:12 + --> $DIR/if_same_then_else.rs:32:12 | LL | } else { | ____________^ -LL | | //~ ERROR same body as `if` block LL | | Foo { bar: 42 }; LL | | 0..10; +LL | | ..; ... | LL | | foo(); LL | | } @@ -30,16 +30,16 @@ error: this `if` has identical blocks | LL | let _ = if true { | _____________________^ +LL | | LL | | 0.0 LL | | } else { | |_____^ | note: same as this - --> $DIR/if_same_then_else.rs:69:12 + --> $DIR/if_same_then_else.rs:70:12 | LL | } else { | ____________^ -LL | | //~ ERROR same body as `if` block LL | | 0.0 LL | | }; | |_____^ @@ -49,16 +49,16 @@ error: this `if` has identical blocks | LL | let _ = if true { | _____________________^ +LL | | LL | | -0.0 LL | | } else { | |_____^ | note: same as this - --> $DIR/if_same_then_else.rs:76:12 + --> $DIR/if_same_then_else.rs:77:12 | LL | } else { | ____________^ -LL | | //~ ERROR same body as `if` block LL | | -0.0 LL | | }; | |_____^ @@ -68,16 +68,16 @@ error: this `if` has identical blocks | LL | let _ = if true { | _____________________^ +LL | | LL | | 42 LL | | } else { | |_____^ | note: same as this - --> $DIR/if_same_then_else.rs:92:12 + --> $DIR/if_same_then_else.rs:93:12 | LL | } else { | ____________^ -LL | | //~ ERROR same body as `if` block LL | | 42 LL | | }; | |_____^ @@ -87,22 +87,22 @@ error: this `if` has identical blocks | LL | if true { | _____________^ +LL | | LL | | let bar = if true { 42 } else { 43 }; LL | | -LL | | while foo() { ... | LL | | bar + 1; LL | | } else { | |_____^ | note: same as this - --> $DIR/if_same_then_else.rs:104:12 + --> $DIR/if_same_then_else.rs:105:12 | LL | } else { | ____________^ -LL | | //~ ERROR same body as `if` block LL | | let bar = if true { 42 } else { 43 }; LL | | +LL | | while foo() { ... | LL | | bar + 1; LL | | } diff --git a/tests/ui/if_same_then_else2.rs b/tests/ui/if_same_then_else2.rs index 3b9b029d354..0b171f21d0c 100644 --- a/tests/ui/if_same_then_else2.rs +++ b/tests/ui/if_same_then_else2.rs @@ -13,6 +13,7 @@ fn if_same_then_else2() -> Result<&'static str, ()> { if true { + //~^ ERROR: this `if` has identical blocks for _ in &[42] { let foo: &Option<_> = &Some::(42); if foo.is_some() { @@ -22,7 +23,6 @@ fn if_same_then_else2() -> Result<&'static str, ()> { } } } else { - //~ ERROR same body as `if` block for _ in &[42] { let bar: &Option<_> = &Some::(42); if bar.is_some() { @@ -34,16 +34,16 @@ fn if_same_then_else2() -> Result<&'static str, ()> { } if true { + //~^ ERROR: this `if` has identical blocks if let Some(a) = Some(42) {} } else { - //~ ERROR same body as `if` block if let Some(a) = Some(42) {} } if true { + //~^ ERROR: this `if` has identical blocks if let (1, .., 3) = (1, 2, 3) {} } else { - //~ ERROR same body as `if` block if let (1, .., 3) = (1, 2, 3) {} } @@ -91,16 +91,16 @@ fn if_same_then_else2() -> Result<&'static str, ()> { // Same NaNs let _ = if true { + //~^ ERROR: this `if` has identical blocks f32::NAN } else { - //~ ERROR same body as `if` block f32::NAN }; if true { + //~^ ERROR: this `if` has identical blocks Ok("foo")?; } else { - //~ ERROR same body as `if` block Ok("foo")?; } @@ -122,6 +122,7 @@ fn if_same_then_else2() -> Result<&'static str, ()> { let foo = "bar"; return Ok(&foo[0..]); } else if true { + //~^ ERROR: this `if` has identical blocks let foo = ""; return Ok(&foo[0..]); } else { diff --git a/tests/ui/if_same_then_else2.stderr b/tests/ui/if_same_then_else2.stderr index a4d8a74167e..56e5f3e45b2 100644 --- a/tests/ui/if_same_then_else2.stderr +++ b/tests/ui/if_same_then_else2.stderr @@ -3,22 +3,22 @@ error: this `if` has identical blocks | LL | if true { | _____________^ +LL | | LL | | for _ in &[42] { LL | | let foo: &Option<_> = &Some::(42); -LL | | if foo.is_some() { ... | LL | | } LL | | } else { | |_____^ | note: same as this - --> $DIR/if_same_then_else2.rs:24:12 + --> $DIR/if_same_then_else2.rs:25:12 | LL | } else { | ____________^ -LL | | //~ ERROR same body as `if` block LL | | for _ in &[42] { LL | | let bar: &Option<_> = &Some::(42); +LL | | if bar.is_some() { ... | LL | | } LL | | } @@ -30,16 +30,16 @@ error: this `if` has identical blocks | LL | if true { | _____________^ +LL | | LL | | if let Some(a) = Some(42) {} LL | | } else { | |_____^ | note: same as this - --> $DIR/if_same_then_else2.rs:38:12 + --> $DIR/if_same_then_else2.rs:39:12 | LL | } else { | ____________^ -LL | | //~ ERROR same body as `if` block LL | | if let Some(a) = Some(42) {} LL | | } | |_____^ @@ -49,16 +49,16 @@ error: this `if` has identical blocks | LL | if true { | _____________^ +LL | | LL | | if let (1, .., 3) = (1, 2, 3) {} LL | | } else { | |_____^ | note: same as this - --> $DIR/if_same_then_else2.rs:45:12 + --> $DIR/if_same_then_else2.rs:46:12 | LL | } else { | ____________^ -LL | | //~ ERROR same body as `if` block LL | | if let (1, .., 3) = (1, 2, 3) {} LL | | } | |_____^ @@ -68,16 +68,16 @@ error: this `if` has identical blocks | LL | let _ = if true { | _____________________^ +LL | | LL | | f32::NAN LL | | } else { | |_____^ | note: same as this - --> $DIR/if_same_then_else2.rs:95:12 + --> $DIR/if_same_then_else2.rs:96:12 | LL | } else { | ____________^ -LL | | //~ ERROR same body as `if` block LL | | f32::NAN LL | | }; | |_____^ @@ -87,16 +87,16 @@ error: this `if` has identical blocks | LL | if true { | _____________^ +LL | | LL | | Ok("foo")?; LL | | } else { | |_____^ | note: same as this - --> $DIR/if_same_then_else2.rs:102:12 + --> $DIR/if_same_then_else2.rs:103:12 | LL | } else { | ____________^ -LL | | //~ ERROR same body as `if` block LL | | Ok("foo")?; LL | | } | |_____^ @@ -106,13 +106,14 @@ error: this `if` has identical blocks | LL | } else if true { | ____________________^ +LL | | LL | | let foo = ""; LL | | return Ok(&foo[0..]); LL | | } else { | |_____^ | note: same as this - --> $DIR/if_same_then_else2.rs:127:12 + --> $DIR/if_same_then_else2.rs:128:12 | LL | } else { | ____________^ diff --git a/tests/ui/ifs_same_cond.rs b/tests/ui/ifs_same_cond.rs index c321b08909f..5c338e3c5c8 100644 --- a/tests/ui/ifs_same_cond.rs +++ b/tests/ui/ifs_same_cond.rs @@ -12,18 +12,18 @@ fn ifs_same_cond() { if b { } else if b { - //~ ERROR ifs same condition + //~^ ERROR: this `if` has the same condition as a previous `if` } if a == 1 { } else if a == 1 { - //~ ERROR ifs same condition + //~^ ERROR: this `if` has the same condition as a previous `if` } if 2 * a == 1 { } else if 2 * a == 2 { } else if 2 * a == 1 { - //~ ERROR ifs same condition + //~^ ERROR: this `if` has the same condition as a previous `if` } else if a == 1 { } @@ -52,6 +52,7 @@ fn issue10272() { let a = String::from("ha"); if a.contains("ah") { } else if a.contains("ah") { + //~^ ERROR: this `if` has the same condition as a previous `if` // Trigger this lint } else if a.contains("ha") { } else if a == "wow" { diff --git a/tests/ui/implicit_hasher.rs b/tests/ui/implicit_hasher.rs index ca7c1221372..7ed7bf94a4b 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:proc-macro #![deny(clippy::implicit_hasher)] #![allow(unused)] diff --git a/tests/ui/inconsistent_struct_constructor.fixed b/tests/ui/inconsistent_struct_constructor.fixed index 620d45e6828..d84346e8789 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 +//@aux-build:proc_macros.rs:proc-macro #![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 10ffadcb2ba..87fba7448e3 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 +//@aux-build:proc_macros.rs:proc-macro #![warn(clippy::inconsistent_struct_constructor)] #![allow(clippy::redundant_field_names)] diff --git a/tests/ui/into_iter_on_ref.fixed b/tests/ui/into_iter_on_ref.fixed index 9f550acb157..af197e33fd8 100644 --- a/tests/ui/into_iter_on_ref.fixed +++ b/tests/ui/into_iter_on_ref.fixed @@ -11,35 +11,35 @@ fn main() { for _ in &vec![X, X] {} let _ = vec![1, 2, 3].into_iter(); - let _ = (&vec![1, 2, 3]).iter(); //~ WARN equivalent to .iter() - let _ = vec![1, 2, 3].into_boxed_slice().iter(); //~ WARN equivalent to .iter() - let _ = std::rc::Rc::from(&[X][..]).iter(); //~ WARN equivalent to .iter() - let _ = std::sync::Arc::from(&[X][..]).iter(); //~ WARN equivalent to .iter() + let _ = (&vec![1, 2, 3]).iter(); //~ ERROR: equivalent to `.iter() + let _ = vec![1, 2, 3].into_boxed_slice().iter(); //~ ERROR: equivalent to `.iter() + let _ = std::rc::Rc::from(&[X][..]).iter(); //~ ERROR: equivalent to `.iter() + let _ = std::sync::Arc::from(&[X][..]).iter(); //~ ERROR: equivalent to `.iter() - let _ = (&&&&&&&[1, 2, 3]).iter(); //~ ERROR equivalent to .iter() - let _ = (&&&&mut &&&[1, 2, 3]).iter(); //~ ERROR equivalent to .iter() - let _ = (&mut &mut &mut [1, 2, 3]).iter_mut(); //~ ERROR equivalent to .iter_mut() + let _ = (&&&&&&&[1, 2, 3]).iter(); //~ ERROR: equivalent to `.iter() + let _ = (&&&&mut &&&[1, 2, 3]).iter(); //~ ERROR: equivalent to `.iter() + let _ = (&mut &mut &mut [1, 2, 3]).iter_mut(); //~ ERROR: equivalent to `.iter_mut() - let _ = (&Some(4)).iter(); //~ WARN equivalent to .iter() - let _ = (&mut Some(5)).iter_mut(); //~ WARN equivalent to .iter_mut() - let _ = (&Ok::<_, i32>(6)).iter(); //~ WARN equivalent to .iter() - let _ = (&mut Err::(7)).iter_mut(); //~ WARN equivalent to .iter_mut() - let _ = (&Vec::::new()).iter(); //~ WARN equivalent to .iter() - let _ = (&mut Vec::::new()).iter_mut(); //~ WARN equivalent to .iter_mut() - let _ = (&BTreeMap::::new()).iter(); //~ WARN equivalent to .iter() - let _ = (&mut BTreeMap::::new()).iter_mut(); //~ WARN equivalent to .iter_mut() - let _ = (&VecDeque::::new()).iter(); //~ WARN equivalent to .iter() - let _ = (&mut VecDeque::::new()).iter_mut(); //~ WARN equivalent to .iter_mut() - let _ = (&LinkedList::::new()).iter(); //~ WARN equivalent to .iter() - let _ = (&mut LinkedList::::new()).iter_mut(); //~ WARN equivalent to .iter_mut() - let _ = (&HashMap::::new()).iter(); //~ WARN equivalent to .iter() - let _ = (&mut HashMap::::new()).iter_mut(); //~ WARN equivalent to .iter_mut() + let _ = (&Some(4)).iter(); //~ ERROR: equivalent to `.iter() + let _ = (&mut Some(5)).iter_mut(); //~ ERROR: equivalent to `.iter_mut() + let _ = (&Ok::<_, i32>(6)).iter(); //~ ERROR: equivalent to `.iter() + let _ = (&mut Err::(7)).iter_mut(); //~ ERROR: equivalent to `.iter_mut() + let _ = (&Vec::::new()).iter(); //~ ERROR: equivalent to `.iter() + let _ = (&mut Vec::::new()).iter_mut(); //~ ERROR: equivalent to `.iter_mut() + let _ = (&BTreeMap::::new()).iter(); //~ ERROR: equivalent to `.iter() + let _ = (&mut BTreeMap::::new()).iter_mut(); //~ ERROR: equivalent to `.iter_mut() + let _ = (&VecDeque::::new()).iter(); //~ ERROR: equivalent to `.iter() + let _ = (&mut VecDeque::::new()).iter_mut(); //~ ERROR: equivalent to `.iter_mut() + let _ = (&LinkedList::::new()).iter(); //~ ERROR: equivalent to `.iter() + let _ = (&mut LinkedList::::new()).iter_mut(); //~ ERROR: equivalent to `.iter_mut() + let _ = (&HashMap::::new()).iter(); //~ ERROR: equivalent to `.iter() + let _ = (&mut HashMap::::new()).iter_mut(); //~ ERROR: equivalent to `.iter_mut() - let _ = (&BTreeSet::::new()).iter(); //~ WARN equivalent to .iter() - let _ = (&BinaryHeap::::new()).iter(); //~ WARN equivalent to .iter() - let _ = (&HashSet::::new()).iter(); //~ WARN equivalent to .iter() - let _ = std::path::Path::new("12/34").iter(); //~ WARN equivalent to .iter() - let _ = std::path::PathBuf::from("12/34").iter(); //~ ERROR equivalent to .iter() + let _ = (&BTreeSet::::new()).iter(); //~ ERROR: equivalent to `.iter() + let _ = (&BinaryHeap::::new()).iter(); //~ ERROR: equivalent to `.iter() + let _ = (&HashSet::::new()).iter(); //~ ERROR: equivalent to `.iter() + let _ = std::path::Path::new("12/34").iter(); //~ ERROR: equivalent to `.iter() + let _ = std::path::PathBuf::from("12/34").iter(); //~ ERROR: equivalent to `.iter() - let _ = (&[1, 2, 3]).iter().next(); //~ WARN equivalent to .iter() + let _ = (&[1, 2, 3]).iter().next(); //~ ERROR: equivalent to `.iter() } diff --git a/tests/ui/into_iter_on_ref.rs b/tests/ui/into_iter_on_ref.rs index 3381ae04dce..3ac13d7dd3e 100644 --- a/tests/ui/into_iter_on_ref.rs +++ b/tests/ui/into_iter_on_ref.rs @@ -11,35 +11,35 @@ fn main() { for _ in &vec![X, X] {} let _ = vec![1, 2, 3].into_iter(); - let _ = (&vec![1, 2, 3]).into_iter(); //~ WARN equivalent to .iter() - let _ = vec![1, 2, 3].into_boxed_slice().into_iter(); //~ WARN equivalent to .iter() - let _ = std::rc::Rc::from(&[X][..]).into_iter(); //~ WARN equivalent to .iter() - let _ = std::sync::Arc::from(&[X][..]).into_iter(); //~ WARN equivalent to .iter() + let _ = (&vec![1, 2, 3]).into_iter(); //~ ERROR: equivalent to `.iter() + let _ = vec![1, 2, 3].into_boxed_slice().into_iter(); //~ ERROR: equivalent to `.iter() + let _ = std::rc::Rc::from(&[X][..]).into_iter(); //~ ERROR: equivalent to `.iter() + let _ = std::sync::Arc::from(&[X][..]).into_iter(); //~ ERROR: equivalent to `.iter() - let _ = (&&&&&&&[1, 2, 3]).into_iter(); //~ ERROR equivalent to .iter() - let _ = (&&&&mut &&&[1, 2, 3]).into_iter(); //~ ERROR equivalent to .iter() - let _ = (&mut &mut &mut [1, 2, 3]).into_iter(); //~ ERROR equivalent to .iter_mut() + let _ = (&&&&&&&[1, 2, 3]).into_iter(); //~ ERROR: equivalent to `.iter() + let _ = (&&&&mut &&&[1, 2, 3]).into_iter(); //~ ERROR: equivalent to `.iter() + let _ = (&mut &mut &mut [1, 2, 3]).into_iter(); //~ ERROR: equivalent to `.iter_mut() - let _ = (&Some(4)).into_iter(); //~ WARN equivalent to .iter() - let _ = (&mut Some(5)).into_iter(); //~ WARN equivalent to .iter_mut() - let _ = (&Ok::<_, i32>(6)).into_iter(); //~ WARN equivalent to .iter() - let _ = (&mut Err::(7)).into_iter(); //~ WARN equivalent to .iter_mut() - let _ = (&Vec::::new()).into_iter(); //~ WARN equivalent to .iter() - let _ = (&mut Vec::::new()).into_iter(); //~ WARN equivalent to .iter_mut() - let _ = (&BTreeMap::::new()).into_iter(); //~ WARN equivalent to .iter() - let _ = (&mut BTreeMap::::new()).into_iter(); //~ WARN equivalent to .iter_mut() - let _ = (&VecDeque::::new()).into_iter(); //~ WARN equivalent to .iter() - let _ = (&mut VecDeque::::new()).into_iter(); //~ WARN equivalent to .iter_mut() - let _ = (&LinkedList::::new()).into_iter(); //~ WARN equivalent to .iter() - let _ = (&mut LinkedList::::new()).into_iter(); //~ WARN equivalent to .iter_mut() - let _ = (&HashMap::::new()).into_iter(); //~ WARN equivalent to .iter() - let _ = (&mut HashMap::::new()).into_iter(); //~ WARN equivalent to .iter_mut() + let _ = (&Some(4)).into_iter(); //~ ERROR: equivalent to `.iter() + let _ = (&mut Some(5)).into_iter(); //~ ERROR: equivalent to `.iter_mut() + let _ = (&Ok::<_, i32>(6)).into_iter(); //~ ERROR: equivalent to `.iter() + let _ = (&mut Err::(7)).into_iter(); //~ ERROR: equivalent to `.iter_mut() + let _ = (&Vec::::new()).into_iter(); //~ ERROR: equivalent to `.iter() + let _ = (&mut Vec::::new()).into_iter(); //~ ERROR: equivalent to `.iter_mut() + let _ = (&BTreeMap::::new()).into_iter(); //~ ERROR: equivalent to `.iter() + let _ = (&mut BTreeMap::::new()).into_iter(); //~ ERROR: equivalent to `.iter_mut() + let _ = (&VecDeque::::new()).into_iter(); //~ ERROR: equivalent to `.iter() + let _ = (&mut VecDeque::::new()).into_iter(); //~ ERROR: equivalent to `.iter_mut() + let _ = (&LinkedList::::new()).into_iter(); //~ ERROR: equivalent to `.iter() + let _ = (&mut LinkedList::::new()).into_iter(); //~ ERROR: equivalent to `.iter_mut() + let _ = (&HashMap::::new()).into_iter(); //~ ERROR: equivalent to `.iter() + let _ = (&mut HashMap::::new()).into_iter(); //~ ERROR: equivalent to `.iter_mut() - let _ = (&BTreeSet::::new()).into_iter(); //~ WARN equivalent to .iter() - let _ = (&BinaryHeap::::new()).into_iter(); //~ WARN equivalent to .iter() - let _ = (&HashSet::::new()).into_iter(); //~ WARN equivalent to .iter() - let _ = std::path::Path::new("12/34").into_iter(); //~ WARN equivalent to .iter() - let _ = std::path::PathBuf::from("12/34").into_iter(); //~ ERROR equivalent to .iter() + let _ = (&BTreeSet::::new()).into_iter(); //~ ERROR: equivalent to `.iter() + let _ = (&BinaryHeap::::new()).into_iter(); //~ ERROR: equivalent to `.iter() + let _ = (&HashSet::::new()).into_iter(); //~ ERROR: equivalent to `.iter() + let _ = std::path::Path::new("12/34").into_iter(); //~ ERROR: equivalent to `.iter() + let _ = std::path::PathBuf::from("12/34").into_iter(); //~ ERROR: equivalent to `.iter() - let _ = (&[1, 2, 3]).into_iter().next(); //~ WARN equivalent to .iter() + let _ = (&[1, 2, 3]).into_iter().next(); //~ ERROR: equivalent to `.iter() } diff --git a/tests/ui/into_iter_on_ref.stderr b/tests/ui/into_iter_on_ref.stderr index 28003b365bb..06014a93f8c 100644 --- a/tests/ui/into_iter_on_ref.stderr +++ b/tests/ui/into_iter_on_ref.stderr @@ -1,7 +1,7 @@ error: this `.into_iter()` call is equivalent to `.iter()` and will not consume the `Vec` --> $DIR/into_iter_on_ref.rs:14:30 | -LL | let _ = (&vec![1, 2, 3]).into_iter(); //~ WARN equivalent to .iter() +LL | let _ = (&vec![1, 2, 3]).into_iter(); | ^^^^^^^^^ help: call directly: `iter` | = note: `-D clippy::into-iter-on-ref` implied by `-D warnings` @@ -9,157 +9,157 @@ LL | let _ = (&vec![1, 2, 3]).into_iter(); //~ WARN equivalent to .iter() error: this `.into_iter()` call is equivalent to `.iter()` and will not consume the `slice` --> $DIR/into_iter_on_ref.rs:15:46 | -LL | let _ = vec![1, 2, 3].into_boxed_slice().into_iter(); //~ WARN equivalent to .iter() +LL | let _ = vec![1, 2, 3].into_boxed_slice().into_iter(); | ^^^^^^^^^ help: call directly: `iter` error: this `.into_iter()` call is equivalent to `.iter()` and will not consume the `slice` --> $DIR/into_iter_on_ref.rs:16:41 | -LL | let _ = std::rc::Rc::from(&[X][..]).into_iter(); //~ WARN equivalent to .iter() +LL | let _ = std::rc::Rc::from(&[X][..]).into_iter(); | ^^^^^^^^^ help: call directly: `iter` error: this `.into_iter()` call is equivalent to `.iter()` and will not consume the `slice` --> $DIR/into_iter_on_ref.rs:17:44 | -LL | let _ = std::sync::Arc::from(&[X][..]).into_iter(); //~ WARN equivalent to .iter() +LL | let _ = std::sync::Arc::from(&[X][..]).into_iter(); | ^^^^^^^^^ help: call directly: `iter` error: this `.into_iter()` call is equivalent to `.iter()` and will not consume the `array` --> $DIR/into_iter_on_ref.rs:19:32 | -LL | let _ = (&&&&&&&[1, 2, 3]).into_iter(); //~ ERROR equivalent to .iter() +LL | let _ = (&&&&&&&[1, 2, 3]).into_iter(); | ^^^^^^^^^ help: call directly: `iter` error: this `.into_iter()` call is equivalent to `.iter()` and will not consume the `array` --> $DIR/into_iter_on_ref.rs:20:36 | -LL | let _ = (&&&&mut &&&[1, 2, 3]).into_iter(); //~ ERROR equivalent to .iter() +LL | let _ = (&&&&mut &&&[1, 2, 3]).into_iter(); | ^^^^^^^^^ help: call directly: `iter` error: this `.into_iter()` call is equivalent to `.iter_mut()` and will not consume the `array` --> $DIR/into_iter_on_ref.rs:21:40 | -LL | let _ = (&mut &mut &mut [1, 2, 3]).into_iter(); //~ ERROR equivalent to .iter_mut() +LL | let _ = (&mut &mut &mut [1, 2, 3]).into_iter(); | ^^^^^^^^^ help: call directly: `iter_mut` error: this `.into_iter()` call is equivalent to `.iter()` and will not consume the `Option` --> $DIR/into_iter_on_ref.rs:23:24 | -LL | let _ = (&Some(4)).into_iter(); //~ WARN equivalent to .iter() +LL | let _ = (&Some(4)).into_iter(); | ^^^^^^^^^ help: call directly: `iter` error: this `.into_iter()` call is equivalent to `.iter_mut()` and will not consume the `Option` --> $DIR/into_iter_on_ref.rs:24:28 | -LL | let _ = (&mut Some(5)).into_iter(); //~ WARN equivalent to .iter_mut() +LL | let _ = (&mut Some(5)).into_iter(); | ^^^^^^^^^ help: call directly: `iter_mut` error: this `.into_iter()` call is equivalent to `.iter()` and will not consume the `Result` --> $DIR/into_iter_on_ref.rs:25:32 | -LL | let _ = (&Ok::<_, i32>(6)).into_iter(); //~ WARN equivalent to .iter() +LL | let _ = (&Ok::<_, i32>(6)).into_iter(); | ^^^^^^^^^ help: call directly: `iter` error: this `.into_iter()` call is equivalent to `.iter_mut()` and will not consume the `Result` --> $DIR/into_iter_on_ref.rs:26:37 | -LL | let _ = (&mut Err::(7)).into_iter(); //~ WARN equivalent to .iter_mut() +LL | let _ = (&mut Err::(7)).into_iter(); | ^^^^^^^^^ help: call directly: `iter_mut` error: this `.into_iter()` call is equivalent to `.iter()` and will not consume the `Vec` --> $DIR/into_iter_on_ref.rs:27:34 | -LL | let _ = (&Vec::::new()).into_iter(); //~ WARN equivalent to .iter() +LL | let _ = (&Vec::::new()).into_iter(); | ^^^^^^^^^ help: call directly: `iter` error: this `.into_iter()` call is equivalent to `.iter_mut()` and will not consume the `Vec` --> $DIR/into_iter_on_ref.rs:28:38 | -LL | let _ = (&mut Vec::::new()).into_iter(); //~ WARN equivalent to .iter_mut() +LL | let _ = (&mut Vec::::new()).into_iter(); | ^^^^^^^^^ help: call directly: `iter_mut` error: this `.into_iter()` call is equivalent to `.iter()` and will not consume the `BTreeMap` --> $DIR/into_iter_on_ref.rs:29:44 | -LL | let _ = (&BTreeMap::::new()).into_iter(); //~ WARN equivalent to .iter() +LL | let _ = (&BTreeMap::::new()).into_iter(); | ^^^^^^^^^ help: call directly: `iter` error: this `.into_iter()` call is equivalent to `.iter_mut()` and will not consume the `BTreeMap` --> $DIR/into_iter_on_ref.rs:30:48 | -LL | let _ = (&mut BTreeMap::::new()).into_iter(); //~ WARN equivalent to .iter_mut() +LL | let _ = (&mut BTreeMap::::new()).into_iter(); | ^^^^^^^^^ help: call directly: `iter_mut` error: this `.into_iter()` call is equivalent to `.iter()` and will not consume the `VecDeque` --> $DIR/into_iter_on_ref.rs:31:39 | -LL | let _ = (&VecDeque::::new()).into_iter(); //~ WARN equivalent to .iter() +LL | let _ = (&VecDeque::::new()).into_iter(); | ^^^^^^^^^ help: call directly: `iter` error: this `.into_iter()` call is equivalent to `.iter_mut()` and will not consume the `VecDeque` --> $DIR/into_iter_on_ref.rs:32:43 | -LL | let _ = (&mut VecDeque::::new()).into_iter(); //~ WARN equivalent to .iter_mut() +LL | let _ = (&mut VecDeque::::new()).into_iter(); | ^^^^^^^^^ help: call directly: `iter_mut` error: this `.into_iter()` call is equivalent to `.iter()` and will not consume the `LinkedList` --> $DIR/into_iter_on_ref.rs:33:41 | -LL | let _ = (&LinkedList::::new()).into_iter(); //~ WARN equivalent to .iter() +LL | let _ = (&LinkedList::::new()).into_iter(); | ^^^^^^^^^ help: call directly: `iter` error: this `.into_iter()` call is equivalent to `.iter_mut()` and will not consume the `LinkedList` --> $DIR/into_iter_on_ref.rs:34:45 | -LL | let _ = (&mut LinkedList::::new()).into_iter(); //~ WARN equivalent to .iter_mut() +LL | let _ = (&mut LinkedList::::new()).into_iter(); | ^^^^^^^^^ help: call directly: `iter_mut` error: this `.into_iter()` call is equivalent to `.iter()` and will not consume the `HashMap` --> $DIR/into_iter_on_ref.rs:35:43 | -LL | let _ = (&HashMap::::new()).into_iter(); //~ WARN equivalent to .iter() +LL | let _ = (&HashMap::::new()).into_iter(); | ^^^^^^^^^ help: call directly: `iter` error: this `.into_iter()` call is equivalent to `.iter_mut()` and will not consume the `HashMap` --> $DIR/into_iter_on_ref.rs:36:47 | -LL | let _ = (&mut HashMap::::new()).into_iter(); //~ WARN equivalent to .iter_mut() +LL | let _ = (&mut HashMap::::new()).into_iter(); | ^^^^^^^^^ help: call directly: `iter_mut` error: this `.into_iter()` call is equivalent to `.iter()` and will not consume the `BTreeSet` --> $DIR/into_iter_on_ref.rs:38:39 | -LL | let _ = (&BTreeSet::::new()).into_iter(); //~ WARN equivalent to .iter() +LL | let _ = (&BTreeSet::::new()).into_iter(); | ^^^^^^^^^ help: call directly: `iter` error: this `.into_iter()` call is equivalent to `.iter()` and will not consume the `BinaryHeap` --> $DIR/into_iter_on_ref.rs:39:41 | -LL | let _ = (&BinaryHeap::::new()).into_iter(); //~ WARN equivalent to .iter() +LL | let _ = (&BinaryHeap::::new()).into_iter(); | ^^^^^^^^^ help: call directly: `iter` error: this `.into_iter()` call is equivalent to `.iter()` and will not consume the `HashSet` --> $DIR/into_iter_on_ref.rs:40:38 | -LL | let _ = (&HashSet::::new()).into_iter(); //~ WARN equivalent to .iter() +LL | let _ = (&HashSet::::new()).into_iter(); | ^^^^^^^^^ help: call directly: `iter` error: this `.into_iter()` call is equivalent to `.iter()` and will not consume the `Path` --> $DIR/into_iter_on_ref.rs:41:43 | -LL | let _ = std::path::Path::new("12/34").into_iter(); //~ WARN equivalent to .iter() +LL | let _ = std::path::Path::new("12/34").into_iter(); | ^^^^^^^^^ help: call directly: `iter` error: this `.into_iter()` call is equivalent to `.iter()` and will not consume the `PathBuf` --> $DIR/into_iter_on_ref.rs:42:47 | -LL | let _ = std::path::PathBuf::from("12/34").into_iter(); //~ ERROR equivalent to .iter() +LL | let _ = std::path::PathBuf::from("12/34").into_iter(); | ^^^^^^^^^ help: call directly: `iter` error: this `.into_iter()` call is equivalent to `.iter()` and will not consume the `array` --> $DIR/into_iter_on_ref.rs:44:26 | -LL | let _ = (&[1, 2, 3]).into_iter().next(); //~ WARN equivalent to .iter() +LL | let _ = (&[1, 2, 3]).into_iter().next(); | ^^^^^^^^^ help: call directly: `iter` error: aborting due to 27 previous errors diff --git a/tests/ui/issue-3145.rs b/tests/ui/issue-3145.rs index 586d13647d1..0b07de1144c 100644 --- a/tests/ui/issue-3145.rs +++ b/tests/ui/issue-3145.rs @@ -1,3 +1,3 @@ fn main() { - println!("{}" a); //~ERROR expected `,`, found `a` + println!("{}" a); //~ERROR: expected `,`, found `a` } diff --git a/tests/ui/issue-3145.stderr b/tests/ui/issue-3145.stderr index a35032aa150..d7c2c88a204 100644 --- a/tests/ui/issue-3145.stderr +++ b/tests/ui/issue-3145.stderr @@ -1,7 +1,7 @@ error: expected `,`, found `a` --> $DIR/issue-3145.rs:2:19 | -LL | println!("{}" a); //~ERROR expected `,`, found `a` +LL | println!("{}" a); | ^ expected `,` error: aborting due to previous error diff --git a/tests/ui/items_after_test_module/block_module.stderr b/tests/ui/items_after_test_module/block_module.stderr index 597f1b9510c..1b625747161 100644 --- a/tests/ui/items_after_test_module/block_module.stderr +++ b/tests/ui/items_after_test_module/block_module.stderr @@ -1,17 +1,2 @@ -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 +error: Option 'test' given more than once diff --git a/tests/ui/large_enum_variant.rs b/tests/ui/large_enum_variant.rs index ea8bc5b4aca..e677cc9a7b9 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:proc-macro #![allow(dead_code)] #![allow(unused_variables)] diff --git a/tests/ui/let_underscore_untyped.rs b/tests/ui/let_underscore_untyped.rs index 2c313ff35d5..431d83778e3 100644 --- a/tests/ui/let_underscore_untyped.rs +++ b/tests/ui/let_underscore_untyped.rs @@ -1,4 +1,4 @@ -//@aux-build: proc_macros.rs +//@aux-build: proc_macros.rs:proc-macro #![allow(unused)] #![warn(clippy::let_underscore_untyped)] diff --git a/tests/ui/let_with_type_underscore.rs b/tests/ui/let_with_type_underscore.rs index ae1a480bcfc..8214176cfd5 100644 --- a/tests/ui/let_with_type_underscore.rs +++ b/tests/ui/let_with_type_underscore.rs @@ -1,4 +1,4 @@ -//@aux-build: proc_macros.rs +//@aux-build: proc_macros.rs:proc-macro #![allow(unused)] #![warn(clippy::let_with_type_underscore)] #![allow(clippy::let_unit_value, clippy::needless_late_init)] diff --git a/tests/ui/macro_use_imports.fixed b/tests/ui/macro_use_imports.fixed index b4dabe3cae5..53b6a0250f9 100644 --- a/tests/ui/macro_use_imports.fixed +++ b/tests/ui/macro_use_imports.fixed @@ -1,6 +1,6 @@ //@aux-build:macro_rules.rs //@aux-build:macro_use_helper.rs -//@aux-build:proc_macro_derive.rs +//@aux-build:proc_macro_derive.rs:proc-macro //@run-rustfix //@ignore-32bit diff --git a/tests/ui/macro_use_imports.rs b/tests/ui/macro_use_imports.rs index 925a2c61f8d..a40fa389895 100644 --- a/tests/ui/macro_use_imports.rs +++ b/tests/ui/macro_use_imports.rs @@ -1,6 +1,6 @@ //@aux-build:macro_rules.rs //@aux-build:macro_use_helper.rs -//@aux-build:proc_macro_derive.rs +//@aux-build:proc_macro_derive.rs:proc-macro //@run-rustfix //@ignore-32bit diff --git a/tests/ui/macro_use_imports.stderr b/tests/ui/macro_use_imports.stderr index 6fd338cef86..67a833e85e0 100644 --- a/tests/ui/macro_use_imports.stderr +++ b/tests/ui/macro_use_imports.stderr @@ -1,17 +1,11 @@ error: `macro_use` attributes are no longer needed in the Rust 2018 edition - --> $DIR/macro_use_imports.rs:25:5 + --> $DIR/macro_use_imports.rs:19:5 | LL | #[macro_use] - | ^^^^^^^^^^^^ help: remove the attribute and import the macro directly, try: `use mac::inner::nested::string_add;` + | ^^^^^^^^^^^^ 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};` | = note: `-D clippy::macro-use-imports` implied by `-D warnings` -error: `macro_use` attributes are no longer needed in the Rust 2018 edition - --> $DIR/macro_use_imports.rs:21:5 - | -LL | #[macro_use] - | ^^^^^^^^^^^^ help: remove the attribute and import the macro directly, try: `use mini_mac::ClippyMiniMacroTest;` - error: `macro_use` attributes are no longer needed in the Rust 2018 edition --> $DIR/macro_use_imports.rs:23:5 | @@ -19,10 +13,16 @@ LL | #[macro_use] | ^^^^^^^^^^^^ help: remove the attribute and import the macro directly, try: `use mac::{inner::mut_mut, inner::try_err};` error: `macro_use` attributes are no longer needed in the Rust 2018 edition - --> $DIR/macro_use_imports.rs:19:5 + --> $DIR/macro_use_imports.rs:25:5 | LL | #[macro_use] - | ^^^^^^^^^^^^ 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};` + | ^^^^^^^^^^^^ help: remove the attribute and import the macro directly, try: `use mac::inner::nested::string_add;` + +error: `macro_use` attributes are no longer needed in the Rust 2018 edition + --> $DIR/macro_use_imports.rs:21:5 + | +LL | #[macro_use] + | ^^^^^^^^^^^^ help: remove the attribute and import the macro directly, try: `use mini_mac::ClippyMiniMacroTest;` error: aborting due to 4 previous errors diff --git a/tests/ui/macro_use_imports_expect.rs b/tests/ui/macro_use_imports_expect.rs index b9677851b92..3971aadbef8 100644 --- a/tests/ui/macro_use_imports_expect.rs +++ b/tests/ui/macro_use_imports_expect.rs @@ -1,6 +1,6 @@ //@aux-build:macro_rules.rs //@aux-build:macro_use_helper.rs -//@aux-build:proc_macro_derive.rs +//@aux-build:proc_macro_derive.rs:proc-macro //@ignore-32bit #![feature(lint_reasons)] diff --git a/tests/ui/manual_rem_euclid.fixed b/tests/ui/manual_rem_euclid.fixed index f2e44e56f02..594a76897bb 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 +//@aux-build:proc_macros.rs:proc-macro #![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 b2329c33a47..d5f98e71517 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 +//@aux-build:proc_macros.rs:proc-macro #![warn(clippy::manual_rem_euclid)] #![allow(clippy::let_with_type_underscore)] diff --git a/tests/ui/manual_slice_size_calculation.fixed b/tests/ui/manual_slice_size_calculation.fixed index ac85bd8d3ac..5b9629f4bc1 100644 --- a/tests/ui/manual_slice_size_calculation.fixed +++ b/tests/ui/manual_slice_size_calculation.fixed @@ -1,5 +1,5 @@ //@run-rustfix -//@aux-build:proc_macros.rs +//@aux-build:proc_macros.rs:proc-macro #![allow(unused)] #![warn(clippy::manual_slice_size_calculation)] diff --git a/tests/ui/manual_slice_size_calculation.rs b/tests/ui/manual_slice_size_calculation.rs index 1f824b12bc2..297887a9cfc 100644 --- a/tests/ui/manual_slice_size_calculation.rs +++ b/tests/ui/manual_slice_size_calculation.rs @@ -1,5 +1,5 @@ //@run-rustfix -//@aux-build:proc_macros.rs +//@aux-build:proc_macros.rs:proc-macro #![allow(unused)] #![warn(clippy::manual_slice_size_calculation)] diff --git a/tests/ui/match_same_arms.rs b/tests/ui/match_same_arms.rs index 3914b45464c..fad6a7db988 100644 --- a/tests/ui/match_same_arms.rs +++ b/tests/ui/match_same_arms.rs @@ -8,29 +8,30 @@ pub enum Abc { fn match_same_arms() { let _ = match Abc::A { - Abc::A => 0, + Abc::A => 0, //~ ERROR: this match arm has an identical body to the `_` wildcard arm Abc::B => 1, - _ => 0, //~ ERROR match arms have same body + _ => 0, }; match (1, 2, 3) { - (1, .., 3) => 42, - (.., 3) => 42, //~ ERROR match arms have same body + (1, .., 3) => 42, //~ ERROR: this match arm has an identical body to another arm + (.., 3) => 42, _ => 0, }; let _ = match 42 { 42 => 1, - 51 => 1, //~ ERROR match arms have same body - 41 => 2, - 52 => 2, //~ ERROR match arms have same body + 51 => 1, //~ ERROR: this match arm has an identical body to another arm + 41 => 2, //~ ERROR: this match arm has an identical body to another arm + 52 => 2, _ => 0, }; let _ = match 42 { 1 => 2, - 2 => 2, //~ ERROR 2nd matched arms have same body - 3 => 2, //~ ERROR 3rd matched arms have same body + 2 => 2, //~ ERROR: this match arm has an identical body to another arm + //~^ ERROR: this match arm has an identical body to another arm + 3 => 2, //~ ERROR: this match arm has an identical body to another arm 4 => 3, _ => 0, }; @@ -48,6 +49,7 @@ mod issue4244 { match self { CommandInfo::BuiltIn { name, .. } => name.to_string(), CommandInfo::External { name, .. } => name.to_string(), + //~^ ERROR: this match arm has an identical body to another arm } } } diff --git a/tests/ui/match_same_arms.stderr b/tests/ui/match_same_arms.stderr index db85b5964e8..88b9a20a372 100644 --- a/tests/ui/match_same_arms.stderr +++ b/tests/ui/match_same_arms.stderr @@ -8,7 +8,7 @@ LL | Abc::A => 0, note: `_` wildcard arm here --> $DIR/match_same_arms.rs:13:9 | -LL | _ => 0, //~ ERROR match arms have same body +LL | _ => 0, | ^^^^^^ = note: `-D clippy::match-same-arms` implied by `-D warnings` @@ -24,13 +24,13 @@ LL | (1, .., 3) => 42, note: other arm here --> $DIR/match_same_arms.rs:18:9 | -LL | (.., 3) => 42, //~ ERROR match arms have same body +LL | (.., 3) => 42, | ^^^^^^^^^^^^^ error: this match arm has an identical body to another arm --> $DIR/match_same_arms.rs:24:9 | -LL | 51 => 1, //~ ERROR match arms have same body +LL | 51 => 1, | --^^^^^ | | | help: try merging the arm patterns: `51 | 42` @@ -54,13 +54,13 @@ LL | 41 => 2, note: other arm here --> $DIR/match_same_arms.rs:26:9 | -LL | 52 => 2, //~ ERROR match arms have same body +LL | 52 => 2, | ^^^^^^^ error: this match arm has an identical body to another arm --> $DIR/match_same_arms.rs:32:9 | -LL | 2 => 2, //~ ERROR 2nd matched arms have same body +LL | 2 => 2, | -^^^^^ | | | help: try merging the arm patterns: `2 | 1` @@ -73,9 +73,9 @@ LL | 1 => 2, | ^^^^^^ error: this match arm has an identical body to another arm - --> $DIR/match_same_arms.rs:33:9 + --> $DIR/match_same_arms.rs:34:9 | -LL | 3 => 2, //~ ERROR 3rd matched arms have same body +LL | 3 => 2, | -^^^^^ | | | help: try merging the arm patterns: `3 | 1` @@ -90,20 +90,20 @@ LL | 1 => 2, error: this match arm has an identical body to another arm --> $DIR/match_same_arms.rs:32:9 | -LL | 2 => 2, //~ ERROR 2nd matched arms have same body +LL | 2 => 2, | -^^^^^ | | | help: try merging the arm patterns: `2 | 3` | = help: or try changing either arm body note: other arm here - --> $DIR/match_same_arms.rs:33:9 + --> $DIR/match_same_arms.rs:34:9 | -LL | 3 => 2, //~ ERROR 3rd matched arms have same body +LL | 3 => 2, | ^^^^^^ error: this match arm has an identical body to another arm - --> $DIR/match_same_arms.rs:50:17 + --> $DIR/match_same_arms.rs:51:17 | LL | CommandInfo::External { name, .. } => name.to_string(), | ----------------------------------^^^^^^^^^^^^^^^^^^^^ @@ -112,7 +112,7 @@ LL | CommandInfo::External { name, .. } => name.to_string(), | = help: or try changing either arm body note: other arm here - --> $DIR/match_same_arms.rs:49:17 + --> $DIR/match_same_arms.rs:50:17 | LL | CommandInfo::BuiltIn { name, .. } => name.to_string(), | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/match_same_arms2.rs b/tests/ui/match_same_arms2.rs index 60b2975be04..b1b9a6ae3e8 100644 --- a/tests/ui/match_same_arms2.rs +++ b/tests/ui/match_same_arms2.rs @@ -13,6 +13,7 @@ fn foo() -> bool { fn match_same_arms() { let _ = match 42 { 42 => { + //~^ ERROR: this match arm has an identical body to the `_` wildcard arm foo(); let mut a = 42 + [23].len() as i32; if true { @@ -22,7 +23,6 @@ fn match_same_arms() { a }, _ => { - //~ ERROR match arms have same body foo(); let mut a = 42 + [23].len() as i32; if true { @@ -35,13 +35,13 @@ fn match_same_arms() { let _ = match 42 { 42 => foo(), - 51 => foo(), //~ ERROR match arms have same body + 51 => foo(), //~ ERROR: this match arm has an identical body to another arm _ => true, }; let _ = match Some(42) { Some(_) => 24, - None => 24, //~ ERROR match arms have same body + None => 24, //~ ERROR: this match arm has an identical body to another arm }; let _ = match Some(42) { @@ -63,13 +63,13 @@ fn match_same_arms() { match (Some(42), Some(42)) { (Some(a), None) => bar(a), - (None, Some(a)) => bar(a), //~ ERROR match arms have same body + (None, Some(a)) => bar(a), //~ ERROR: this match arm has an identical body to another arm _ => (), } match (Some(42), Some(42)) { - (Some(a), ..) => bar(a), - (.., Some(a)) => bar(a), //~ ERROR match arms have same body + (Some(a), ..) => bar(a), //~ ERROR: this match arm has an identical body to another arm + (.., Some(a)) => bar(a), _ => (), } @@ -102,7 +102,7 @@ fn match_same_arms() { } match (x, Some(1i32)) { - (Ok(x), Some(_)) => println!("ok {}", x), + (Ok(x), Some(_)) => println!("ok {}", x), //~ ERROR: this match arm has an identical body to another arm (Ok(_), Some(x)) => println!("ok {}", x), _ => println!("err"), } @@ -118,7 +118,7 @@ fn match_same_arms() { match x { Ok(_tmp) => println!("ok"), Ok(3) => println!("ok"), - Ok(_) => println!("ok"), + Ok(_) => println!("ok"), //~ ERROR: this match arm has an identical body to another arm Err(_) => { unreachable!(); }, @@ -146,6 +146,7 @@ fn match_same_arms() { empty!(0); }, 1 => { + //~^ ERROR: this match arm has an identical body to another arm empty!(0); }, x => { @@ -195,7 +196,7 @@ fn main() { // Suggest moving `Foo::Z(_)` up. let _ = match Foo::X(0) { - Foo::X(0) => 1, + Foo::X(0) => 1, //~ ERROR: this match arm has an identical body to another arm Foo::X(_) | Foo::Y(_) => 2, Foo::Z(_) => 1, _ => 0, @@ -205,7 +206,7 @@ fn main() { let _ = match Foo::X(0) { Foo::X(0) => 1, Foo::Y(_) | Foo::Z(0) => 2, - Foo::Z(_) => 1, + Foo::Z(_) => 1, //~ ERROR: this match arm has an identical body to another arm _ => 0, }; @@ -228,7 +229,7 @@ fn main() { Some(Bar { x: 0, y: 5, .. }) => 1, Some(Bar { y: 10, z: 0, .. }) => 2, None => 50, - Some(Bar { y: 0, x: 5, .. }) => 1, + Some(Bar { y: 0, x: 5, .. }) => 1, //~ ERROR: this match arm has an identical body to another arm _ => 200, }; diff --git a/tests/ui/match_same_arms2.stderr b/tests/ui/match_same_arms2.stderr index 8fb461bd286..7f0c70745ac 100644 --- a/tests/ui/match_same_arms2.stderr +++ b/tests/ui/match_same_arms2.stderr @@ -2,9 +2,9 @@ error: this match arm has an identical body to the `_` wildcard arm --> $DIR/match_same_arms2.rs:15:9 | LL | / 42 => { +LL | | LL | | foo(); LL | | let mut a = 42 + [23].len() as i32; -LL | | if true { ... | LL | | a LL | | }, @@ -12,12 +12,12 @@ LL | | }, | = help: or try changing either arm body note: `_` wildcard arm here - --> $DIR/match_same_arms2.rs:24:9 + --> $DIR/match_same_arms2.rs:25:9 | LL | / _ => { -LL | | //~ ERROR match arms have same body LL | | foo(); LL | | let mut a = 42 + [23].len() as i32; +LL | | if true { ... | LL | | a LL | | }, @@ -27,7 +27,7 @@ LL | | }, error: this match arm has an identical body to another arm --> $DIR/match_same_arms2.rs:38:9 | -LL | 51 => foo(), //~ ERROR match arms have same body +LL | 51 => foo(), | --^^^^^^^^^ | | | help: try merging the arm patterns: `51 | 42` @@ -42,7 +42,7 @@ LL | 42 => foo(), error: this match arm has an identical body to another arm --> $DIR/match_same_arms2.rs:44:9 | -LL | None => 24, //~ ERROR match arms have same body +LL | None => 24, | ----^^^^^^ | | | help: try merging the arm patterns: `None | Some(_)` @@ -57,7 +57,7 @@ LL | Some(_) => 24, error: this match arm has an identical body to another arm --> $DIR/match_same_arms2.rs:66:9 | -LL | (None, Some(a)) => bar(a), //~ ERROR match arms have same body +LL | (None, Some(a)) => bar(a), | ---------------^^^^^^^^^^ | | | help: try merging the arm patterns: `(None, Some(a)) | (Some(a), None)` @@ -81,7 +81,7 @@ LL | (Some(a), ..) => bar(a), note: other arm here --> $DIR/match_same_arms2.rs:72:9 | -LL | (.., Some(a)) => bar(a), //~ ERROR match arms have same body +LL | (.., Some(a)) => bar(a), | ^^^^^^^^^^^^^^^^^^^^^^^ error: this match arm has an identical body to another arm @@ -121,6 +121,7 @@ LL | 1 => { | ^ help: try merging the arm patterns: `1 | 0` | _________| | | +LL | | LL | | empty!(0); LL | | }, | |_________^ @@ -135,7 +136,7 @@ LL | | }, | |_________^ error: match expression looks like `matches!` macro - --> $DIR/match_same_arms2.rs:166:16 + --> $DIR/match_same_arms2.rs:167:16 | LL | let _ans = match x { | ________________^ @@ -148,7 +149,7 @@ LL | | }; = note: `-D clippy::match-like-matches-macro` implied by `-D warnings` error: this match arm has an identical body to another arm - --> $DIR/match_same_arms2.rs:198:9 + --> $DIR/match_same_arms2.rs:199:9 | LL | Foo::X(0) => 1, | ---------^^^^^ @@ -157,13 +158,13 @@ LL | Foo::X(0) => 1, | = help: or try changing either arm body note: other arm here - --> $DIR/match_same_arms2.rs:200:9 + --> $DIR/match_same_arms2.rs:201:9 | LL | Foo::Z(_) => 1, | ^^^^^^^^^^^^^^ error: this match arm has an identical body to another arm - --> $DIR/match_same_arms2.rs:208:9 + --> $DIR/match_same_arms2.rs:209:9 | LL | Foo::Z(_) => 1, | ---------^^^^^ @@ -172,13 +173,13 @@ LL | Foo::Z(_) => 1, | = help: or try changing either arm body note: other arm here - --> $DIR/match_same_arms2.rs:206:9 + --> $DIR/match_same_arms2.rs:207:9 | LL | Foo::X(0) => 1, | ^^^^^^^^^^^^^^ error: this match arm has an identical body to another arm - --> $DIR/match_same_arms2.rs:231:9 + --> $DIR/match_same_arms2.rs:232:9 | LL | Some(Bar { y: 0, x: 5, .. }) => 1, | ----------------------------^^^^^ @@ -187,13 +188,13 @@ LL | Some(Bar { y: 0, x: 5, .. }) => 1, | = help: or try changing either arm body note: other arm here - --> $DIR/match_same_arms2.rs:228:9 + --> $DIR/match_same_arms2.rs:229:9 | LL | Some(Bar { x: 0, y: 5, .. }) => 1, | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: this match arm has an identical body to another arm - --> $DIR/match_same_arms2.rs:245:9 + --> $DIR/match_same_arms2.rs:246:9 | LL | 1 => cfg!(not_enable), | -^^^^^^^^^^^^^^^^^^^^ @@ -202,7 +203,7 @@ LL | 1 => cfg!(not_enable), | = help: or try changing either arm body note: other arm here - --> $DIR/match_same_arms2.rs:244:9 + --> $DIR/match_same_arms2.rs:245:9 | LL | 0 => cfg!(not_enable), | ^^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/mem_replace_macro.rs b/tests/ui/mem_replace_macro.rs index 132873858b7..e53342f2ed3 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:proc-macro #![warn(clippy::mem_replace_with_default)] extern crate proc_macros; diff --git a/tests/ui/min_ident_chars.rs b/tests/ui/min_ident_chars.rs index c5e03468ef9..b5b9e66aa7a 100644 --- a/tests/ui/min_ident_chars.rs +++ b/tests/ui/min_ident_chars.rs @@ -1,4 +1,4 @@ -//@aux-build:proc_macros.rs +//@aux-build:proc_macros.rs:proc-macro #![allow(irrefutable_let_patterns, nonstandard_style, unused)] #![warn(clippy::min_ident_chars)] diff --git a/tests/ui/missing_assert_message.rs b/tests/ui/missing_assert_message.rs index 89404ca8827..af1358f61b5 100644 --- a/tests/ui/missing_assert_message.rs +++ b/tests/ui/missing_assert_message.rs @@ -7,8 +7,6 @@ macro_rules! bar { }; } -fn main() {} - // Should trigger warning fn asserts_without_message() { assert!(foo()); @@ -66,9 +64,14 @@ fn asserts_without_message_but_inside_a_test_function() { debug_assert_ne!(foo(), foo()); } +fn foo() -> bool { + true +} + // Should not trigger warning #[cfg(test)] mod tests { + use super::foo; fn asserts_without_message_but_inside_a_test_module() { assert!(foo()); assert_eq!(foo(), foo()); @@ -78,7 +81,3 @@ mod tests { debug_assert_ne!(foo(), foo()); } } - -fn foo() -> bool { - true -} diff --git a/tests/ui/missing_assert_message.stderr b/tests/ui/missing_assert_message.stderr index ecd03801277..33a5c1f8e05 100644 --- a/tests/ui/missing_assert_message.stderr +++ b/tests/ui/missing_assert_message.stderr @@ -1,5 +1,5 @@ error: assert without any message - --> $DIR/missing_assert_message.rs:14:5 + --> $DIR/missing_assert_message.rs:12:5 | LL | assert!(foo()); | ^^^^^^^^^^^^^^ @@ -8,7 +8,7 @@ LL | assert!(foo()); = note: `-D clippy::missing-assert-message` implied by `-D warnings` error: assert without any message - --> $DIR/missing_assert_message.rs:15:5 + --> $DIR/missing_assert_message.rs:13:5 | LL | assert_eq!(foo(), foo()); | ^^^^^^^^^^^^^^^^^^^^^^^^ @@ -16,7 +16,7 @@ LL | assert_eq!(foo(), foo()); = help: consider describing why the failing assert is problematic error: assert without any message - --> $DIR/missing_assert_message.rs:16:5 + --> $DIR/missing_assert_message.rs:14:5 | LL | assert_ne!(foo(), foo()); | ^^^^^^^^^^^^^^^^^^^^^^^^ @@ -24,7 +24,7 @@ LL | assert_ne!(foo(), foo()); = help: consider describing why the failing assert is problematic error: assert without any message - --> $DIR/missing_assert_message.rs:17:5 + --> $DIR/missing_assert_message.rs:15:5 | LL | debug_assert!(foo()); | ^^^^^^^^^^^^^^^^^^^^ @@ -32,7 +32,7 @@ LL | debug_assert!(foo()); = help: consider describing why the failing assert is problematic error: assert without any message - --> $DIR/missing_assert_message.rs:18:5 + --> $DIR/missing_assert_message.rs:16:5 | LL | debug_assert_eq!(foo(), foo()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -40,7 +40,7 @@ LL | debug_assert_eq!(foo(), foo()); = help: consider describing why the failing assert is problematic error: assert without any message - --> $DIR/missing_assert_message.rs:19:5 + --> $DIR/missing_assert_message.rs:17:5 | LL | debug_assert_ne!(foo(), foo()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -48,7 +48,7 @@ LL | debug_assert_ne!(foo(), foo()); = help: consider describing why the failing assert is problematic error: assert without any message - --> $DIR/missing_assert_message.rs:24:5 + --> $DIR/missing_assert_message.rs:22:5 | LL | assert!(bar!(true)); | ^^^^^^^^^^^^^^^^^^^ @@ -56,7 +56,7 @@ LL | assert!(bar!(true)); = help: consider describing why the failing assert is problematic error: assert without any message - --> $DIR/missing_assert_message.rs:25:5 + --> $DIR/missing_assert_message.rs:23:5 | LL | assert!(bar!(true, false)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -64,7 +64,7 @@ LL | assert!(bar!(true, false)); = help: consider describing why the failing assert is problematic error: assert without any message - --> $DIR/missing_assert_message.rs:26:5 + --> $DIR/missing_assert_message.rs:24:5 | LL | assert_eq!(bar!(true), foo()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -72,7 +72,7 @@ LL | assert_eq!(bar!(true), foo()); = help: consider describing why the failing assert is problematic error: assert without any message - --> $DIR/missing_assert_message.rs:27:5 + --> $DIR/missing_assert_message.rs:25:5 | LL | assert_ne!(bar!(true, true), bar!(true)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -80,7 +80,7 @@ LL | assert_ne!(bar!(true, true), bar!(true)); = help: consider describing why the failing assert is problematic error: assert without any message - --> $DIR/missing_assert_message.rs:32:5 + --> $DIR/missing_assert_message.rs:30:5 | LL | assert!(foo(),); | ^^^^^^^^^^^^^^^ @@ -88,7 +88,7 @@ LL | assert!(foo(),); = help: consider describing why the failing assert is problematic error: assert without any message - --> $DIR/missing_assert_message.rs:33:5 + --> $DIR/missing_assert_message.rs:31:5 | LL | assert_eq!(foo(), foo(),); | ^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -96,7 +96,7 @@ LL | assert_eq!(foo(), foo(),); = help: consider describing why the failing assert is problematic error: assert without any message - --> $DIR/missing_assert_message.rs:34:5 + --> $DIR/missing_assert_message.rs:32:5 | LL | assert_ne!(foo(), foo(),); | ^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -104,7 +104,7 @@ LL | assert_ne!(foo(), foo(),); = help: consider describing why the failing assert is problematic error: assert without any message - --> $DIR/missing_assert_message.rs:35:5 + --> $DIR/missing_assert_message.rs:33:5 | LL | debug_assert!(foo(),); | ^^^^^^^^^^^^^^^^^^^^^ @@ -112,7 +112,7 @@ LL | debug_assert!(foo(),); = help: consider describing why the failing assert is problematic error: assert without any message - --> $DIR/missing_assert_message.rs:36:5 + --> $DIR/missing_assert_message.rs:34:5 | LL | debug_assert_eq!(foo(), foo(),); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -120,7 +120,7 @@ LL | debug_assert_eq!(foo(), foo(),); = help: consider describing why the failing assert is problematic error: assert without any message - --> $DIR/missing_assert_message.rs:37:5 + --> $DIR/missing_assert_message.rs:35:5 | LL | debug_assert_ne!(foo(), foo(),); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 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 abadf82fe4b..06e05352479 100644 --- a/tests/ui/missing_const_for_fn/cant_be_const.rs +++ b/tests/ui/missing_const_for_fn/cant_be_const.rs @@ -3,7 +3,7 @@ //! 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:../auxiliary/proc_macros.rs:proc-macro #![warn(clippy::missing_const_for_fn)] #![feature(start)] @@ -44,7 +44,6 @@ static Y: u32 = 0; // refer to a static variable fn get_y() -> u32 { Y - //~^ ERROR E0013 } // Don't lint entrypoint functions diff --git a/tests/ui/missing_doc.rs b/tests/ui/missing_doc.rs index bf587e774f7..cff1706a842 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 +//@aux-build: proc_macros.rs:proc-macro #![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 520ddbe16b8..2d45132f968 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:proc-macro #![warn(clippy::missing_docs_in_private_items)] #![allow(dead_code)] diff --git a/tests/ui/missing_inline_proc_macro.rs b/tests/ui/missing_inline_proc_macro.rs index 3c68fb905f1..e47a198c6ae 100644 --- a/tests/ui/missing_inline_proc_macro.rs +++ b/tests/ui/missing_inline_proc_macro.rs @@ -1,5 +1,4 @@ #![warn(clippy::missing_inline_in_public_items)] -#![crate_type = "proc-macro"] extern crate proc_macro; diff --git a/tests/ui/mistyped_literal_suffix.fixed b/tests/ui/mistyped_literal_suffix.fixed index 62cfeafdc49..9c2ffcb02ea 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 +//@aux-build: proc_macros.rs:proc-macro #![allow( dead_code, diff --git a/tests/ui/mistyped_literal_suffix.rs b/tests/ui/mistyped_literal_suffix.rs index f83b7c3dbda..a0a1e96a775 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 +//@aux-build: proc_macros.rs:proc-macro #![allow( dead_code, diff --git a/tests/ui/multiple_unsafe_ops_per_block.rs b/tests/ui/multiple_unsafe_ops_per_block.rs index 4ef6f0ca92f..23ad36bb473 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:proc-macro #![allow(unused)] #![allow(deref_nullptr)] #![allow(clippy::unnecessary_operation)] diff --git a/tests/ui/must_use_unit.fixed b/tests/ui/must_use_unit.fixed index 4f7cf4e56d1..c460fd7c6b0 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 +//@aux-build:proc_macros.rs:proc-macro #![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 3a814ce1685..fe95624f799 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 +//@aux-build:proc_macros.rs:proc-macro #![warn(clippy::must_use_unit)] #![allow(clippy::unused_unit)] diff --git a/tests/ui/mut_mut.rs b/tests/ui/mut_mut.rs index d838098de11..b7213428367 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:proc-macro #![warn(clippy::mut_mut)] #![allow(unused)] #![allow(clippy::no_effect, clippy::uninlined_format_args, clippy::unnecessary_operation)] diff --git a/tests/ui/needless_arbitrary_self_type_unfixable.rs b/tests/ui/needless_arbitrary_self_type_unfixable.rs index 00871f9f450..876f16a3854 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:proc-macro #![warn(clippy::needless_arbitrary_self_type)] diff --git a/tests/ui/needless_if.fixed b/tests/ui/needless_if.fixed index 8fd945f1a54..5e6e140c2db 100644 --- a/tests/ui/needless_if.fixed +++ b/tests/ui/needless_if.fixed @@ -1,5 +1,5 @@ //@run-rustfix -//@aux-build:proc_macros.rs +//@aux-build:proc_macros.rs:proc-macro #![feature(let_chains)] #![allow( clippy::blocks_in_if_conditions, diff --git a/tests/ui/needless_if.rs b/tests/ui/needless_if.rs index 04868299a54..eb28ce73be8 100644 --- a/tests/ui/needless_if.rs +++ b/tests/ui/needless_if.rs @@ -1,5 +1,5 @@ //@run-rustfix -//@aux-build:proc_macros.rs +//@aux-build:proc_macros.rs:proc-macro #![feature(let_chains)] #![allow( clippy::blocks_in_if_conditions, diff --git a/tests/ui/needless_late_init.fixed b/tests/ui/needless_late_init.fixed index b3ed0932ab5..933dd8bed2a 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 +//@aux-build:proc_macros.rs:proc-macro #![feature(let_chains)] #![allow(unused)] #![allow( diff --git a/tests/ui/needless_late_init.rs b/tests/ui/needless_late_init.rs index dbbbf24085e..ba3a04e0825 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 +//@aux-build:proc_macros.rs:proc-macro #![feature(let_chains)] #![allow(unused)] #![allow( diff --git a/tests/ui/needless_lifetimes.fixed b/tests/ui/needless_lifetimes.fixed index 7b99042f744..302a3f9edbe 100644 --- a/tests/ui/needless_lifetimes.fixed +++ b/tests/ui/needless_lifetimes.fixed @@ -1,5 +1,5 @@ //@run-rustfix -//@aux-build:proc_macros.rs +//@aux-build:proc_macros.rs:proc-macro #![warn(clippy::needless_lifetimes)] #![allow( diff --git a/tests/ui/needless_lifetimes.rs b/tests/ui/needless_lifetimes.rs index 6fcf1efc2ee..b15477c92e8 100644 --- a/tests/ui/needless_lifetimes.rs +++ b/tests/ui/needless_lifetimes.rs @@ -1,5 +1,5 @@ //@run-rustfix -//@aux-build:proc_macros.rs +//@aux-build:proc_macros.rs:proc-macro #![warn(clippy::needless_lifetimes)] #![allow( diff --git a/tests/ui/needless_pass_by_value_proc_macro.rs b/tests/ui/needless_pass_by_value_proc_macro.rs index 78a0e92d179..c603163c145 100644 --- a/tests/ui/needless_pass_by_value_proc_macro.rs +++ b/tests/ui/needless_pass_by_value_proc_macro.rs @@ -1,4 +1,3 @@ -#![crate_type = "proc-macro"] #![warn(clippy::needless_pass_by_value)] extern crate proc_macro; diff --git a/tests/ui/non_expressive_names.rs b/tests/ui/non_expressive_names.rs index 583096ac054..987a4775ef0 100644 --- a/tests/ui/non_expressive_names.rs +++ b/tests/ui/non_expressive_names.rs @@ -25,9 +25,9 @@ impl MaybeInst { } fn underscores_and_numbers() { - let _1 = 1; //~ERROR Consider a more descriptive name - let ____1 = 1; //~ERROR Consider a more descriptive name - let __1___2 = 12; //~ERROR Consider a more descriptive name + let _1 = 1; //~ERROR: consider choosing a more descriptive name + let ____1 = 1; //~ERROR: consider choosing a more descriptive name + let __1___2 = 12; //~ERROR: consider choosing a more descriptive name let _1_ok = 1; } @@ -48,9 +48,9 @@ struct Bar; impl Bar { fn bar() { - let _1 = 1; - let ____1 = 1; - let __1___2 = 12; + let _1 = 1; //~ERROR: consider choosing a more descriptive name + let ____1 = 1; //~ERROR: consider choosing a more descriptive name + let __1___2 = 12; //~ERROR: consider choosing a more descriptive name let _1_ok = 1; } } diff --git a/tests/ui/non_expressive_names.stderr b/tests/ui/non_expressive_names.stderr index 116d5da8729..b62748d4989 100644 --- a/tests/ui/non_expressive_names.stderr +++ b/tests/ui/non_expressive_names.stderr @@ -1,7 +1,7 @@ error: consider choosing a more descriptive name --> $DIR/non_expressive_names.rs:28:9 | -LL | let _1 = 1; //~ERROR Consider a more descriptive name +LL | let _1 = 1; | ^^ | = note: `-D clippy::just-underscores-and-digits` implied by `-D warnings` @@ -9,13 +9,13 @@ LL | let _1 = 1; //~ERROR Consider a more descriptive name error: consider choosing a more descriptive name --> $DIR/non_expressive_names.rs:29:9 | -LL | let ____1 = 1; //~ERROR Consider a more descriptive name +LL | let ____1 = 1; | ^^^^^ error: consider choosing a more descriptive name --> $DIR/non_expressive_names.rs:30:9 | -LL | let __1___2 = 12; //~ERROR Consider a more descriptive name +LL | let __1___2 = 12; | ^^^^^^^ error: consider choosing a more descriptive name diff --git a/tests/ui/non_octal_unix_permissions.fixed b/tests/ui/non_octal_unix_permissions.fixed index 89d12752834..5d0da8dce67 100644 --- a/tests/ui/non_octal_unix_permissions.fixed +++ b/tests/ui/non_octal_unix_permissions.fixed @@ -1,4 +1,4 @@ -//@ignore-windows +//@ignore-target-windows //@run-rustfix #![warn(clippy::non_octal_unix_permissions)] use std::fs::{DirBuilder, File, OpenOptions, Permissions}; diff --git a/tests/ui/non_octal_unix_permissions.rs b/tests/ui/non_octal_unix_permissions.rs index 1b3a322d726..04a3643050e 100644 --- a/tests/ui/non_octal_unix_permissions.rs +++ b/tests/ui/non_octal_unix_permissions.rs @@ -1,4 +1,4 @@ -//@ignore-windows +//@ignore-target-windows //@run-rustfix #![warn(clippy::non_octal_unix_permissions)] use std::fs::{DirBuilder, File, OpenOptions, Permissions}; diff --git a/tests/ui/octal_escapes.stderr b/tests/ui/octal_escapes.stderr index aa362e96321..63fdfe486e8 100644 --- a/tests/ui/octal_escapes.stderr +++ b/tests/ui/octal_escapes.stderr @@ -34,17 +34,17 @@ LL | let _bad2 = b"/x0033[0m"; error: octal-looking escape in string literal --> $DIR/octal_escapes.rs:6:17 | -LL | let _bad3 = "//033[0m"; +LL | let _bad3 = "///033[0m"; | ^^^^^^^^^^^ | = 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 _bad3 = "//x1b[0m"; +LL | let _bad3 = "///x1b[0m"; | ~~~~~~~~~~~ help: if the null character is intended, disambiguate using | -LL | let _bad3 = "//x0033[0m"; +LL | let _bad3 = "///x0033[0m"; | ~~~~~~~~~~~~~ error: octal-looking escape in string literal diff --git a/tests/ui/option_env_unwrap.rs b/tests/ui/option_env_unwrap.rs index ee1fe3f1fc0..65a1b467f81 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:proc-macro #![warn(clippy::option_env_unwrap)] #![allow(clippy::map_flatten)] diff --git a/tests/ui/print_with_newline.fixed b/tests/ui/print_with_newline.fixed new file mode 100644 index 00000000000..6098dea3991 --- /dev/null +++ b/tests/ui/print_with_newline.fixed @@ -0,0 +1,58 @@ +// 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)] + +fn main() { + println!("Hello"); + println!("Hello {}", "world"); + println!("Hello {} {}", "world", "#2"); + println!("{}", 1265); + println!(); + + // these are all fine + print!(""); + print!("Hello"); + println!("Hello"); + println!("Hello\n"); + println!("Hello {}\n", "world"); + print!("Issue\n{}", 1265); + print!("{}", 1265); + print!("\n{}", 1275); + print!("\n\n"); + print!("like eof\n\n"); + print!("Hello {} {}\n\n", "world", "#2"); + println!("\ndon't\nwarn\nfor\nmultiple\nnewlines\n"); // #3126 + println!("\nbla\n\n"); // #3126 + + // Escaping + print!("\\n"); // #3514 + println!("\\"); // should fail + print!("\\\\n"); + + // Raw strings + print!(r"\n"); // #3778 + + // Literal newlines should also fail + println!( + + ); + println!( + + ); + + // Don't warn on CRLF (#4208) + print!("\r\n"); + print!("foo\r\n"); + println!("\\r"); // should fail + print!("foo\rbar\n"); + + // Ignore expanded format strings + macro_rules! newline { + () => { + "\n" + }; + } + print!(newline!()); +} diff --git a/tests/ui/print_with_newline.rs b/tests/ui/print_with_newline.rs index ff79ca75ffa..d9c7acc2748 100644 --- a/tests/ui/print_with_newline.rs +++ b/tests/ui/print_with_newline.rs @@ -47,7 +47,7 @@ fn main() { // Don't warn on CRLF (#4208) print!("\r\n"); print!("foo\r\n"); - print!("\\r\n"); //~ ERROR + print!("\\r\n"); // should fail print!("foo\rbar\n"); // Ignore expanded format strings diff --git a/tests/ui/print_with_newline.stderr b/tests/ui/print_with_newline.stderr index b9f5675faec..b97711e777d 100644 --- a/tests/ui/print_with_newline.stderr +++ b/tests/ui/print_with_newline.stderr @@ -62,13 +62,13 @@ LL + println!(); error: using `print!()` with a format string that ends in a single newline --> $DIR/print_with_newline.rs:31:5 | -LL | print!("//n"); // should fail +LL | print!("///n"); // should fail | ^^^^^^^^^^^^^^ | help: use `println!` instead | -LL - print!("//n"); // should fail -LL + println!("/"); // should fail +LL - print!("///n"); // should fail +LL + println!("//"); // should fail | error: using `print!()` with a format string that ends in a single newline @@ -104,13 +104,13 @@ LL ~ error: using `print!()` with a format string that ends in a single newline --> $DIR/print_with_newline.rs:50:5 | -LL | print!("/r/n"); //~ ERROR +LL | print!("//r/n"); // should fail | ^^^^^^^^^^^^^^^ | help: use `println!` instead | -LL - print!("/r/n"); //~ ERROR -LL + println!("/r"); //~ ERROR +LL - print!("//r/n"); // should fail +LL + println!("//r"); // should fail | error: aborting due to 9 previous errors diff --git a/tests/ui/proc_macro.rs b/tests/ui/proc_macro.rs index 59914b8b8f6..b77874034d0 100644 --- a/tests/ui/proc_macro.rs +++ b/tests/ui/proc_macro.rs @@ -1,5 +1,4 @@ //! Check that we correctly lint procedural macros. -#![crate_type = "proc-macro"] extern crate proc_macro; diff --git a/tests/ui/proc_macro.stderr b/tests/ui/proc_macro.stderr index c795f6ad0d2..d912b502755 100644 --- a/tests/ui/proc_macro.stderr +++ b/tests/ui/proc_macro.stderr @@ -1,5 +1,5 @@ error: approximate value of `f{32, 64}::consts::PI` found - --> $DIR/proc_macro.rs:10:14 + --> $DIR/proc_macro.rs:9:14 | LL | let _x = 3.14; | ^^^^ diff --git a/tests/ui/ptr_as_ptr.fixed b/tests/ui/ptr_as_ptr.fixed index 2c2567d67cd..26a64c861cf 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 +//@aux-build:proc_macros.rs:proc-macro #![warn(clippy::ptr_as_ptr)] diff --git a/tests/ui/ptr_as_ptr.rs b/tests/ui/ptr_as_ptr.rs index 6000e5c08ac..ea40d494733 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 +//@aux-build:proc_macros.rs:proc-macro #![warn(clippy::ptr_as_ptr)] diff --git a/tests/ui/ptr_cast_constness.fixed b/tests/ui/ptr_cast_constness.fixed index ba3eca061df..1ef1809d153 100644 --- a/tests/ui/ptr_cast_constness.fixed +++ b/tests/ui/ptr_cast_constness.fixed @@ -1,5 +1,5 @@ //@run-rustfix -//@aux-build:proc_macros.rs +//@aux-build:proc_macros.rs:proc-macro #![warn(clippy::ptr_cast_constness)] #![allow(clippy::transmute_ptr_to_ref, clippy::unnecessary_cast, unused)] diff --git a/tests/ui/ptr_cast_constness.rs b/tests/ui/ptr_cast_constness.rs index adeb43edf68..2c15cd429da 100644 --- a/tests/ui/ptr_cast_constness.rs +++ b/tests/ui/ptr_cast_constness.rs @@ -1,5 +1,5 @@ //@run-rustfix -//@aux-build:proc_macros.rs +//@aux-build:proc_macros.rs:proc-macro #![warn(clippy::ptr_cast_constness)] #![allow(clippy::transmute_ptr_to_ref, clippy::unnecessary_cast, unused)] diff --git a/tests/ui/redundant_pub_crate.fixed b/tests/ui/redundant_pub_crate.fixed index f65c0fdd35d..a1ed491bbc6 100644 --- a/tests/ui/redundant_pub_crate.fixed +++ b/tests/ui/redundant_pub_crate.fixed @@ -14,7 +14,7 @@ mod m1 { } pub mod m1_2 { - // ^ private due to m1 + //:^ private due to m1 fn f() {} pub fn g() {} // private due to m1_2 and m1 pub fn h() {} @@ -39,7 +39,7 @@ pub(crate) mod m2 { } pub mod m2_2 { - // ^ already crate visible due to m2 + //:^ already crate visible due to m2 fn f() {} pub fn g() {} // already crate visible due to m2_2 and m2 pub fn h() {} @@ -64,7 +64,7 @@ pub mod m3 { } pub(crate) mod m3_2 { - // ^ ok + //:^ ok fn f() {} pub fn g() {} // already crate visible due to m3_2 pub fn h() {} @@ -89,7 +89,7 @@ mod m4 { } pub mod m4_2 { - // ^ private: not re-exported by `pub use m4::*` + //:^ private: not re-exported by `pub use m4::*` fn f() {} pub fn g() {} // private due to m4_2 pub fn h() {} diff --git a/tests/ui/redundant_pub_crate.rs b/tests/ui/redundant_pub_crate.rs index fb07fed98be..9accd297fc9 100644 --- a/tests/ui/redundant_pub_crate.rs +++ b/tests/ui/redundant_pub_crate.rs @@ -14,7 +14,7 @@ mod m1 { } pub(crate) mod m1_2 { - // ^ private due to m1 + //:^ private due to m1 fn f() {} pub(crate) fn g() {} // private due to m1_2 and m1 pub fn h() {} @@ -39,7 +39,7 @@ pub(crate) mod m2 { } pub(crate) mod m2_2 { - // ^ already crate visible due to m2 + //:^ already crate visible due to m2 fn f() {} pub(crate) fn g() {} // already crate visible due to m2_2 and m2 pub fn h() {} @@ -64,7 +64,7 @@ pub mod m3 { } pub(crate) mod m3_2 { - // ^ ok + //:^ ok fn f() {} pub(crate) fn g() {} // already crate visible due to m3_2 pub fn h() {} @@ -89,7 +89,7 @@ mod m4 { } pub(crate) mod m4_2 { - // ^ private: not re-exported by `pub use m4::*` + //:^ private: not re-exported by `pub use m4::*` fn f() {} pub(crate) fn g() {} // private due to m4_2 pub fn h() {} diff --git a/tests/ui/redundant_static_lifetimes.fixed b/tests/ui/redundant_static_lifetimes.fixed index 2651735d103..a83699ec68d 100644 --- a/tests/ui/redundant_static_lifetimes.fixed +++ b/tests/ui/redundant_static_lifetimes.fixed @@ -5,39 +5,39 @@ #[derive(Debug)] struct Foo; -const VAR_ONE: &str = "Test constant #1"; // ERROR Consider removing 'static. +const VAR_ONE: &str = "Test constant #1"; // ERROR: Consider removing 'static. const VAR_TWO: &str = "Test constant #2"; // This line should not raise a warning. -const VAR_THREE: &[&str] = &["one", "two"]; // ERROR Consider removing 'static +const VAR_THREE: &[&str] = &["one", "two"]; // ERROR: Consider removing 'static -const VAR_FOUR: (&str, (&str, &str), &str) = ("on", ("th", "th"), "on"); // ERROR Consider removing 'static +const VAR_FOUR: (&str, (&str, &str), &str) = ("on", ("th", "th"), "on"); // ERROR: Consider removing 'static const VAR_SIX: &u8 = &5; const VAR_HEIGHT: &Foo = &Foo {}; -const VAR_SLICE: &[u8] = b"Test constant #1"; // ERROR Consider removing 'static. +const VAR_SLICE: &[u8] = b"Test constant #1"; // ERROR: Consider removing 'static. -const VAR_TUPLE: &(u8, u8) = &(1, 2); // ERROR Consider removing 'static. +const VAR_TUPLE: &(u8, u8) = &(1, 2); // ERROR: Consider removing 'static. -const VAR_ARRAY: &[u8; 1] = b"T"; // ERROR Consider removing 'static. +const VAR_ARRAY: &[u8; 1] = b"T"; // ERROR: Consider removing 'static. -static STATIC_VAR_ONE: &str = "Test static #1"; // ERROR Consider removing 'static. +static STATIC_VAR_ONE: &str = "Test static #1"; // ERROR: Consider removing 'static. static STATIC_VAR_TWO: &str = "Test static #2"; // This line should not raise a warning. -static STATIC_VAR_THREE: &[&str] = &["one", "two"]; // ERROR Consider removing 'static +static STATIC_VAR_THREE: &[&str] = &["one", "two"]; // ERROR: Consider removing 'static static STATIC_VAR_SIX: &u8 = &5; static STATIC_VAR_HEIGHT: &Foo = &Foo {}; -static STATIC_VAR_SLICE: &[u8] = b"Test static #3"; // ERROR Consider removing 'static. +static STATIC_VAR_SLICE: &[u8] = b"Test static #3"; // ERROR: Consider removing 'static. -static STATIC_VAR_TUPLE: &(u8, u8) = &(1, 2); // ERROR Consider removing 'static. +static STATIC_VAR_TUPLE: &(u8, u8) = &(1, 2); // ERROR: Consider removing 'static. -static STATIC_VAR_ARRAY: &[u8; 1] = b"T"; // ERROR Consider removing 'static. +static STATIC_VAR_ARRAY: &[u8; 1] = b"T"; // ERROR: Consider removing 'static. static mut STATIC_MUT_SLICE: &mut [u32] = &mut [0]; diff --git a/tests/ui/redundant_static_lifetimes.rs b/tests/ui/redundant_static_lifetimes.rs index 7286652899d..b165cbaa3aa 100644 --- a/tests/ui/redundant_static_lifetimes.rs +++ b/tests/ui/redundant_static_lifetimes.rs @@ -5,39 +5,39 @@ #[derive(Debug)] struct Foo; -const VAR_ONE: &'static str = "Test constant #1"; // ERROR Consider removing 'static. +const VAR_ONE: &'static str = "Test constant #1"; // ERROR: Consider removing 'static. const VAR_TWO: &str = "Test constant #2"; // This line should not raise a warning. -const VAR_THREE: &[&'static str] = &["one", "two"]; // ERROR Consider removing 'static +const VAR_THREE: &[&'static str] = &["one", "two"]; // ERROR: Consider removing 'static -const VAR_FOUR: (&str, (&str, &'static str), &'static str) = ("on", ("th", "th"), "on"); // ERROR Consider removing 'static +const VAR_FOUR: (&str, (&str, &'static str), &'static str) = ("on", ("th", "th"), "on"); // ERROR: Consider removing 'static const VAR_SIX: &'static u8 = &5; const VAR_HEIGHT: &'static Foo = &Foo {}; -const VAR_SLICE: &'static [u8] = b"Test constant #1"; // ERROR Consider removing 'static. +const VAR_SLICE: &'static [u8] = b"Test constant #1"; // ERROR: Consider removing 'static. -const VAR_TUPLE: &'static (u8, u8) = &(1, 2); // ERROR Consider removing 'static. +const VAR_TUPLE: &'static (u8, u8) = &(1, 2); // ERROR: Consider removing 'static. -const VAR_ARRAY: &'static [u8; 1] = b"T"; // ERROR Consider removing 'static. +const VAR_ARRAY: &'static [u8; 1] = b"T"; // ERROR: Consider removing 'static. -static STATIC_VAR_ONE: &'static str = "Test static #1"; // ERROR Consider removing 'static. +static STATIC_VAR_ONE: &'static str = "Test static #1"; // ERROR: Consider removing 'static. static STATIC_VAR_TWO: &str = "Test static #2"; // This line should not raise a warning. -static STATIC_VAR_THREE: &[&'static str] = &["one", "two"]; // ERROR Consider removing 'static +static STATIC_VAR_THREE: &[&'static str] = &["one", "two"]; // ERROR: Consider removing 'static static STATIC_VAR_SIX: &'static u8 = &5; static STATIC_VAR_HEIGHT: &'static Foo = &Foo {}; -static STATIC_VAR_SLICE: &'static [u8] = b"Test static #3"; // ERROR Consider removing 'static. +static STATIC_VAR_SLICE: &'static [u8] = b"Test static #3"; // ERROR: Consider removing 'static. -static STATIC_VAR_TUPLE: &'static (u8, u8) = &(1, 2); // ERROR Consider removing 'static. +static STATIC_VAR_TUPLE: &'static (u8, u8) = &(1, 2); // ERROR: Consider removing 'static. -static STATIC_VAR_ARRAY: &'static [u8; 1] = b"T"; // ERROR Consider removing 'static. +static STATIC_VAR_ARRAY: &'static [u8; 1] = b"T"; // ERROR: Consider removing 'static. static mut STATIC_MUT_SLICE: &'static mut [u32] = &mut [0]; diff --git a/tests/ui/redundant_static_lifetimes.stderr b/tests/ui/redundant_static_lifetimes.stderr index b2cbd2d9d01..a13e5eadf15 100644 --- a/tests/ui/redundant_static_lifetimes.stderr +++ b/tests/ui/redundant_static_lifetimes.stderr @@ -1,7 +1,7 @@ error: constants have by default a `'static` lifetime --> $DIR/redundant_static_lifetimes.rs:8:17 | -LL | const VAR_ONE: &'static str = "Test constant #1"; // ERROR Consider removing 'static. +LL | const VAR_ONE: &'static str = "Test constant #1"; // ERROR: Consider removing 'static. | -^^^^^^^---- help: consider removing `'static`: `&str` | = note: `-D clippy::redundant-static-lifetimes` implied by `-D warnings` @@ -9,19 +9,19 @@ LL | const VAR_ONE: &'static str = "Test constant #1"; // ERROR Consider removin error: constants have by default a `'static` lifetime --> $DIR/redundant_static_lifetimes.rs:12:21 | -LL | const VAR_THREE: &[&'static str] = &["one", "two"]; // ERROR Consider removing 'static +LL | const VAR_THREE: &[&'static str] = &["one", "two"]; // ERROR: Consider removing 'static | -^^^^^^^---- help: consider removing `'static`: `&str` error: constants have by default a `'static` lifetime --> $DIR/redundant_static_lifetimes.rs:14:32 | -LL | const VAR_FOUR: (&str, (&str, &'static str), &'static str) = ("on", ("th", "th"), "on"); // ERROR Consider removing 'static +LL | const VAR_FOUR: (&str, (&str, &'static str), &'static str) = ("on", ("th", "th"), "on"); // ERROR: Consider removing 'static | -^^^^^^^---- help: consider removing `'static`: `&str` error: constants have by default a `'static` lifetime --> $DIR/redundant_static_lifetimes.rs:14:47 | -LL | const VAR_FOUR: (&str, (&str, &'static str), &'static str) = ("on", ("th", "th"), "on"); // ERROR Consider removing 'static +LL | const VAR_FOUR: (&str, (&str, &'static str), &'static str) = ("on", ("th", "th"), "on"); // ERROR: Consider removing 'static | -^^^^^^^---- help: consider removing `'static`: `&str` error: constants have by default a `'static` lifetime @@ -39,31 +39,31 @@ LL | const VAR_HEIGHT: &'static Foo = &Foo {}; error: constants have by default a `'static` lifetime --> $DIR/redundant_static_lifetimes.rs:20:19 | -LL | const VAR_SLICE: &'static [u8] = b"Test constant #1"; // ERROR Consider removing 'static. +LL | const VAR_SLICE: &'static [u8] = b"Test constant #1"; // ERROR: Consider removing 'static. | -^^^^^^^----- help: consider removing `'static`: `&[u8]` error: constants have by default a `'static` lifetime --> $DIR/redundant_static_lifetimes.rs:22:19 | -LL | const VAR_TUPLE: &'static (u8, u8) = &(1, 2); // ERROR Consider removing 'static. +LL | const VAR_TUPLE: &'static (u8, u8) = &(1, 2); // ERROR: Consider removing 'static. | -^^^^^^^--------- help: consider removing `'static`: `&(u8, u8)` error: constants have by default a `'static` lifetime --> $DIR/redundant_static_lifetimes.rs:24:19 | -LL | const VAR_ARRAY: &'static [u8; 1] = b"T"; // ERROR Consider removing 'static. +LL | const VAR_ARRAY: &'static [u8; 1] = b"T"; // ERROR: Consider removing 'static. | -^^^^^^^-------- help: consider removing `'static`: `&[u8; 1]` error: statics have by default a `'static` lifetime --> $DIR/redundant_static_lifetimes.rs:26:25 | -LL | static STATIC_VAR_ONE: &'static str = "Test static #1"; // ERROR Consider removing 'static. +LL | static STATIC_VAR_ONE: &'static str = "Test static #1"; // ERROR: Consider removing 'static. | -^^^^^^^---- help: consider removing `'static`: `&str` error: statics have by default a `'static` lifetime --> $DIR/redundant_static_lifetimes.rs:30:29 | -LL | static STATIC_VAR_THREE: &[&'static str] = &["one", "two"]; // ERROR Consider removing 'static +LL | static STATIC_VAR_THREE: &[&'static str] = &["one", "two"]; // ERROR: Consider removing 'static | -^^^^^^^---- help: consider removing `'static`: `&str` error: statics have by default a `'static` lifetime @@ -81,19 +81,19 @@ LL | static STATIC_VAR_HEIGHT: &'static Foo = &Foo {}; error: statics have by default a `'static` lifetime --> $DIR/redundant_static_lifetimes.rs:36:27 | -LL | static STATIC_VAR_SLICE: &'static [u8] = b"Test static #3"; // ERROR Consider removing 'static. +LL | static STATIC_VAR_SLICE: &'static [u8] = b"Test static #3"; // ERROR: Consider removing 'static. | -^^^^^^^----- help: consider removing `'static`: `&[u8]` error: statics have by default a `'static` lifetime --> $DIR/redundant_static_lifetimes.rs:38:27 | -LL | static STATIC_VAR_TUPLE: &'static (u8, u8) = &(1, 2); // ERROR Consider removing 'static. +LL | static STATIC_VAR_TUPLE: &'static (u8, u8) = &(1, 2); // ERROR: Consider removing 'static. | -^^^^^^^--------- help: consider removing `'static`: `&(u8, u8)` error: statics have by default a `'static` lifetime --> $DIR/redundant_static_lifetimes.rs:40:27 | -LL | static STATIC_VAR_ARRAY: &'static [u8; 1] = b"T"; // ERROR Consider removing 'static. +LL | static STATIC_VAR_ARRAY: &'static [u8; 1] = b"T"; // ERROR: Consider removing 'static. | -^^^^^^^-------- help: consider removing `'static`: `&[u8; 1]` error: statics have by default a `'static` lifetime diff --git a/tests/ui/redundant_static_lifetimes_multiple.rs b/tests/ui/redundant_static_lifetimes_multiple.rs index f57dd58e230..b3f263a7d66 100644 --- a/tests/ui/redundant_static_lifetimes_multiple.rs +++ b/tests/ui/redundant_static_lifetimes_multiple.rs @@ -1,12 +1,12 @@ // these are rustfixable, but run-rustfix tests cannot handle them -const VAR_FIVE: &'static [&[&'static str]] = &[&["test"], &["other one"]]; // ERROR Consider removing 'static +const VAR_FIVE: &'static [&[&'static str]] = &[&["test"], &["other one"]]; // ERROR: Consider removing 'static const VAR_SEVEN: &[&(&str, &'static [&'static str])] = &[&("one", &["other one"])]; -static STATIC_VAR_FOUR: (&str, (&str, &'static str), &'static str) = ("on", ("th", "th"), "on"); // ERROR Consider removing 'static +static STATIC_VAR_FOUR: (&str, (&str, &'static str), &'static str) = ("on", ("th", "th"), "on"); // ERROR: Consider removing 'static -static STATIC_VAR_FIVE: &'static [&[&'static str]] = &[&["test"], &["other one"]]; // ERROR Consider removing 'static +static STATIC_VAR_FIVE: &'static [&[&'static str]] = &[&["test"], &["other one"]]; // ERROR: Consider removing 'static static STATIC_VAR_SEVEN: &[&(&str, &'static [&'static str])] = &[&("one", &["other one"])]; diff --git a/tests/ui/redundant_static_lifetimes_multiple.stderr b/tests/ui/redundant_static_lifetimes_multiple.stderr index cc7e55a757a..4e7500903f8 100644 --- a/tests/ui/redundant_static_lifetimes_multiple.stderr +++ b/tests/ui/redundant_static_lifetimes_multiple.stderr @@ -1,7 +1,7 @@ error: constants have by default a `'static` lifetime --> $DIR/redundant_static_lifetimes_multiple.rs:3:18 | -LL | const VAR_FIVE: &'static [&[&'static str]] = &[&["test"], &["other one"]]; // ERROR Consider removing 'static +LL | const VAR_FIVE: &'static [&[&'static str]] = &[&["test"], &["other one"]]; // ERROR: Consider removing 'static | -^^^^^^^------------------ help: consider removing `'static`: `&[&[&'static str]]` | = note: `-D clippy::redundant-static-lifetimes` implied by `-D warnings` @@ -9,7 +9,7 @@ LL | const VAR_FIVE: &'static [&[&'static str]] = &[&["test"], &["other one"]]; error: constants have by default a `'static` lifetime --> $DIR/redundant_static_lifetimes_multiple.rs:3:30 | -LL | const VAR_FIVE: &'static [&[&'static str]] = &[&["test"], &["other one"]]; // ERROR Consider removing 'static +LL | const VAR_FIVE: &'static [&[&'static str]] = &[&["test"], &["other one"]]; // ERROR: Consider removing 'static | -^^^^^^^---- help: consider removing `'static`: `&str` error: constants have by default a `'static` lifetime @@ -27,25 +27,25 @@ LL | const VAR_SEVEN: &[&(&str, &'static [&'static str])] = &[&("one", &["other error: statics have by default a `'static` lifetime --> $DIR/redundant_static_lifetimes_multiple.rs:7:40 | -LL | static STATIC_VAR_FOUR: (&str, (&str, &'static str), &'static str) = ("on", ("th", "th"), "on"); // ERROR Consider removing 'static +LL | static STATIC_VAR_FOUR: (&str, (&str, &'static str), &'static str) = ("on", ("th", "th"), "on"); // ERROR: Consider removing 'static | -^^^^^^^---- help: consider removing `'static`: `&str` error: statics have by default a `'static` lifetime --> $DIR/redundant_static_lifetimes_multiple.rs:7:55 | -LL | static STATIC_VAR_FOUR: (&str, (&str, &'static str), &'static str) = ("on", ("th", "th"), "on"); // ERROR Consider removing 'static +LL | static STATIC_VAR_FOUR: (&str, (&str, &'static str), &'static str) = ("on", ("th", "th"), "on"); // ERROR: Consider removing 'static | -^^^^^^^---- help: consider removing `'static`: `&str` error: statics have by default a `'static` lifetime --> $DIR/redundant_static_lifetimes_multiple.rs:9:26 | -LL | static STATIC_VAR_FIVE: &'static [&[&'static str]] = &[&["test"], &["other one"]]; // ERROR Consider removing 'static +LL | static STATIC_VAR_FIVE: &'static [&[&'static str]] = &[&["test"], &["other one"]]; // ERROR: Consider removing 'static | -^^^^^^^------------------ help: consider removing `'static`: `&[&[&'static str]]` error: statics have by default a `'static` lifetime --> $DIR/redundant_static_lifetimes_multiple.rs:9:38 | -LL | static STATIC_VAR_FIVE: &'static [&[&'static str]] = &[&["test"], &["other one"]]; // ERROR Consider removing 'static +LL | static STATIC_VAR_FIVE: &'static [&[&'static str]] = &[&["test"], &["other one"]]; // ERROR: Consider removing 'static | -^^^^^^^---- help: consider removing `'static`: `&str` error: statics have by default a `'static` lifetime diff --git a/tests/ui/regex.stderr b/tests/ui/regex.stderr index 1e8a21283cd..c74dc8108fe 100644 --- a/tests/ui/regex.stderr +++ b/tests/ui/regex.stderr @@ -88,7 +88,7 @@ error: regex parse error: error: unrecognized escape sequence --> $DIR/regex.rs:42:42 | -LL | let escaped_string_span = Regex::new("/b/c"); +LL | let escaped_string_span = Regex::new("//b//c"); | ^^^^^^^^ | = help: consider using a raw string literal: `r".."` @@ -156,7 +156,7 @@ LL | let trivial_contains = Regex::new(NOT_A_REAL_REGEX); error: trivial regex --> $DIR/regex.rs:65:40 | -LL | let trivial_backslash = Regex::new("a/.b"); +LL | let trivial_backslash = Regex::new("a//.b"); | ^^^^^^^ | = help: consider using `str::contains` diff --git a/tests/ui/same_functions_in_if_condition.rs b/tests/ui/same_functions_in_if_condition.rs index aea1507cc5b..02e347ed9f6 100644 --- a/tests/ui/same_functions_in_if_condition.rs +++ b/tests/ui/same_functions_in_if_condition.rs @@ -35,33 +35,33 @@ fn ifs_same_cond_fn() { if function() { } else if function() { - //~ ERROR ifs same condition + //~^ ERROR: `if` has the same function call as a previous `if` } if fn_arg(a) { } else if fn_arg(a) { - //~ ERROR ifs same condition + //~^ ERROR: `if` has the same function call as a previous `if` } if obj.method() { } else if obj.method() { - //~ ERROR ifs same condition + //~^ ERROR: `if` has the same function call as a previous `if` } if obj.method_arg(a) { } else if obj.method_arg(a) { - //~ ERROR ifs same condition + //~^ ERROR: `if` has the same function call as a previous `if` } let mut v = vec![1]; if v.pop().is_none() { - //~ ERROR ifs same condition } else if v.pop().is_none() { + //~^ ERROR: `if` has the same function call as a previous `if` } if v.len() == 42 { - //~ ERROR ifs same condition } else if v.len() == 42 { + //~^ ERROR: `if` has the same function call as a previous `if` } if v.len() == 1 { diff --git a/tests/ui/same_functions_in_if_condition.stderr b/tests/ui/same_functions_in_if_condition.stderr index aade3b1fa45..d7b2d762db7 100644 --- a/tests/ui/same_functions_in_if_condition.stderr +++ b/tests/ui/same_functions_in_if_condition.stderr @@ -52,7 +52,7 @@ LL | if obj.method_arg(a) { | ^^^^^^^^^^^^^^^^^ error: this `if` has the same function call as a previous `if` - --> $DIR/same_functions_in_if_condition.rs:59:15 + --> $DIR/same_functions_in_if_condition.rs:58:15 | LL | } else if v.pop().is_none() { | ^^^^^^^^^^^^^^^^^ @@ -64,7 +64,7 @@ LL | if v.pop().is_none() { | ^^^^^^^^^^^^^^^^^ error: this `if` has the same function call as a previous `if` - --> $DIR/same_functions_in_if_condition.rs:64:15 + --> $DIR/same_functions_in_if_condition.rs:63:15 | LL | } else if v.len() == 42 { | ^^^^^^^^^^^^^ diff --git a/tests/ui/shadow.rs b/tests/ui/shadow.rs index c2895718a1a..9be8c5e59d0 100644 --- a/tests/ui/shadow.rs +++ b/tests/ui/shadow.rs @@ -1,4 +1,4 @@ -//@aux-build:proc_macro_derive.rs +//@aux-build:proc_macro_derive.rs:proc-macro #![warn(clippy::shadow_same, clippy::shadow_reuse, clippy::shadow_unrelated)] #![allow(clippy::let_unit_value, clippy::needless_if)] diff --git a/tests/ui/significant_drop_in_scrutinee.fixed b/tests/ui/significant_drop_in_scrutinee.fixed new file mode 100644 index 00000000000..acc78d6bb04 --- /dev/null +++ b/tests/ui/significant_drop_in_scrutinee.fixed @@ -0,0 +1,627 @@ +// 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)] + +use std::num::ParseIntError; +use std::ops::Deref; +use std::sync::atomic::{AtomicU64, Ordering}; +use std::sync::RwLock; +use std::sync::{Mutex, MutexGuard}; + +struct State {} + +impl State { + fn foo(&self) -> bool { + true + } + + fn bar(&self) {} +} + +fn should_not_trigger_lint_with_mutex_guard_outside_match() { + let mutex = Mutex::new(State {}); + + // Should not trigger lint because the temporary should drop at the `;` on line before the match + let is_foo = mutex.lock().unwrap().foo(); + match is_foo { + true => { + mutex.lock().unwrap().bar(); + }, + false => {}, + }; +} + +fn should_not_trigger_lint_with_mutex_guard_when_taking_ownership_in_match() { + let mutex = Mutex::new(State {}); + + // Should not trigger lint because the scrutinee is explicitly returning the MutexGuard, + // so its lifetime should not be surprising. + match mutex.lock() { + Ok(guard) => { + guard.foo(); + mutex.lock().unwrap().bar(); + }, + _ => {}, + }; +} + +fn should_trigger_lint_with_mutex_guard_in_match_scrutinee() { + let mutex = Mutex::new(State {}); + + // Should trigger lint because the lifetime of the temporary MutexGuard is surprising because it + // is preserved until the end of the match, but there is no clear indication that this is the + // case. + match mutex.lock().unwrap().foo() { + true => { + mutex.lock().unwrap().bar(); + }, + false => {}, + }; +} + +fn should_not_trigger_lint_with_mutex_guard_in_match_scrutinee_when_lint_allowed() { + let mutex = Mutex::new(State {}); + + // Lint should not be triggered because it is "allowed" below. + #[allow(clippy::significant_drop_in_scrutinee)] + match mutex.lock().unwrap().foo() { + true => { + mutex.lock().unwrap().bar(); + }, + false => {}, + }; +} + +fn should_not_trigger_lint_for_insignificant_drop() { + // Should not trigger lint because there are no temporaries whose drops have a significant + // side effect. + match 1u64.to_string().is_empty() { + true => { + println!("It was empty") + }, + false => { + println!("It was not empty") + }, + } +} + +struct StateWithMutex { + m: Mutex, +} + +struct MutexGuardWrapper<'a> { + mg: MutexGuard<'a, u64>, +} + +impl<'a> MutexGuardWrapper<'a> { + fn get_the_value(&self) -> u64 { + *self.mg.deref() + } +} + +struct MutexGuardWrapperWrapper<'a> { + mg: MutexGuardWrapper<'a>, +} + +impl<'a> MutexGuardWrapperWrapper<'a> { + fn get_the_value(&self) -> u64 { + *self.mg.mg.deref() + } +} + +impl StateWithMutex { + fn lock_m(&self) -> MutexGuardWrapper<'_> { + MutexGuardWrapper { + mg: self.m.lock().unwrap(), + } + } + + fn lock_m_m(&self) -> MutexGuardWrapperWrapper<'_> { + MutexGuardWrapperWrapper { + mg: MutexGuardWrapper { + mg: self.m.lock().unwrap(), + }, + } + } + + fn foo(&self) -> bool { + true + } + + fn bar(&self) {} +} + +fn should_trigger_lint_with_wrapped_mutex() { + let s = StateWithMutex { m: Mutex::new(1) }; + + // Should trigger lint because a temporary contains a type with a significant drop and its + // lifetime is not obvious. Additionally, it is not obvious from looking at the scrutinee that + // the temporary contains such a type, making it potentially even more surprising. + match s.lock_m().get_the_value() { + 1 => { + println!("Got 1. Is it still 1?"); + println!("{}", s.lock_m().get_the_value()); + }, + 2 => { + println!("Got 2. Is it still 2?"); + println!("{}", s.lock_m().get_the_value()); + }, + _ => {}, + } + println!("All done!"); +} + +fn should_trigger_lint_with_double_wrapped_mutex() { + let s = StateWithMutex { m: Mutex::new(1) }; + + // Should trigger lint because a temporary contains a type which further contains a type with a + // significant drop and its lifetime is not obvious. Additionally, it is not obvious from + // looking at the scrutinee that the temporary contains such a type, making it potentially even + // more surprising. + match s.lock_m_m().get_the_value() { + 1 => { + println!("Got 1. Is it still 1?"); + println!("{}", s.lock_m().get_the_value()); + }, + 2 => { + println!("Got 2. Is it still 2?"); + println!("{}", s.lock_m().get_the_value()); + }, + _ => {}, + } + println!("All done!"); +} + +struct Counter { + i: AtomicU64, +} + +#[clippy::has_significant_drop] +struct CounterWrapper<'a> { + counter: &'a Counter, +} + +impl<'a> CounterWrapper<'a> { + fn new(counter: &Counter) -> CounterWrapper { + counter.i.fetch_add(1, Ordering::Relaxed); + CounterWrapper { counter } + } +} + +impl<'a> Drop for CounterWrapper<'a> { + fn drop(&mut self) { + self.counter.i.fetch_sub(1, Ordering::Relaxed); + } +} + +impl Counter { + fn temp_increment(&self) -> Vec { + vec![CounterWrapper::new(self), CounterWrapper::new(self)] + } +} + +fn should_trigger_lint_for_vec() { + let counter = Counter { i: AtomicU64::new(0) }; + + // Should trigger lint because the temporary in the scrutinee returns a collection of types + // which have significant drops. The types with significant drops are also non-obvious when + // reading the expression in the scrutinee. + match counter.temp_increment().len() { + 2 => { + let current_count = counter.i.load(Ordering::Relaxed); + println!("Current count {}", current_count); + assert_eq!(current_count, 0); + }, + 1 => {}, + 3 => {}, + _ => {}, + }; +} + +struct StateWithField { + s: String, +} + +// Should trigger lint only on the type in the tuple which is created using a temporary +// with a significant drop. Additionally, this test ensures that the format of the tuple +// is preserved correctly in the suggestion. +fn should_trigger_lint_for_tuple_in_scrutinee() { + let mutex1 = Mutex::new(StateWithField { s: "one".to_owned() }); + + { + match (mutex1.lock().unwrap().s.len(), true) { + (3, _) => { + println!("started"); + mutex1.lock().unwrap().s.len(); + println!("done"); + }, + (_, _) => {}, + }; + + match (true, mutex1.lock().unwrap().s.len(), true) { + (_, 3, _) => { + println!("started"); + mutex1.lock().unwrap().s.len(); + println!("done"); + }, + (_, _, _) => {}, + }; + + let mutex2 = Mutex::new(StateWithField { s: "two".to_owned() }); + match (mutex1.lock().unwrap().s.len(), true, mutex2.lock().unwrap().s.len()) { + (3, _, 3) => { + println!("started"); + mutex1.lock().unwrap().s.len(); + mutex2.lock().unwrap().s.len(); + println!("done"); + }, + (_, _, _) => {}, + }; + + let mutex3 = Mutex::new(StateWithField { s: "three".to_owned() }); + match mutex3.lock().unwrap().s.as_str() { + "three" => { + println!("started"); + mutex1.lock().unwrap().s.len(); + mutex2.lock().unwrap().s.len(); + println!("done"); + }, + _ => {}, + }; + + match (true, mutex3.lock().unwrap().s.as_str()) { + (_, "three") => { + println!("started"); + mutex1.lock().unwrap().s.len(); + mutex2.lock().unwrap().s.len(); + println!("done"); + }, + (_, _) => {}, + }; + } +} + +// Should trigger lint when either side of a binary operation creates a temporary with a +// significant drop. +// To avoid potential unnecessary copies or creating references that would trigger the significant +// drop problem, the lint recommends moving the entire binary operation. +fn should_trigger_lint_for_accessing_field_in_mutex_in_one_side_of_binary_op() { + let mutex = Mutex::new(StateWithField { s: "state".to_owned() }); + + match mutex.lock().unwrap().s.len() > 1 { + true => { + mutex.lock().unwrap().s.len(); + }, + false => {}, + }; + + match 1 < mutex.lock().unwrap().s.len() { + true => { + mutex.lock().unwrap().s.len(); + }, + false => {}, + }; +} + +// Should trigger lint when both sides of a binary operation creates a temporary with a +// significant drop. +// To avoid potential unnecessary copies or creating references that would trigger the significant +// drop problem, the lint recommends moving the entire binary operation. +fn should_trigger_lint_for_accessing_fields_in_mutex_in_both_sides_of_binary_op() { + let mutex1 = Mutex::new(StateWithField { s: "state".to_owned() }); + let mutex2 = Mutex::new(StateWithField { + s: "statewithfield".to_owned(), + }); + + match mutex1.lock().unwrap().s.len() < mutex2.lock().unwrap().s.len() { + true => { + println!( + "{} < {}", + mutex1.lock().unwrap().s.len(), + mutex2.lock().unwrap().s.len() + ); + }, + false => {}, + }; + + match mutex1.lock().unwrap().s.len() >= mutex2.lock().unwrap().s.len() { + true => { + println!( + "{} >= {}", + mutex1.lock().unwrap().s.len(), + mutex2.lock().unwrap().s.len() + ); + }, + false => {}, + }; +} + +fn should_not_trigger_lint_for_closure_in_scrutinee() { + let mutex1 = Mutex::new(StateWithField { s: "one".to_owned() }); + + let get_mutex_guard = || mutex1.lock().unwrap().s.len(); + + // Should not trigger lint because the temporary with a significant drop will be dropped + // at the end of the closure, so the MutexGuard will be unlocked and not have a potentially + // surprising lifetime. + match get_mutex_guard() > 1 { + true => { + mutex1.lock().unwrap().s.len(); + }, + false => {}, + }; +} + +fn should_trigger_lint_for_return_from_closure_in_scrutinee() { + let mutex1 = Mutex::new(StateWithField { s: "one".to_owned() }); + + let get_mutex_guard = || mutex1.lock().unwrap(); + + // Should trigger lint because the temporary with a significant drop is returned from the + // closure but not used directly in any match arms, so it has a potentially surprising lifetime. + match get_mutex_guard().s.len() > 1 { + true => { + mutex1.lock().unwrap().s.len(); + }, + false => {}, + }; +} + +fn should_trigger_lint_for_return_from_match_in_scrutinee() { + let mutex1 = Mutex::new(StateWithField { s: "one".to_owned() }); + let mutex2 = Mutex::new(StateWithField { s: "two".to_owned() }); + + let i = 100; + + // Should trigger lint because the nested match within the scrutinee returns a temporary with a + // significant drop is but not used directly in any match arms, so it has a potentially + // surprising lifetime. + match match i { + 100 => mutex1.lock().unwrap(), + _ => mutex2.lock().unwrap(), + } + .s + .len() + > 1 + { + true => { + mutex1.lock().unwrap().s.len(); + }, + false => { + println!("nothing to do here"); + }, + }; +} + +fn should_trigger_lint_for_return_from_if_in_scrutinee() { + let mutex1 = Mutex::new(StateWithField { s: "one".to_owned() }); + let mutex2 = Mutex::new(StateWithField { s: "two".to_owned() }); + + let i = 100; + + // Should trigger lint because the nested if-expression within the scrutinee returns a temporary + // with a significant drop is but not used directly in any match arms, so it has a potentially + // surprising lifetime. + match if i > 1 { + mutex1.lock().unwrap() + } else { + mutex2.lock().unwrap() + } + .s + .len() + > 1 + { + true => { + mutex1.lock().unwrap().s.len(); + }, + false => {}, + }; +} + +fn should_not_trigger_lint_for_if_in_scrutinee() { + let mutex = Mutex::new(StateWithField { s: "state".to_owned() }); + + let i = 100; + + // Should not trigger the lint because the temporary with a significant drop *is* dropped within + // the body of the if-expression nested within the match scrutinee, and therefore does not have + // a potentially surprising lifetime. + match if i > 1 { + mutex.lock().unwrap().s.len() > 1 + } else { + false + } { + true => { + mutex.lock().unwrap().s.len(); + }, + false => {}, + }; +} + +struct StateWithBoxedMutexGuard { + u: Mutex, +} + +impl StateWithBoxedMutexGuard { + fn new() -> StateWithBoxedMutexGuard { + StateWithBoxedMutexGuard { u: Mutex::new(42) } + } + fn lock(&self) -> Box> { + Box::new(self.u.lock().unwrap()) + } +} + +fn should_trigger_lint_for_boxed_mutex_guard() { + let s = StateWithBoxedMutexGuard::new(); + + // Should trigger lint because a temporary Box holding a type with a significant drop in a match + // scrutinee may have a potentially surprising lifetime. + match s.lock().deref().deref() { + 0 | 1 => println!("Value was less than 2"), + _ => println!("Value is {}", s.lock().deref()), + }; +} + +struct StateStringWithBoxedMutexGuard { + s: Mutex, +} + +impl StateStringWithBoxedMutexGuard { + fn new() -> StateStringWithBoxedMutexGuard { + StateStringWithBoxedMutexGuard { + s: Mutex::new("A String".to_owned()), + } + } + fn lock(&self) -> Box> { + Box::new(self.s.lock().unwrap()) + } +} + +fn should_trigger_lint_for_boxed_mutex_guard_holding_string() { + let s = StateStringWithBoxedMutexGuard::new(); + + let matcher = String::from("A String"); + + // Should trigger lint because a temporary Box holding a type with a significant drop in a match + // scrutinee may have a potentially surprising lifetime. + match s.lock().deref().deref() { + matcher => println!("Value is {}", s.lock().deref()), + _ => println!("Value was not a match"), + }; +} + +struct StateWithIntField { + i: u64, +} + +// Should trigger lint when either side of an assign expression contains a temporary with a +// significant drop, because the temporary's lifetime will be extended to the end of the match. +// To avoid potential unnecessary copies or creating references that would trigger the significant +// drop problem, the lint recommends moving the entire binary operation. +fn should_trigger_lint_in_assign_expr() { + let mutex = Mutex::new(StateWithIntField { i: 10 }); + + let mut i = 100; + + match mutex.lock().unwrap().i = i { + _ => { + println!("{}", mutex.lock().unwrap().i); + }, + }; + + match i = mutex.lock().unwrap().i { + _ => { + println!("{}", mutex.lock().unwrap().i); + }, + }; + + match mutex.lock().unwrap().i += 1 { + _ => { + println!("{}", mutex.lock().unwrap().i); + }, + }; + + match i += mutex.lock().unwrap().i { + _ => { + println!("{}", mutex.lock().unwrap().i); + }, + }; +} + +#[derive(Debug)] +enum RecursiveEnum { + Foo(Option>), +} + +#[derive(Debug)] +enum GenericRecursiveEnum { + Foo(T, Option>>), +} + +fn should_not_cause_stack_overflow() { + // Test that when a type recursively contains itself, a stack overflow does not occur when + // checking sub-types for significant drops. + let f = RecursiveEnum::Foo(Some(Box::new(RecursiveEnum::Foo(None)))); + match f { + RecursiveEnum::Foo(Some(f)) => { + println!("{:?}", f) + }, + RecursiveEnum::Foo(f) => { + println!("{:?}", f) + }, + } + + let f = GenericRecursiveEnum::Foo(1u64, Some(Box::new(GenericRecursiveEnum::Foo(2u64, None)))); + match f { + GenericRecursiveEnum::Foo(i, Some(f)) => { + println!("{} {:?}", i, f) + }, + GenericRecursiveEnum::Foo(i, f) => { + println!("{} {:?}", i, f) + }, + } +} + +fn should_not_produce_lint_for_try_desugar() -> Result { + // TryDesugar (i.e. using `?` for a Result type) will turn into a match but is out of scope + // for this lint + let rwlock = RwLock::new("1".to_string()); + let result = rwlock.read().unwrap().parse::()?; + println!("{}", result); + rwlock.write().unwrap().push('2'); + Ok(result) +} + +struct ResultReturner { + s: String, +} + +impl ResultReturner { + fn to_number(&self) -> Result { + self.s.parse::() + } +} + +fn should_trigger_lint_for_non_ref_move_and_clone_suggestion() { + let rwlock = RwLock::::new(ResultReturner { s: "1".to_string() }); + match rwlock.read().unwrap().to_number() { + Ok(n) => println!("Converted to number: {}", n), + Err(e) => println!("Could not convert {} to number", e), + }; +} + +fn should_trigger_lint_for_read_write_lock_for_loop() { + // For-in loops desugar to match expressions and are prone to the type of deadlock this lint is + // designed to look for. + let rwlock = RwLock::>::new(vec!["1".to_string()]); + for s in rwlock.read().unwrap().iter() { + println!("{}", s); + } +} + +fn do_bar(mutex: &Mutex) { + mutex.lock().unwrap().bar(); +} + +fn should_trigger_lint_without_significant_drop_in_arm() { + let mutex = Mutex::new(State {}); + + // Should trigger lint because the lifetime of the temporary MutexGuard is surprising because it + // is preserved until the end of the match, but there is no clear indication that this is the + // case. + match mutex.lock().unwrap().foo() { + true => do_bar(&mutex), + false => {}, + }; +} + +fn should_not_trigger_on_significant_iterator_drop() { + let lines = std::io::stdin().lines(); + for line in lines { + println!("foo: {}", line.unwrap()); + } +} + +fn main() {} diff --git a/tests/ui/single_call_fn.rs b/tests/ui/single_call_fn.rs index bfb773187fb..76e175014b8 100644 --- a/tests/ui/single_call_fn.rs +++ b/tests/ui/single_call_fn.rs @@ -1,5 +1,4 @@ -//@aux-build:proc_macros.rs -//@compile-flags: --test +//@aux-build:proc_macros.rs:proc-macro #![allow(clippy::redundant_closure_call, unused)] #![warn(clippy::single_call_fn)] #![no_main] diff --git a/tests/ui/single_call_fn.stderr b/tests/ui/single_call_fn.stderr index bb92e3cf71a..9ef8c487844 100644 --- a/tests/ui/single_call_fn.stderr +++ b/tests/ui/single_call_fn.stderr @@ -1,5 +1,5 @@ error: this function is only used once - --> $DIR/single_call_fn.rs:34:1 + --> $DIR/single_call_fn.rs:33:1 | LL | / fn c() { LL | | println!("really"); @@ -9,44 +9,44 @@ LL | | } | |_^ | help: used here - --> $DIR/single_call_fn.rs:41:5 + --> $DIR/single_call_fn.rs:40:5 | LL | c(); | ^ = note: `-D clippy::single-call-fn` implied by `-D warnings` error: this function is only used once - --> $DIR/single_call_fn.rs:13:1 + --> $DIR/single_call_fn.rs:12:1 | LL | fn i() {} | ^^^^^^^^^ | help: used here - --> $DIR/single_call_fn.rs:18:13 + --> $DIR/single_call_fn.rs:17:13 | LL | let a = i; | ^ error: this function is only used once - --> $DIR/single_call_fn.rs:44:1 + --> $DIR/single_call_fn.rs:43:1 | LL | fn a() {} | ^^^^^^^^^ | help: used here - --> $DIR/single_call_fn.rs:47:5 + --> $DIR/single_call_fn.rs:46:5 | LL | a(); | ^ error: this function is only used once - --> $DIR/single_call_fn.rs:14:1 + --> $DIR/single_call_fn.rs:13:1 | LL | fn j() {} | ^^^^^^^^^ | help: used here - --> $DIR/single_call_fn.rs:25:9 + --> $DIR/single_call_fn.rs:24:9 | LL | j(); | ^ diff --git a/tests/ui/single_char_pattern.stderr b/tests/ui/single_char_pattern.stderr index 5564aac674d..5ae2450c226 100644 --- a/tests/ui/single_char_pattern.stderr +++ b/tests/ui/single_char_pattern.stderr @@ -226,13 +226,13 @@ error: single-character string constant used as pattern --> $DIR/single_char_pattern.rs:65:13 | LL | x.split(r#"/"#); - | ^^^^^^ help: try using a `char` instead: `'/'` + | ^^^^^^ help: try using a `char` instead: `'//'` error: single-character string constant used as pattern --> $DIR/single_char_pattern.rs:66:13 | LL | x.split(r"/"); - | ^^^^ help: try using a `char` instead: `'/'` + | ^^^^ help: try using a `char` instead: `'//'` error: aborting due to 39 previous errors diff --git a/tests/ui/single_match_else.fixed b/tests/ui/single_match_else.fixed index f88498655a4..fcc8f14803d 100644 --- a/tests/ui/single_match_else.fixed +++ b/tests/ui/single_match_else.fixed @@ -1,5 +1,5 @@ //@run-rustfix -//@aux-build: proc_macros.rs +//@aux-build: proc_macros.rs:proc-macro #![warn(clippy::single_match_else)] #![allow(unused, clippy::needless_return, clippy::no_effect, clippy::uninlined_format_args)] extern crate proc_macros; diff --git a/tests/ui/single_match_else.rs b/tests/ui/single_match_else.rs index b34b9553919..77afd58a08d 100644 --- a/tests/ui/single_match_else.rs +++ b/tests/ui/single_match_else.rs @@ -1,5 +1,5 @@ //@run-rustfix -//@aux-build: proc_macros.rs +//@aux-build: proc_macros.rs:proc-macro #![warn(clippy::single_match_else)] #![allow(unused, clippy::needless_return, clippy::no_effect, clippy::uninlined_format_args)] extern crate proc_macros; diff --git a/tests/ui/single_range_in_vec_init.rs b/tests/ui/single_range_in_vec_init.rs index abf784e0f0e..833e1c43bfc 100644 --- a/tests/ui/single_range_in_vec_init.rs +++ b/tests/ui/single_range_in_vec_init.rs @@ -1,4 +1,4 @@ -//@aux-build:proc_macros.rs +//@aux-build:proc_macros.rs:proc-macro #![allow(clippy::no_effect, clippy::useless_vec, unused)] #![warn(clippy::single_range_in_vec_init)] #![feature(generic_arg_infer)] @@ -39,8 +39,8 @@ fn main() { [0.0..200.0]; vec![0.0..200.0]; // `Copy` is not implemented for `Range`, so this doesn't matter - // [0..200; 2]; - // [vec!0..200; 2]; + // FIXME: [0..200; 2]; + // FIXME: [vec!0..200; 2]; // Unfortunately skips any macros a!(); diff --git a/tests/ui/string_add.rs b/tests/ui/string_add.rs index de78dfe4d69..6980242ae72 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:proc-macro extern crate proc_macros; use proc_macros::external; diff --git a/tests/ui/suspicious_else_formatting.rs b/tests/ui/suspicious_else_formatting.rs index c0856427eae..0473ccdc3f6 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:proc-macro #![warn(clippy::suspicious_else_formatting)] #![allow( diff --git a/tests/ui/tests_outside_test_module.rs b/tests/ui/tests_outside_test_module.rs index 21fdfdf9005..d53c692b78e 100644 --- a/tests/ui/tests_outside_test_module.rs +++ b/tests/ui/tests_outside_test_module.rs @@ -1,4 +1,3 @@ -//@compile-flags: --test #![allow(unused)] #![warn(clippy::tests_outside_test_module)] diff --git a/tests/ui/tests_outside_test_module.stderr b/tests/ui/tests_outside_test_module.stderr index 125a79d6edf..71c649c5d27 100644 --- a/tests/ui/tests_outside_test_module.stderr +++ b/tests/ui/tests_outside_test_module.stderr @@ -1,5 +1,5 @@ error: this function marked with #[test] is outside a #[cfg(test)] module - --> $DIR/tests_outside_test_module.rs:11:1 + --> $DIR/tests_outside_test_module.rs:10:1 | LL | fn my_test() {} | ^^^^^^^^^^^^^^^ diff --git a/tests/ui/toplevel_ref_arg.fixed b/tests/ui/toplevel_ref_arg.fixed index 4bacf9efdae..9ad45c7a817 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 +//@aux-build:proc_macros.rs:proc-macro #![warn(clippy::toplevel_ref_arg)] #![allow(clippy::uninlined_format_args, unused, clippy::useless_vec)] diff --git a/tests/ui/toplevel_ref_arg.rs b/tests/ui/toplevel_ref_arg.rs index 723870ccc80..45ccc024cbd 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 +//@aux-build:proc_macros.rs:proc-macro #![warn(clippy::toplevel_ref_arg)] #![allow(clippy::uninlined_format_args, unused, clippy::useless_vec)] diff --git a/tests/ui/toplevel_ref_arg_non_rustfix.rs b/tests/ui/toplevel_ref_arg_non_rustfix.rs index 8aaf47b1bd0..464762af825 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:proc-macro #![warn(clippy::toplevel_ref_arg)] #![allow(unused)] diff --git a/tests/ui/transmute_ptr_to_ptr.rs b/tests/ui/transmute_ptr_to_ptr.rs index f06ffab5d9b..61a6c98ed5a 100644 --- a/tests/ui/transmute_ptr_to_ptr.rs +++ b/tests/ui/transmute_ptr_to_ptr.rs @@ -32,7 +32,7 @@ fn transmute_ptr_to_ptr() { // ref-ref transmutes; bad let _: &f32 = std::mem::transmute(&1u32); let _: &f64 = std::mem::transmute(&1f32); - // ^ this test is here because both f32 and f64 are the same TypeVariant, but they are not + //:^ this test is here because both f32 and f64 are the same TypeVariant, but they are not // the same type let _: &mut f32 = std::mem::transmute(&mut 1u32); let _: &GenericParam = std::mem::transmute(&GenericParam { t: 1u32 }); diff --git a/tests/ui/try_err.fixed b/tests/ui/try_err.fixed index dc773ad4bad..1816740870a 100644 --- a/tests/ui/try_err.fixed +++ b/tests/ui/try_err.fixed @@ -1,5 +1,5 @@ //@run-rustfix -//@aux-build:proc_macros.rs +//@aux-build:proc_macros.rs:proc-macro #![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 7a7433a7ec2..0e47c4d023e 100644 --- a/tests/ui/try_err.rs +++ b/tests/ui/try_err.rs @@ -1,5 +1,5 @@ //@run-rustfix -//@aux-build:proc_macros.rs +//@aux-build:proc_macros.rs:proc-macro #![deny(clippy::try_err)] #![allow(clippy::unnecessary_wraps, clippy::needless_question_mark)] diff --git a/tests/ui/undocumented_unsafe_blocks.rs b/tests/ui/undocumented_unsafe_blocks.rs index f4e7f1943ae..a9cc4295435 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:proc-macro #![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 910968afa7f..032040c4805 100644 --- a/tests/ui/unicode.fixed +++ b/tests/ui/unicode.fixed @@ -1,5 +1,4 @@ //@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 bc4b84d3435..dd215bc6048 100644 --- a/tests/ui/unicode.rs +++ b/tests/ui/unicode.rs @@ -1,5 +1,4 @@ //@run-rustfix -//@compile-flags: --test #![allow(dead_code)] #[warn(clippy::invisible_characters)] diff --git a/tests/ui/unicode.stderr b/tests/ui/unicode.stderr index ea74a81451e..21cc22a778b 100644 --- a/tests/ui/unicode.stderr +++ b/tests/ui/unicode.stderr @@ -1,5 +1,5 @@ error: invisible character detected - --> $DIR/unicode.rs:7:12 + --> $DIR/unicode.rs:6:12 | LL | print!("Here >​< is a ZWS, and ​another"); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider replacing the string with: `"Here >/u{200B}< is a ZWS, and /u{200B}another"` @@ -7,19 +7,19 @@ LL | print!("Here >​< is a ZWS, and ​another"); = note: `-D clippy::invisible-characters` implied by `-D warnings` error: invisible character detected - --> $DIR/unicode.rs:9:12 + --> $DIR/unicode.rs:8:12 | LL | print!("Here >­< is a SHY, and ­another"); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider replacing the string with: `"Here >/u{AD}< is a SHY, and /u{AD}another"` error: invisible character detected - --> $DIR/unicode.rs:11:12 + --> $DIR/unicode.rs:10:12 | LL | print!("Here >⁠< is a WJ, and ⁠another"); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider replacing the string with: `"Here >/u{2060}< is a WJ, and /u{2060}another"` error: non-NFC Unicode sequence detected - --> $DIR/unicode.rs:17:12 + --> $DIR/unicode.rs:16:12 | LL | print!("̀àh?"); | ^^^^^ help: consider replacing the string with: `"̀àh?"` @@ -27,37 +27,37 @@ LL | print!("̀àh?"); = note: `-D clippy::unicode-not-nfc` implied by `-D warnings` error: literal non-ASCII character detected - --> $DIR/unicode.rs:25:16 + --> $DIR/unicode.rs:24:16 | LL | print!("Üben!"); | ^^^^^^^ help: consider replacing the string with: `"/u{dc}ben!"` | note: the lint level is defined here - --> $DIR/unicode.rs:22:13 + --> $DIR/unicode.rs:21:13 | LL | #![deny(clippy::non_ascii_literal)] | ^^^^^^^^^^^^^^^^^^^^^^^^^ error: literal non-ASCII character detected - --> $DIR/unicode.rs:31:36 + --> $DIR/unicode.rs:30:36 | LL | const _EMPTY_BLOCK: char = '▱'; | ^^^ help: consider replacing the string with: `'/u{25b1}'` error: literal non-ASCII character detected - --> $DIR/unicode.rs:32:35 + --> $DIR/unicode.rs:31:35 | LL | const _FULL_BLOCK: char = '▰'; | ^^^ help: consider replacing the string with: `'/u{25b0}'` error: literal non-ASCII character detected - --> $DIR/unicode.rs:52:21 + --> $DIR/unicode.rs:51:21 | LL | let _ = "悲しいかな、ここに日本語を書くことはできない。"; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider replacing the string with: `"/u{60b2}/u{3057}/u{3044}/u{304b}/u{306a}/u{3001}/u{3053}/u{3053}/u{306b}/u{65e5}/u{672c}/u{8a9e}/u{3092}/u{66f8}/u{304f}/u{3053}/u{3068}/u{306f}/u{3067}/u{304d}/u{306a}/u{3044}/u{3002}"` | note: the lint level is defined here - --> $DIR/unicode.rs:41:17 + --> $DIR/unicode.rs:40:17 | LL | #![deny(clippy::non_ascii_literal)] | ^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/uninlined_format_args.fixed b/tests/ui/uninlined_format_args.fixed index 972e0356b62..a042731a9bf 100644 --- a/tests/ui/uninlined_format_args.fixed +++ b/tests/ui/uninlined_format_args.fixed @@ -1,4 +1,4 @@ -//@aux-build:proc_macros.rs +//@aux-build:proc_macros.rs:proc-macro //@run-rustfix #![warn(clippy::uninlined_format_args)] #![allow(named_arguments_used_positionally, unused)] diff --git a/tests/ui/uninlined_format_args.rs b/tests/ui/uninlined_format_args.rs index 7614ffb38e6..d830b74d607 100644 --- a/tests/ui/uninlined_format_args.rs +++ b/tests/ui/uninlined_format_args.rs @@ -1,4 +1,4 @@ -//@aux-build:proc_macros.rs +//@aux-build:proc_macros.rs:proc-macro //@run-rustfix #![warn(clippy::uninlined_format_args)] #![allow(named_arguments_used_positionally, unused)] diff --git a/tests/ui/unit_arg.rs b/tests/ui/unit_arg.rs index d082063c8e8..fded8db5daf 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:proc-macro #![warn(clippy::unit_arg)] #![allow(unused_must_use, unused_variables)] #![allow( diff --git a/tests/ui/unnecessary_lazy_eval.fixed b/tests/ui/unnecessary_lazy_eval.fixed index 75a42809ad2..dca38034177 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 +//@aux-build: proc_macros.rs:proc-macro #![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 3777b9c25c2..7fda719edc1 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 +//@aux-build: proc_macros.rs:proc-macro #![warn(clippy::unnecessary_lazy_evaluations)] #![allow(clippy::redundant_closure)] #![allow(clippy::bind_instead_of_map)] diff --git a/tests/ui/unnecessary_unsafety_doc.rs b/tests/ui/unnecessary_unsafety_doc.rs index 373b18470f6..2d55dc664a3 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:proc-macro #![allow(clippy::let_unit_value)] #![warn(clippy::unnecessary_safety_doc)] diff --git a/tests/ui/unseparated_prefix_literals.fixed b/tests/ui/unseparated_prefix_literals.fixed index b6241612d9d..12512087267 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 +//@aux-build:proc_macro_derive.rs:proc-macro #![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 ae583f4bde3..0a3ffc4784b 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 +//@aux-build:proc_macro_derive.rs:proc-macro #![warn(clippy::unseparated_literal_suffix)] #![allow(dead_code)] diff --git a/tests/ui/update-all-references.sh b/tests/ui/update-all-references.sh index 4391499a1e1..d4204307026 100755 --- a/tests/ui/update-all-references.sh +++ b/tests/ui/update-all-references.sh @@ -1,3 +1,3 @@ #!/bin/bash -echo "Please use 'cargo dev bless' instead." +echo "Please use 'cargo bless' instead." diff --git a/tests/ui/use_self.fixed b/tests/ui/use_self.fixed index 89ea14759b7..4179f21c510 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 +//@aux-build:proc_macro_derive.rs:proc-macro #![warn(clippy::use_self)] #![allow(dead_code, unreachable_code)] diff --git a/tests/ui/use_self.rs b/tests/ui/use_self.rs index 49e5bcb7ed9..01a36def9e9 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 +//@aux-build:proc_macro_derive.rs:proc-macro #![warn(clippy::use_self)] #![allow(dead_code, unreachable_code)] diff --git a/tests/ui/used_underscore_binding.rs b/tests/ui/used_underscore_binding.rs index c672eff1c27..879e2e24ab3 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:proc-macro #![feature(rustc_private)] #![warn(clippy::all)] #![warn(clippy::used_underscore_binding)] diff --git a/tests/ui/useless_attribute.fixed b/tests/ui/useless_attribute.fixed index de6660c95e6..8e77ec444b5 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 +//@aux-build:proc_macro_derive.rs:proc-macro #![allow(unused)] #![warn(clippy::useless_attribute)] diff --git a/tests/ui/useless_attribute.rs b/tests/ui/useless_attribute.rs index 8de4331e8a6..27498d9bc13 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 +//@aux-build:proc_macro_derive.rs:proc-macro #![allow(unused)] #![warn(clippy::useless_attribute)] diff --git a/tests/ui/wildcard_imports.fixed b/tests/ui/wildcard_imports.fixed index 733bbcfbcef..2961b062ec3 100644 --- a/tests/ui/wildcard_imports.fixed +++ b/tests/ui/wildcard_imports.fixed @@ -211,7 +211,7 @@ mod super_imports { } mod use_explicit_should_be_replaced { - use super_imports::foofoo; + use crate::super_imports::foofoo; fn with_explicit() { let _ = foofoo(); diff --git a/tests/ui/wildcard_imports.rs b/tests/ui/wildcard_imports.rs index 4acdd374bde..28508a2538b 100644 --- a/tests/ui/wildcard_imports.rs +++ b/tests/ui/wildcard_imports.rs @@ -212,7 +212,7 @@ mod super_imports { } mod use_explicit_should_be_replaced { - use super_imports::*; + use crate::super_imports::*; fn with_explicit() { let _ = foofoo(); diff --git a/tests/ui/wildcard_imports.stderr b/tests/ui/wildcard_imports.stderr index 235be2d5708..c96b3041a00 100644 --- a/tests/ui/wildcard_imports.stderr +++ b/tests/ui/wildcard_imports.stderr @@ -107,8 +107,8 @@ LL | use super::*; error: usage of wildcard import --> $DIR/wildcard_imports.rs:215:13 | -LL | use super_imports::*; - | ^^^^^^^^^^^^^^^^ help: try: `super_imports::foofoo` +LL | use crate::super_imports::*; + | ^^^^^^^^^^^^^^^^^^^^^^^ help: try: `crate::super_imports::foofoo` error: usage of wildcard import --> $DIR/wildcard_imports.rs:224:17 diff --git a/tests/ui/write_literal_2.stderr b/tests/ui/write_literal_2.stderr index d5956db9ff0..bf22738480d 100644 --- a/tests/ui/write_literal_2.stderr +++ b/tests/ui/write_literal_2.stderr @@ -87,7 +87,7 @@ LL | "1", "2", "3", help: try this | LL ~ "some 1/ -LL ~ {} / {}", "2", "3", +LL ~ {} // {}", "2", "3", | error: literal with an empty format string @@ -98,7 +98,7 @@ LL | "1", "2", "3", | help: try this | -LL ~ 2 / {}", +LL ~ 2 // {}", LL ~ "1", "3", | @@ -110,43 +110,43 @@ LL | "1", "2", "3", | help: try this | -LL ~ {} / 3", +LL ~ {} // 3", LL ~ "1", "2", | error: literal with an empty format string --> $DIR/write_literal_2.rs:27:23 | -LL | writeln!(v, "{}", "/"); +LL | writeln!(v, "{}", "//"); | ^^^^ | help: try this | -LL - writeln!(v, "{}", "/"); -LL + writeln!(v, "/"); +LL - writeln!(v, "{}", "//"); +LL + writeln!(v, "//"); | error: literal with an empty format string --> $DIR/write_literal_2.rs:28:24 | -LL | writeln!(v, r"{}", "/"); +LL | writeln!(v, r"{}", "//"); | ^^^^ | help: try this | -LL - writeln!(v, r"{}", "/"); +LL - writeln!(v, r"{}", "//"); LL + writeln!(v, r"/"); | error: literal with an empty format string --> $DIR/write_literal_2.rs:29:26 | -LL | writeln!(v, r#"{}"#, "/"); +LL | writeln!(v, r#"{}"#, "//"); | ^^^^ | help: try this | -LL - writeln!(v, r#"{}"#, "/"); +LL - writeln!(v, r#"{}"#, "//"); LL + writeln!(v, r#"/"#); | @@ -159,7 +159,7 @@ LL | writeln!(v, "{}", r"/"); help: try this | LL - writeln!(v, "{}", r"/"); -LL + writeln!(v, "/"); +LL + writeln!(v, "//"); | error: literal with an empty format string diff --git a/tests/ui/write_with_newline.fixed b/tests/ui/write_with_newline.fixed new file mode 100644 index 00000000000..0a10e526a2f --- /dev/null +++ b/tests/ui/write_with_newline.fixed @@ -0,0 +1,63 @@ +// 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)] + +use std::io::Write; + +fn main() { + let mut v = Vec::new(); + + // These should fail + writeln!(v, "Hello"); + writeln!(v, "Hello {}", "world"); + writeln!(v, "Hello {} {}", "world", "#2"); + writeln!(v, "{}", 1265); + writeln!(v); + + // These should be fine + write!(v, ""); + write!(v, "Hello"); + writeln!(v, "Hello"); + writeln!(v, "Hello\n"); + writeln!(v, "Hello {}\n", "world"); + write!(v, "Issue\n{}", 1265); + write!(v, "{}", 1265); + write!(v, "\n{}", 1275); + write!(v, "\n\n"); + write!(v, "like eof\n\n"); + write!(v, "Hello {} {}\n\n", "world", "#2"); + writeln!(v, "\ndon't\nwarn\nfor\nmultiple\nnewlines\n"); // #3126 + writeln!(v, "\nbla\n\n"); // #3126 + + // Escaping + write!(v, "\\n"); // #3514 + writeln!(v, "\\"); // should fail + write!(v, "\\\\n"); + + // Raw strings + write!(v, r"\n"); // #3778 + + // Literal newlines should also fail + writeln!( + v + ); + writeln!( + v + ); + + // Don't warn on CRLF (#4208) + write!(v, "\r\n"); + write!(v, "foo\r\n"); + writeln!(v, "\\r"); // warns + write!(v, "foo\rbar\n"); + + // Ignore expanded format strings + macro_rules! newline { + () => { + "\n" + }; + } + write!(v, newline!()); +} diff --git a/tests/ui/write_with_newline.stderr b/tests/ui/write_with_newline.stderr index 9035275b29d..03a18a4dc3f 100644 --- a/tests/ui/write_with_newline.stderr +++ b/tests/ui/write_with_newline.stderr @@ -62,13 +62,13 @@ LL + writeln!(v); error: using `write!()` with a format string that ends in a single newline --> $DIR/write_with_newline.rs:36:5 | -LL | write!(v, "//n"); // should fail +LL | write!(v, "///n"); // should fail | ^^^^^^^^^^^^^^^^^ | help: use `writeln!` instead | -LL - write!(v, "//n"); // should fail -LL + writeln!(v, "/"); // should fail +LL - write!(v, "///n"); // should fail +LL + writeln!(v, "//"); // should fail | error: using `write!()` with a format string that ends in a single newline @@ -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"); +LL | write!(v, "//r/n"); | ^^^^^^^^^^^^^^^^^^ | help: use `writeln!` instead | -LL - write!(v, "/r/n"); -LL + writeln!(v, "/r"); +LL - write!(v, "//r/n"); +LL + writeln!(v, "//r"); | error: aborting due to 9 previous errors From 0a87ce866244dd3d23270f438819d5418f736262 Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Mon, 26 Jun 2023 14:30:19 +0000 Subject: [PATCH 263/310] Find the right `cargo-clippy` binary in CI --- tests/compile-test.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tests/compile-test.rs b/tests/compile-test.rs index 281e778ada6..c5e8622bc85 100644 --- a/tests/compile-test.rs +++ b/tests/compile-test.rs @@ -161,7 +161,8 @@ fn run_ui_cargo() { } let mut config = base_config("ui-cargo"); - config.program = CommandBuilder::cargo(); + config.program.input_file_flag = CommandBuilder::cargo().input_file_flag; + config.program.out_dir_flag = CommandBuilder::cargo().out_dir_flag; config.program.args = vec!["clippy".into(), "--color".into(), "never".into(), "--quiet".into()]; config .program From 733a9ea6b906441b755fbcd983c93a466b331070 Mon Sep 17 00:00:00 2001 From: y21 <30553356+y21@users.noreply.github.com> Date: Mon, 26 Jun 2023 20:13:06 +0200 Subject: [PATCH 264/310] [`option_if_let_else`]: suggest `.as_ref()` if `&Option<_>` --- clippy_lints/src/option_if_let_else.rs | 3 +++ tests/ui/option_if_let_else.fixed | 18 ++++++++++++++++++ tests/ui/option_if_let_else.rs | 24 ++++++++++++++++++++++++ tests/ui/option_if_let_else.stderr | 20 +++++++++++++++++++- 4 files changed, 64 insertions(+), 1 deletion(-) diff --git a/clippy_lints/src/option_if_let_else.rs b/clippy_lints/src/option_if_let_else.rs index aa6d4004268..abdccc47f54 100644 --- a/clippy_lints/src/option_if_let_else.rs +++ b/clippy_lints/src/option_if_let_else.rs @@ -140,6 +140,9 @@ fn try_get_option_occurrence<'tcx>( let (as_ref, as_mut) = match &expr.kind { ExprKind::AddrOf(_, Mutability::Not, _) => (true, false), ExprKind::AddrOf(_, Mutability::Mut, _) => (false, true), + _ if let Some(mutb) = cx.typeck_results().expr_ty(expr).ref_mutability() => { + (mutb == Mutability::Not, mutb == Mutability::Mut) + } _ => (bind_annotation == BindingAnnotation::REF, bind_annotation == BindingAnnotation::REF_MUT), }; diff --git a/tests/ui/option_if_let_else.fixed b/tests/ui/option_if_let_else.fixed index 2b8ce5477cc..44ab8ebb50a 100644 --- a/tests/ui/option_if_let_else.fixed +++ b/tests/ui/option_if_let_else.fixed @@ -198,6 +198,8 @@ fn main() { let _ = res.map_or(1, |a| a + 1); let _ = res.map_or(1, |a| a + 1); let _ = res.map_or(5, |a| a + 1); + issue10729::reproduce(&None); + issue10729::reproduce2(&mut None); } #[allow(dead_code)] @@ -208,3 +210,19 @@ fn issue9742() -> Option<&'static str> { _ => None, } } + +mod issue10729 { + #![allow(clippy::unit_arg)] + + pub fn reproduce(initial: &Option) { + // 👇 needs `.as_ref()` because initial is an `&Option<_>` + initial.as_ref().map_or({}, |value| do_something(value)) + } + + pub fn reproduce2(initial: &mut Option) { + initial.as_mut().map_or({}, |value| do_something2(value)) + } + + fn do_something(_value: &str) {} + fn do_something2(_value: &mut str) {} +} diff --git a/tests/ui/option_if_let_else.rs b/tests/ui/option_if_let_else.rs index cfbec8cb27d..9358c20ab95 100644 --- a/tests/ui/option_if_let_else.rs +++ b/tests/ui/option_if_let_else.rs @@ -239,6 +239,8 @@ fn main() { Ok(a) => a + 1, }; let _ = if let Ok(a) = res { a + 1 } else { 5 }; + issue10729::reproduce(&None); + issue10729::reproduce2(&mut None); } #[allow(dead_code)] @@ -249,3 +251,25 @@ fn issue9742() -> Option<&'static str> { _ => None, } } + +mod issue10729 { + #![allow(clippy::unit_arg)] + + pub fn reproduce(initial: &Option) { + // 👇 needs `.as_ref()` because initial is an `&Option<_>` + match initial { + Some(value) => do_something(value), + None => {}, + } + } + + pub fn reproduce2(initial: &mut Option) { + match initial { + Some(value) => do_something2(value), + None => {}, + } + } + + fn do_something(_value: &str) {} + fn do_something2(_value: &mut str) {} +} diff --git a/tests/ui/option_if_let_else.stderr b/tests/ui/option_if_let_else.stderr index 91d52fc79b8..fde27f21690 100644 --- a/tests/ui/option_if_let_else.stderr +++ b/tests/ui/option_if_let_else.stderr @@ -271,5 +271,23 @@ error: use Option::map_or instead of an if let/else LL | let _ = if let Ok(a) = res { a + 1 } else { 5 }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `res.map_or(5, |a| a + 1)` -error: aborting due to 21 previous errors +error: use Option::map_or instead of an if let/else + --> $DIR/option_if_let_else.rs:260:9 + | +LL | / match initial { +LL | | Some(value) => do_something(value), +LL | | None => {}, +LL | | } + | |_________^ help: try: `initial.as_ref().map_or({}, |value| do_something(value))` + +error: use Option::map_or instead of an if let/else + --> $DIR/option_if_let_else.rs:267:9 + | +LL | / match initial { +LL | | Some(value) => do_something2(value), +LL | | None => {}, +LL | | } + | |_________^ help: try: `initial.as_mut().map_or({}, |value| do_something2(value))` + +error: aborting due to 23 previous errors From d29506794ee270e300d08d57c14ba49e7dc18289 Mon Sep 17 00:00:00 2001 From: Catherine <114838443+Centri3@users.noreply.github.com> Date: Thu, 22 Jun 2023 22:01:17 -0500 Subject: [PATCH 265/310] Don't lint code from external macros --- clippy_lints/src/misc_early/mod.rs | 4 +++ tests/ui/patterns.fixed | 11 +++++++++ tests/ui/patterns.rs | 11 +++++++++ tests/ui/patterns.stderr | 6 ++--- tests/ui/unneeded_field_pattern.rs | 14 ++++++++++- tests/ui/unneeded_field_pattern.stderr | 4 +-- tests/ui/unneeded_wildcard_pattern.fixed | 8 ++++++ tests/ui/unneeded_wildcard_pattern.rs | 8 ++++++ tests/ui/unneeded_wildcard_pattern.stderr | 30 +++++++++++------------ 9 files changed, 75 insertions(+), 21 deletions(-) diff --git a/clippy_lints/src/misc_early/mod.rs b/clippy_lints/src/misc_early/mod.rs index 78be6b9e23f..78253ab6cdc 100644 --- a/clippy_lints/src/misc_early/mod.rs +++ b/clippy_lints/src/misc_early/mod.rs @@ -339,6 +339,10 @@ impl EarlyLintPass for MiscEarlyLints { } fn check_pat(&mut self, cx: &EarlyContext<'_>, pat: &Pat) { + if in_external_macro(cx.sess(), pat.span) { + return; + } + unneeded_field_pattern::check(cx, pat); redundant_pattern::check(cx, pat); unneeded_wildcard_pattern::check(cx, pat); diff --git a/tests/ui/patterns.fixed b/tests/ui/patterns.fixed index a1da47d84fd..714143e7586 100644 --- a/tests/ui/patterns.fixed +++ b/tests/ui/patterns.fixed @@ -1,8 +1,12 @@ //@run-rustfix +//@aux-build:proc_macros.rs:proc-macro #![warn(clippy::all)] #![allow(unused)] #![allow(clippy::uninlined_format_args)] +#[macro_use] +extern crate proc_macros; + fn main() { let v = Some(true); let s = [0, 1, 2, 3, 4]; @@ -34,4 +38,11 @@ fn main() { ref x => println!("vec: {:?}", x), ref y if y == &vec![0] => (), } + external! { + let v = Some(true); + match v { + Some(x) => (), + y @ _ => (), + } + } } diff --git a/tests/ui/patterns.rs b/tests/ui/patterns.rs index 399066b813e..153e2640701 100644 --- a/tests/ui/patterns.rs +++ b/tests/ui/patterns.rs @@ -1,8 +1,12 @@ //@run-rustfix +//@aux-build:proc_macros.rs:proc-macro #![warn(clippy::all)] #![allow(unused)] #![allow(clippy::uninlined_format_args)] +#[macro_use] +extern crate proc_macros; + fn main() { let v = Some(true); let s = [0, 1, 2, 3, 4]; @@ -34,4 +38,11 @@ fn main() { ref x @ _ => println!("vec: {:?}", x), ref y if y == &vec![0] => (), } + external! { + let v = Some(true); + match v { + Some(x) => (), + y @ _ => (), + } + } } diff --git a/tests/ui/patterns.stderr b/tests/ui/patterns.stderr index 2c46b4eb593..276330d21c4 100644 --- a/tests/ui/patterns.stderr +++ b/tests/ui/patterns.stderr @@ -1,5 +1,5 @@ error: the `y @ _` pattern can be written as just `y` - --> $DIR/patterns.rs:11:9 + --> $DIR/patterns.rs:15:9 | LL | y @ _ => (), | ^^^^^ help: try: `y` @@ -7,13 +7,13 @@ LL | y @ _ => (), = note: `-D clippy::redundant-pattern` implied by `-D warnings` error: the `x @ _` pattern can be written as just `x` - --> $DIR/patterns.rs:26:9 + --> $DIR/patterns.rs:30:9 | LL | ref mut x @ _ => { | ^^^^^^^^^^^^^ help: try: `ref mut x` error: the `x @ _` pattern can be written as just `x` - --> $DIR/patterns.rs:34:9 + --> $DIR/patterns.rs:38:9 | LL | ref x @ _ => println!("vec: {:?}", x), | ^^^^^^^^^ help: try: `ref x` diff --git a/tests/ui/unneeded_field_pattern.rs b/tests/ui/unneeded_field_pattern.rs index fa639aa70d6..48ae1cf6640 100644 --- a/tests/ui/unneeded_field_pattern.rs +++ b/tests/ui/unneeded_field_pattern.rs @@ -1,5 +1,9 @@ +//@aux-build:proc_macros.rs:proc-macro #![warn(clippy::unneeded_field_pattern)] -#[allow(dead_code, unused)] +#![allow(dead_code, unused)] + +#[macro_use] +extern crate proc_macros; struct Foo { a: i32, @@ -19,4 +23,12 @@ fn main() { Foo { b: 0, .. } => {}, // should be OK Foo { .. } => {}, // and the Force might be with this one } + external! { + let f = Foo { a: 0, b: 0, c: 0 }; + match f { + Foo { a: _, b: 0, .. } => {}, + + Foo { a: _, b: _, c: _ } => {}, + } + } } diff --git a/tests/ui/unneeded_field_pattern.stderr b/tests/ui/unneeded_field_pattern.stderr index 6f7c3154569..3f15684986f 100644 --- a/tests/ui/unneeded_field_pattern.stderr +++ b/tests/ui/unneeded_field_pattern.stderr @@ -1,5 +1,5 @@ error: you matched a field with a wildcard pattern, consider using `..` instead - --> $DIR/unneeded_field_pattern.rs:14:15 + --> $DIR/unneeded_field_pattern.rs:18:15 | LL | Foo { a: _, b: 0, .. } => {}, | ^^^^ @@ -8,7 +8,7 @@ LL | Foo { a: _, b: 0, .. } => {}, = note: `-D clippy::unneeded-field-pattern` implied by `-D warnings` error: all the struct fields are matched to a wildcard pattern, consider using `..` - --> $DIR/unneeded_field_pattern.rs:16:9 + --> $DIR/unneeded_field_pattern.rs:20:9 | LL | Foo { a: _, b: _, c: _ } => {}, | ^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/unneeded_wildcard_pattern.fixed b/tests/ui/unneeded_wildcard_pattern.fixed index d18c65a7709..2eeba509e83 100644 --- a/tests/ui/unneeded_wildcard_pattern.fixed +++ b/tests/ui/unneeded_wildcard_pattern.fixed @@ -1,8 +1,12 @@ //@run-rustfix +//@aux-build:proc_macros.rs:proc-macro #![feature(stmt_expr_attributes)] #![deny(clippy::unneeded_wildcard_pattern)] #![allow(clippy::needless_if)] +#[macro_use] +extern crate proc_macros; + fn main() { let t = (0, 1, 2, 3); @@ -43,4 +47,8 @@ fn main() { { if let S(0, ..,) = s {}; } + external! { + let t = (0, 1, 2, 3); + if let (0, _, ..) = t {}; + } } diff --git a/tests/ui/unneeded_wildcard_pattern.rs b/tests/ui/unneeded_wildcard_pattern.rs index c80756c4495..5416cfaa542 100644 --- a/tests/ui/unneeded_wildcard_pattern.rs +++ b/tests/ui/unneeded_wildcard_pattern.rs @@ -1,8 +1,12 @@ //@run-rustfix +//@aux-build:proc_macros.rs:proc-macro #![feature(stmt_expr_attributes)] #![deny(clippy::unneeded_wildcard_pattern)] #![allow(clippy::needless_if)] +#[macro_use] +extern crate proc_macros; + fn main() { let t = (0, 1, 2, 3); @@ -43,4 +47,8 @@ fn main() { { if let S(0, .., _, _,) = s {}; } + external! { + let t = (0, 1, 2, 3); + if let (0, _, ..) = t {}; + } } diff --git a/tests/ui/unneeded_wildcard_pattern.stderr b/tests/ui/unneeded_wildcard_pattern.stderr index 8a004b77e94..ffbdc049506 100644 --- a/tests/ui/unneeded_wildcard_pattern.stderr +++ b/tests/ui/unneeded_wildcard_pattern.stderr @@ -1,89 +1,89 @@ error: this pattern is unneeded as the `..` pattern can match that element - --> $DIR/unneeded_wildcard_pattern.rs:9:18 + --> $DIR/unneeded_wildcard_pattern.rs:13:18 | LL | if let (0, .., _) = t {}; | ^^^ help: remove it | note: the lint level is defined here - --> $DIR/unneeded_wildcard_pattern.rs:3:9 + --> $DIR/unneeded_wildcard_pattern.rs:4:9 | LL | #![deny(clippy::unneeded_wildcard_pattern)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: this pattern is unneeded as the `..` pattern can match that element - --> $DIR/unneeded_wildcard_pattern.rs:10:16 + --> $DIR/unneeded_wildcard_pattern.rs:14:16 | LL | if let (0, _, ..) = t {}; | ^^^ help: remove it error: this pattern is unneeded as the `..` pattern can match that element - --> $DIR/unneeded_wildcard_pattern.rs:11:13 + --> $DIR/unneeded_wildcard_pattern.rs:15:13 | LL | if let (_, .., 0) = t {}; | ^^^ help: remove it error: this pattern is unneeded as the `..` pattern can match that element - --> $DIR/unneeded_wildcard_pattern.rs:12:15 + --> $DIR/unneeded_wildcard_pattern.rs:16:15 | LL | if let (.., _, 0) = t {}; | ^^^ help: remove it error: these patterns are unneeded as the `..` pattern can match those elements - --> $DIR/unneeded_wildcard_pattern.rs:13:16 + --> $DIR/unneeded_wildcard_pattern.rs:17:16 | LL | if let (0, _, _, ..) = t {}; | ^^^^^^ help: remove them error: these patterns are unneeded as the `..` pattern can match those elements - --> $DIR/unneeded_wildcard_pattern.rs:14:18 + --> $DIR/unneeded_wildcard_pattern.rs:18:18 | LL | if let (0, .., _, _) = t {}; | ^^^^^^ help: remove them error: these patterns are unneeded as the `..` pattern can match those elements - --> $DIR/unneeded_wildcard_pattern.rs:23:22 + --> $DIR/unneeded_wildcard_pattern.rs:27:22 | LL | if let (0, .., _, _,) = t {}; | ^^^^^^ help: remove them error: this pattern is unneeded as the `..` pattern can match that element - --> $DIR/unneeded_wildcard_pattern.rs:30:19 + --> $DIR/unneeded_wildcard_pattern.rs:34:19 | LL | if let S(0, .., _) = s {}; | ^^^ help: remove it error: this pattern is unneeded as the `..` pattern can match that element - --> $DIR/unneeded_wildcard_pattern.rs:31:17 + --> $DIR/unneeded_wildcard_pattern.rs:35:17 | LL | if let S(0, _, ..) = s {}; | ^^^ help: remove it error: this pattern is unneeded as the `..` pattern can match that element - --> $DIR/unneeded_wildcard_pattern.rs:32:14 + --> $DIR/unneeded_wildcard_pattern.rs:36:14 | LL | if let S(_, .., 0) = s {}; | ^^^ help: remove it error: this pattern is unneeded as the `..` pattern can match that element - --> $DIR/unneeded_wildcard_pattern.rs:33:16 + --> $DIR/unneeded_wildcard_pattern.rs:37:16 | LL | if let S(.., _, 0) = s {}; | ^^^ help: remove it error: these patterns are unneeded as the `..` pattern can match those elements - --> $DIR/unneeded_wildcard_pattern.rs:34:17 + --> $DIR/unneeded_wildcard_pattern.rs:38:17 | LL | if let S(0, _, _, ..) = s {}; | ^^^^^^ help: remove them error: these patterns are unneeded as the `..` pattern can match those elements - --> $DIR/unneeded_wildcard_pattern.rs:35:19 + --> $DIR/unneeded_wildcard_pattern.rs:39:19 | LL | if let S(0, .., _, _) = s {}; | ^^^^^^ help: remove them error: these patterns are unneeded as the `..` pattern can match those elements - --> $DIR/unneeded_wildcard_pattern.rs:44:23 + --> $DIR/unneeded_wildcard_pattern.rs:48:23 | LL | if let S(0, .., _, _,) = s {}; | ^^^^^^ help: remove them From 716c552632acb50a524e62284b9ca2446333a626 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Thu, 22 Jun 2023 18:17:13 +0000 Subject: [PATCH 266/310] Migrate predicates_of and caller_bounds to Clause --- clippy_lints/src/dereference.rs | 8 ++--- clippy_lints/src/derive.rs | 12 ++++---- clippy_lints/src/methods/needless_collect.rs | 4 +-- .../src/methods/unnecessary_to_owned.rs | 8 ++--- clippy_lints/src/needless_pass_by_value.rs | 2 +- clippy_lints/src/unit_return_expecting_ord.rs | 6 ++-- clippy_utils/src/eager_or_lazy.rs | 4 +-- clippy_utils/src/qualify_min_const_fn.rs | 29 ------------------- clippy_utils/src/ty.rs | 16 +++++----- 9 files changed, 30 insertions(+), 59 deletions(-) diff --git a/clippy_lints/src/dereference.rs b/clippy_lints/src/dereference.rs index ee6aef71980..1ecaa1a123c 100644 --- a/clippy_lints/src/dereference.rs +++ b/clippy_lints/src/dereference.rs @@ -27,7 +27,7 @@ use rustc_middle::mir::{Rvalue, StatementKind}; use rustc_middle::ty::adjustment::{Adjust, Adjustment, AutoBorrow, AutoBorrowMutability}; use rustc_middle::ty::{ self, Binder, BoundVariableKind, ClauseKind, EarlyBinder, FnSig, GenericArgKind, List, ParamEnv, ParamTy, - PredicateKind, ProjectionPredicate, Ty, TyCtxt, TypeVisitableExt, TypeckResults, + ProjectionPredicate, Ty, TyCtxt, TypeVisitableExt, TypeckResults, }; use rustc_session::{declare_tool_lint, impl_lint_pass}; use rustc_span::{symbol::sym, Span, Symbol}; @@ -1133,7 +1133,7 @@ fn needless_borrow_impl_arg_position<'tcx>( let projection_predicates = predicates .iter() .filter_map(|predicate| { - if let PredicateKind::Clause(ClauseKind::Projection(projection_predicate)) = predicate.kind().skip_binder() { + if let ClauseKind::Projection(projection_predicate) = predicate.kind().skip_binder() { Some(projection_predicate) } else { None @@ -1147,7 +1147,7 @@ fn needless_borrow_impl_arg_position<'tcx>( if predicates .iter() .filter_map(|predicate| { - if let PredicateKind::Clause(ClauseKind::Trait(trait_predicate)) = predicate.kind().skip_binder() + if let ClauseKind::Trait(trait_predicate) = predicate.kind().skip_binder() && trait_predicate.trait_ref.self_ty() == param_ty.to_ty(cx.tcx) { Some(trait_predicate.trait_ref.def_id) @@ -1209,7 +1209,7 @@ fn needless_borrow_impl_arg_position<'tcx>( } predicates.iter().all(|predicate| { - if let PredicateKind::Clause(ClauseKind::Trait(trait_predicate)) = predicate.kind().skip_binder() + if let ClauseKind::Trait(trait_predicate) = predicate.kind().skip_binder() && cx.tcx.is_diagnostic_item(sym::IntoIterator, trait_predicate.trait_ref.def_id) && let ty::Param(param_ty) = trait_predicate.self_ty().kind() && let GenericArgKind::Type(ty) = substs_with_referent_ty[param_ty.index as usize].unpack() diff --git a/clippy_lints/src/derive.rs b/clippy_lints/src/derive.rs index 8d84e756ff8..10a2f0cb1e7 100644 --- a/clippy_lints/src/derive.rs +++ b/clippy_lints/src/derive.rs @@ -14,8 +14,8 @@ use rustc_lint::{LateContext, LateLintPass}; use rustc_middle::hir::nested_filter; use rustc_middle::traits::Reveal; use rustc_middle::ty::{ - self, Binder, BoundConstness, ClauseKind, GenericArgKind, GenericParamDefKind, ImplPolarity, ParamEnv, PredicateKind, - TraitPredicate, Ty, TyCtxt, + self, BoundConstness, ClauseKind, GenericArgKind, GenericParamDefKind, ImplPolarity, ParamEnv, + ToPredicate, TraitPredicate, Ty, TyCtxt, }; use rustc_session::{declare_lint_pass, declare_tool_lint}; use rustc_span::def_id::LocalDefId; @@ -503,7 +503,7 @@ fn param_env_for_derived_eq(tcx: TyCtxt<'_>, did: DefId, eq_trait_id: DefId) -> let ty_predicates = tcx.predicates_of(did).predicates; for (p, _) in ty_predicates { - if let PredicateKind::Clause(ClauseKind::Trait(p)) = p.kind().skip_binder() + if let ClauseKind::Trait(p) = p.kind().skip_binder() && p.trait_ref.def_id == eq_trait_id && let ty::Param(self_ty) = p.trait_ref.self_ty().kind() && p.constness == BoundConstness::NotConst @@ -514,13 +514,13 @@ fn param_env_for_derived_eq(tcx: TyCtxt<'_>, did: DefId, eq_trait_id: DefId) -> } ParamEnv::new( - tcx.mk_predicates_from_iter(ty_predicates.iter().map(|&(p, _)| p).chain( + tcx.mk_clauses_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(ClauseKind::Trait(TraitPredicate { + ClauseKind::Trait(TraitPredicate { trait_ref: ty::TraitRef::new(tcx, eq_trait_id, [tcx.mk_param_from_def(param)]), constness: BoundConstness::NotConst, polarity: ImplPolarity::Positive, - })))) + }).to_predicate(tcx) }), )), Reveal::UserFacing, diff --git a/clippy_lints/src/methods/needless_collect.rs b/clippy_lints/src/methods/needless_collect.rs index cf85d3174db..0699997d0d2 100644 --- a/clippy_lints/src/methods/needless_collect.rs +++ b/clippy_lints/src/methods/needless_collect.rs @@ -16,7 +16,7 @@ use rustc_hir::{ }; use rustc_lint::LateContext; use rustc_middle::hir::nested_filter; -use rustc_middle::ty::{self, AssocKind, ClauseKind, EarlyBinder, GenericArg, GenericArgKind, PredicateKind, Ty}; +use rustc_middle::ty::{self, AssocKind, ClauseKind, EarlyBinder, GenericArg, GenericArgKind, Ty}; use rustc_span::symbol::Ident; use rustc_span::{sym, Span, Symbol}; @@ -175,7 +175,7 @@ fn check_collect_into_intoiterator<'tcx>( .caller_bounds() .into_iter() .filter_map(|p| { - if let PredicateKind::Clause(ClauseKind::Trait(t)) = p.kind().skip_binder() + if let ClauseKind::Trait(t) = p.kind().skip_binder() && cx.tcx.is_diagnostic_item(sym::IntoIterator,t.trait_ref.def_id) { Some(t.self_ty()) } else { diff --git a/clippy_lints/src/methods/unnecessary_to_owned.rs b/clippy_lints/src/methods/unnecessary_to_owned.rs index 06fa95cd657..80eb00a1b42 100644 --- a/clippy_lints/src/methods/unnecessary_to_owned.rs +++ b/clippy_lints/src/methods/unnecessary_to_owned.rs @@ -14,7 +14,7 @@ use rustc_lint::LateContext; use rustc_middle::mir::Mutability; use rustc_middle::ty::adjustment::{Adjust, Adjustment, OverloadedDeref}; use rustc_middle::ty::subst::{GenericArg, GenericArgKind, SubstsRef}; -use rustc_middle::ty::{self, ClauseKind, EarlyBinder, ParamTy, PredicateKind, ProjectionPredicate, TraitPredicate, Ty}; +use rustc_middle::ty::{self, ClauseKind, EarlyBinder, ParamTy, ProjectionPredicate, TraitPredicate, Ty}; use rustc_span::{sym, Symbol}; use rustc_trait_selection::traits::{query::evaluate_obligation::InferCtxtExt as _, Obligation, ObligationCause}; @@ -345,12 +345,12 @@ fn get_input_traits_and_projections<'tcx>( let mut projection_predicates = Vec::new(); for predicate in cx.tcx.param_env(callee_def_id).caller_bounds() { match predicate.kind().skip_binder() { - PredicateKind::Clause(ClauseKind::Trait(trait_predicate)) => { + ClauseKind::Trait(trait_predicate) => { if trait_predicate.trait_ref.self_ty() == input { trait_predicates.push(trait_predicate); } }, - PredicateKind::Clause(ClauseKind::Projection(projection_predicate)) => { + ClauseKind::Projection(projection_predicate) => { if projection_predicate.projection_ty.self_ty() == input { projection_predicates.push(projection_predicate); } @@ -407,7 +407,7 @@ fn can_change_type<'a>(cx: &LateContext<'a>, mut expr: &'a Expr<'a>, mut ty: Ty< let mut trait_predicates = cx.tcx.param_env(callee_def_id) .caller_bounds().iter().filter(|predicate| { - if let PredicateKind::Clause(ClauseKind::Trait(trait_predicate)) + if let ClauseKind::Trait(trait_predicate) = predicate.kind().skip_binder() && trait_predicate.trait_ref.self_ty() == *param_ty { diff --git a/clippy_lints/src/needless_pass_by_value.rs b/clippy_lints/src/needless_pass_by_value.rs index 3773975e955..c0970048cdf 100644 --- a/clippy_lints/src/needless_pass_by_value.rs +++ b/clippy_lints/src/needless_pass_by_value.rs @@ -126,7 +126,7 @@ impl<'tcx> LateLintPass<'tcx> for NeedlessPassByValue { .filter_map(|pred| { // Note that we do not want to deal with qualified predicates here. match pred.kind().no_bound_vars() { - Some(ty::PredicateKind::Clause(ty::ClauseKind::Trait(pred))) if pred.def_id() != sized_trait => { + Some(ty::ClauseKind::Trait(pred)) if pred.def_id() != sized_trait => { Some(pred) }, _ => None, diff --git a/clippy_lints/src/unit_return_expecting_ord.rs b/clippy_lints/src/unit_return_expecting_ord.rs index a375e5d5b4c..99a1d197678 100644 --- a/clippy_lints/src/unit_return_expecting_ord.rs +++ b/clippy_lints/src/unit_return_expecting_ord.rs @@ -4,7 +4,7 @@ use rustc_hir::def_id::DefId; use rustc_hir::{Closure, Expr, ExprKind, StmtKind}; use rustc_lint::{LateContext, LateLintPass}; use rustc_middle::ty; -use rustc_middle::ty::{ClauseKind, GenericPredicates, PredicateKind, ProjectionPredicate, TraitPredicate}; +use rustc_middle::ty::{ClauseKind, GenericPredicates, ProjectionPredicate, TraitPredicate}; use rustc_session::{declare_lint_pass, declare_tool_lint}; use rustc_span::{sym, BytePos, Span}; @@ -45,7 +45,7 @@ fn get_trait_predicates_for_trait_id<'tcx>( let mut preds = Vec::new(); for (pred, _) in generics.predicates { if_chain! { - if let PredicateKind::Clause(ClauseKind::Trait(poly_trait_pred)) = pred.kind().skip_binder(); + if let ClauseKind::Trait(poly_trait_pred) = pred.kind().skip_binder(); let trait_pred = cx.tcx.erase_late_bound_regions(pred.kind().rebind(poly_trait_pred)); if let Some(trait_def_id) = trait_id; if trait_def_id == trait_pred.trait_ref.def_id; @@ -63,7 +63,7 @@ fn get_projection_pred<'tcx>( trait_pred: TraitPredicate<'tcx>, ) -> Option> { generics.predicates.iter().find_map(|(proj_pred, _)| { - if let ty::PredicateKind::Clause(ClauseKind::Projection(pred)) = proj_pred.kind().skip_binder() { + if let ClauseKind::Projection(pred) = proj_pred.kind().skip_binder() { let projection_pred = cx.tcx.erase_late_bound_regions(proj_pred.kind().rebind(pred)); if projection_pred.projection_ty.substs == trait_pred.trait_ref.substs { return Some(projection_pred); diff --git a/clippy_utils/src/eager_or_lazy.rs b/clippy_utils/src/eager_or_lazy.rs index a42b2ccee88..659c693f87a 100644 --- a/clippy_utils/src/eager_or_lazy.rs +++ b/clippy_utils/src/eager_or_lazy.rs @@ -15,7 +15,7 @@ use rustc_hir::def::{DefKind, Res}; use rustc_hir::intravisit::{walk_expr, Visitor}; use rustc_hir::{def_id::DefId, Block, Expr, ExprKind, QPath, UnOp}; use rustc_lint::LateContext; -use rustc_middle::ty::{self, PredicateKind}; +use rustc_middle::ty; use rustc_span::{sym, Symbol}; use std::cmp; use std::ops; @@ -73,7 +73,7 @@ fn fn_eagerness(cx: &LateContext<'_>, fn_id: DefId, name: Symbol, have_one_arg: .flat_map(|v| v.fields.iter()) .any(|x| matches!(cx.tcx.type_of(x.did).subst_identity().peel_refs().kind(), ty::Param(_))) && all_predicates_of(cx.tcx, fn_id).all(|(pred, _)| match pred.kind().skip_binder() { - PredicateKind::Clause(ty::ClauseKind::Trait(pred)) => cx.tcx.trait_def(pred.trait_ref.def_id).is_marker, + ty::ClauseKind::Trait(pred) => cx.tcx.trait_def(pred.trait_ref.def_id).is_marker, _ => true, }) && subs.types().all(|x| matches!(x.peel_refs().kind(), ty::Param(_))) diff --git a/clippy_utils/src/qualify_min_const_fn.rs b/clippy_utils/src/qualify_min_const_fn.rs index a10eb8646af..b7e83ce6caa 100644 --- a/clippy_utils/src/qualify_min_const_fn.rs +++ b/clippy_utils/src/qualify_min_const_fn.rs @@ -21,35 +21,6 @@ type McfResult = Result<(), (Span, Cow<'static, str>)>; pub fn is_min_const_fn<'tcx>(tcx: TyCtxt<'tcx>, body: &Body<'tcx>, msrv: &Msrv) -> McfResult { let def_id = body.source.def_id(); - let mut current = def_id; - loop { - let predicates = tcx.predicates_of(current); - for (predicate, _) in predicates.predicates { - match predicate.kind().skip_binder() { - ty::PredicateKind::Clause( - ty::ClauseKind::RegionOutlives(_) - | ty::ClauseKind::TypeOutlives(_) - | ty::ClauseKind::Projection(_) - | ty::ClauseKind::Trait(..) - | ty::ClauseKind::ConstArgHasType(..), - ) - | ty::PredicateKind::Clause(ty::ClauseKind::WellFormed(_)) - | ty::PredicateKind::Clause(ty::ClauseKind::ConstEvaluatable(..)) - | ty::PredicateKind::ConstEquate(..) - | ty::PredicateKind::TypeWellFormedFromEnv(..) => continue, - ty::PredicateKind::AliasRelate(..) => panic!("alias relate predicate on function: {predicate:#?}"), - ty::PredicateKind::ObjectSafe(_) => panic!("object safe predicate on function: {predicate:#?}"), - ty::PredicateKind::ClosureKind(..) => panic!("closure kind predicate on function: {predicate:#?}"), - ty::PredicateKind::Subtype(_) => panic!("subtype predicate on function: {predicate:#?}"), - ty::PredicateKind::Coerce(_) => panic!("coerce predicate on function: {predicate:#?}"), - ty::PredicateKind::Ambiguous => panic!("ambiguous predicate on function: {predicate:#?}"), - } - } - match predicates.parent { - Some(parent) => current = parent, - None => break, - } - } for local in &body.local_decls { check_ty(tcx, local.ty, local.source_info.span)?; diff --git a/clippy_utils/src/ty.rs b/clippy_utils/src/ty.rs index 2b185943c59..8d3aecd4785 100644 --- a/clippy_utils/src/ty.rs +++ b/clippy_utils/src/ty.rs @@ -17,7 +17,7 @@ use rustc_lint::LateContext; use rustc_middle::mir::interpret::{ConstValue, Scalar}; use rustc_middle::ty::{ self, layout::ValidityRequirement, AdtDef, AliasTy, AssocKind, Binder, BoundRegion, FnSig, IntTy, List, ParamEnv, - Predicate, PredicateKind, Region, RegionKind, SubstsRef, Ty, TyCtxt, TypeSuperVisitable, TypeVisitable, + Region, RegionKind, SubstsRef, Ty, TyCtxt, TypeSuperVisitable, TypeVisitable, TypeVisitableExt, TypeVisitor, UintTy, VariantDef, VariantDiscr, }; use rustc_middle::ty::{GenericArg, GenericArgKind}; @@ -563,7 +563,7 @@ fn is_uninit_value_valid_for_ty_fallback<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'t } /// Gets an iterator over all predicates which apply to the given item. -pub fn all_predicates_of(tcx: TyCtxt<'_>, id: DefId) -> impl Iterator, Span)> { +pub fn all_predicates_of(tcx: TyCtxt<'_>, id: DefId) -> impl Iterator, Span)> { let mut next_id = Some(id); iter::from_fn(move || { next_id.take().map(|id| { @@ -665,7 +665,7 @@ pub fn ty_sig<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>) -> Option sig_from_bounds( cx, ty, - cx.tcx.item_bounds(def_id).subst_iter(cx.tcx, substs).map(|c| c.as_predicate()), + cx.tcx.item_bounds(def_id).subst_iter(cx.tcx, substs), cx.tcx.opt_parent(def_id), ), ty::FnPtr(sig) => Some(ExprFnSig::Sig(sig, None)), @@ -698,7 +698,7 @@ pub fn ty_sig<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>) -> Option( cx: &LateContext<'tcx>, ty: Ty<'tcx>, - predicates: impl IntoIterator>, + predicates: impl IntoIterator>, predicates_id: Option, ) -> Option> { let mut inputs = None; @@ -707,7 +707,7 @@ fn sig_from_bounds<'tcx>( for pred in predicates { match pred.kind().skip_binder() { - PredicateKind::Clause(ty::ClauseKind::Trait(p)) + ty::ClauseKind::Trait(p) if (lang_items.fn_trait() == Some(p.def_id()) || lang_items.fn_mut_trait() == Some(p.def_id()) || lang_items.fn_once_trait() == Some(p.def_id())) @@ -720,7 +720,7 @@ fn sig_from_bounds<'tcx>( } inputs = Some(i); }, - PredicateKind::Clause(ty::ClauseKind::Projection(p)) + ty::ClauseKind::Projection(p) if Some(p.projection_ty.def_id) == lang_items.fn_once_output() && p.projection_ty.self_ty() == ty => { if output.is_some() { @@ -937,7 +937,7 @@ pub fn adt_and_variant_of_res<'tcx>(cx: &LateContext<'tcx>, res: Res) -> Option< } /// Checks if the type is a type parameter implementing `FnOnce`, but not `FnMut`. -pub fn ty_is_fn_once_param<'tcx>(tcx: TyCtxt<'_>, ty: Ty<'tcx>, predicates: &'tcx [Predicate<'_>]) -> bool { +pub fn ty_is_fn_once_param<'tcx>(tcx: TyCtxt<'_>, ty: Ty<'tcx>, predicates: &'tcx [ty::Clause<'_>]) -> bool { let ty::Param(ty) = *ty.kind() else { return false; }; @@ -950,7 +950,7 @@ pub fn ty_is_fn_once_param<'tcx>(tcx: TyCtxt<'_>, ty: Ty<'tcx>, predicates: &'tc predicates .iter() .try_fold(false, |found, p| { - if let PredicateKind::Clause(ty::ClauseKind::Trait(p)) = p.kind().skip_binder() + if let ty::ClauseKind::Trait(p) = p.kind().skip_binder() && let ty::Param(self_ty) = p.trait_ref.self_ty().kind() && ty.index == self_ty.index { From 9b7d8d1dc7cee007ec90a8c82e159bb504655615 Mon Sep 17 00:00:00 2001 From: darklyspaced Date: Mon, 26 Jun 2023 13:13:42 +0800 Subject: [PATCH 267/310] suggests `is_some_and` over `map().unwrap_or(false)` --- clippy_lints/src/methods/mod.rs | 2 ++ .../src/methods/option_map_unwrap_or.rs | 28 +++++++++++++++++-- tests/ui/map_unwrap_or.rs | 4 +++ tests/ui/map_unwrap_or.stderr | 20 ++++++++++--- 4 files changed, 47 insertions(+), 7 deletions(-) diff --git a/clippy_lints/src/methods/mod.rs b/clippy_lints/src/methods/mod.rs index 99c984ba65a..403fac123a9 100644 --- a/clippy_lints/src/methods/mod.rs +++ b/clippy_lints/src/methods/mod.rs @@ -513,6 +513,7 @@ declare_clippy_lint! { /// # let result: Result = Ok(1); /// # fn some_function(foo: ()) -> usize { 1 } /// option.map(|a| a + 1).unwrap_or(0); + /// option.map(|a| a > 10).unwrap_or(false); /// result.map(|a| a + 1).unwrap_or_else(some_function); /// ``` /// @@ -522,6 +523,7 @@ declare_clippy_lint! { /// # let result: Result = Ok(1); /// # fn some_function(foo: ()) -> usize { 1 } /// option.map_or(0, |a| a + 1); + /// option.is_some_and(|a| a > 10); /// result.map_or_else(some_function, |a| a + 1); /// ``` #[clippy::version = "1.45.0"] diff --git a/clippy_lints/src/methods/option_map_unwrap_or.rs b/clippy_lints/src/methods/option_map_unwrap_or.rs index e931c6277f4..6a4d288abbf 100644 --- a/clippy_lints/src/methods/option_map_unwrap_or.rs +++ b/clippy_lints/src/methods/option_map_unwrap_or.rs @@ -74,16 +74,32 @@ pub(super) fn check<'tcx>( return; } + let mut suggest_is_some_and = false; + // argument to `unwrap_or` is false; should suggest using `is_some_and` + if let ExprKind::Lit(unwrap_lit) = &unwrap_arg.kind { + if let rustc_ast::LitKind::Bool(false) = unwrap_lit.node { + suggest_is_some_and = true; + } + } + let mut applicability = Applicability::MachineApplicable; // get snippet for unwrap_or() let unwrap_snippet = snippet_with_applicability(cx, unwrap_arg.span, "..", &mut applicability); // lint message // comparing the snippet from source to raw text ("None") below is safe // because we already have checked the type. - let arg = if unwrap_snippet == "None" { "None" } else { "" }; + let arg = if unwrap_snippet == "None" { + "None" + } else if suggest_is_some_and { + "false" + } else { + "" + }; let unwrap_snippet_none = unwrap_snippet == "None"; let suggest = if unwrap_snippet_none { "and_then()" + } else if suggest_is_some_and { + "is_some_and()" } else { "map_or(, )" }; @@ -98,12 +114,18 @@ pub(super) fn check<'tcx>( let mut suggestion = vec![ ( map_span, - String::from(if unwrap_snippet_none { "and_then" } else { "map_or" }), + String::from(if unwrap_snippet_none { + "and_then" + } else if suggest_is_some_and { + "is_some_and" + } else { + "map_or" + }), ), (expr.span.with_lo(unwrap_recv.span.hi()), String::new()), ]; - if !unwrap_snippet_none { + if !unwrap_snippet_none && !suggest_is_some_and { suggestion.push((map_arg_span.with_hi(map_arg_span.lo()), format!("{unwrap_snippet}, "))); } diff --git a/tests/ui/map_unwrap_or.rs b/tests/ui/map_unwrap_or.rs index 0cd49dd7760..51b88c7cf2e 100644 --- a/tests/ui/map_unwrap_or.rs +++ b/tests/ui/map_unwrap_or.rs @@ -56,6 +56,10 @@ fn option_methods() { .unwrap_or_else(|| 0 ); + + // Check for `map(f).unwrap_or(false)` use. + let _ = opt.map(|x| x > 5).unwrap_or(false); + } #[rustfmt::skip] diff --git a/tests/ui/map_unwrap_or.stderr b/tests/ui/map_unwrap_or.stderr index 41781b050fa..6f23d2e4f88 100644 --- a/tests/ui/map_unwrap_or.stderr +++ b/tests/ui/map_unwrap_or.stderr @@ -126,8 +126,20 @@ LL | | 0 LL | | ); | |_________^ +error: called `map().unwrap_or(false)` on an `Option` value. This can be done more directly by calling `is_some_and()` instead + --> $DIR/map_unwrap_or.rs:61:13 + | +LL | let _ = opt.map(|x| x > 5).unwrap_or(false); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: use `is_some_and()` instead + | +LL - let _ = opt.map(|x| x > 5).unwrap_or(false); +LL + let _ = opt.is_some_and(|x| x > 5); + | + error: called `map().unwrap_or_else()` on a `Result` value. This can be done more directly by calling `.map_or_else(, )` instead - --> $DIR/map_unwrap_or.rs:67:13 + --> $DIR/map_unwrap_or.rs:71:13 | LL | let _ = res.map(|x| { | _____________^ @@ -137,7 +149,7 @@ LL | | ).unwrap_or_else(|_e| 0); | |____________________________^ error: called `map().unwrap_or_else()` on a `Result` value. This can be done more directly by calling `.map_or_else(, )` instead - --> $DIR/map_unwrap_or.rs:71:13 + --> $DIR/map_unwrap_or.rs:75:13 | LL | let _ = res.map(|x| x + 1) | _____________^ @@ -147,10 +159,10 @@ LL | | }); | |__________^ error: called `map().unwrap_or_else()` on a `Result` value. This can be done more directly by calling `.map_or_else(, )` instead - --> $DIR/map_unwrap_or.rs:95:13 + --> $DIR/map_unwrap_or.rs:99:13 | LL | let _ = res.map(|x| x + 1).unwrap_or_else(|_e| 0); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `res.map_or_else(|_e| 0, |x| x + 1)` -error: aborting due to 12 previous errors +error: aborting due to 13 previous errors From c60222dc12c4868a4aee439d98b007b129edc4cb Mon Sep 17 00:00:00 2001 From: darklyspaced Date: Mon, 26 Jun 2023 13:39:45 +0800 Subject: [PATCH 268/310] changed the msrv to 1.70 to suggest `is_some_and` if the msrv is not >= 1.70 then the `map_or` is suggested instead of `is_some_and` (even when `unwrap_or` returns false) --- clippy_lints/src/methods/mod.rs | 2 +- .../src/methods/option_map_unwrap_or.rs | 12 ++++++--- clippy_utils/src/msrvs.rs | 1 + tests/ui/map_unwrap_or.rs | 14 ++++++++++ tests/ui/map_unwrap_or.stderr | 26 ++++++++++++++++++- 5 files changed, 49 insertions(+), 6 deletions(-) diff --git a/clippy_lints/src/methods/mod.rs b/clippy_lints/src/methods/mod.rs index 403fac123a9..b1d3b61aea3 100644 --- a/clippy_lints/src/methods/mod.rs +++ b/clippy_lints/src/methods/mod.rs @@ -3906,7 +3906,7 @@ impl Methods { manual_saturating_arithmetic::check(cx, expr, lhs, rhs, u_arg, &arith["checked_".len()..]); }, Some(("map", m_recv, [m_arg], span, _)) => { - option_map_unwrap_or::check(cx, expr, m_recv, m_arg, recv, u_arg, span); + option_map_unwrap_or::check(cx, expr, m_recv, m_arg, recv, u_arg, span, &self.msrv); }, Some(("then_some", t_recv, [t_arg], _, _)) => { obfuscated_if_else::check(cx, expr, t_recv, t_arg, u_arg); diff --git a/clippy_lints/src/methods/option_map_unwrap_or.rs b/clippy_lints/src/methods/option_map_unwrap_or.rs index 6a4d288abbf..4387090fe23 100644 --- a/clippy_lints/src/methods/option_map_unwrap_or.rs +++ b/clippy_lints/src/methods/option_map_unwrap_or.rs @@ -1,4 +1,5 @@ use clippy_utils::diagnostics::span_lint_and_then; +use clippy_utils::msrvs::{self, Msrv}; use clippy_utils::source::snippet_with_applicability; use clippy_utils::ty::is_copy; use clippy_utils::ty::is_type_diagnostic_item; @@ -27,6 +28,7 @@ pub(super) fn check<'tcx>( unwrap_recv: &rustc_hir::Expr<'_>, unwrap_arg: &'tcx rustc_hir::Expr<'_>, map_span: Span, + msrv: &Msrv, ) { // lint if the caller of `map()` is an `Option` if is_type_diagnostic_item(cx, cx.typeck_results().expr_ty(recv), sym::Option) { @@ -75,10 +77,12 @@ pub(super) fn check<'tcx>( } let mut suggest_is_some_and = false; - // argument to `unwrap_or` is false; should suggest using `is_some_and` - if let ExprKind::Lit(unwrap_lit) = &unwrap_arg.kind { - if let rustc_ast::LitKind::Bool(false) = unwrap_lit.node { - suggest_is_some_and = true; + // argument to `unwrap_or` is false & is_some_and is stabilised; should suggest using `is_some_and` + if msrv.meets(msrvs::OPT_IS_SOME_AND) { + if let ExprKind::Lit(unwrap_lit) = &unwrap_arg.kind { + if let rustc_ast::LitKind::Bool(false) = unwrap_lit.node { + suggest_is_some_and = true; + } } } diff --git a/clippy_utils/src/msrvs.rs b/clippy_utils/src/msrvs.rs index 0a4c3418a08..1541dc8392c 100644 --- a/clippy_utils/src/msrvs.rs +++ b/clippy_utils/src/msrvs.rs @@ -19,6 +19,7 @@ macro_rules! msrv_aliases { // names may refer to stabilized feature flags or library items msrv_aliases! { + 1,70,0 { OPT_IS_SOME_AND } 1,68,0 { PATH_MAIN_SEPARATOR_STR } 1,65,0 { LET_ELSE, POINTER_CAST_CONSTNESS } 1,62,0 { BOOL_THEN_SOME, DEFAULT_ENUM_ATTRIBUTE } diff --git a/tests/ui/map_unwrap_or.rs b/tests/ui/map_unwrap_or.rs index 51b88c7cf2e..bb36cb2c598 100644 --- a/tests/ui/map_unwrap_or.rs +++ b/tests/ui/map_unwrap_or.rs @@ -99,6 +99,20 @@ fn msrv_1_41() { let _ = res.map(|x| x + 1).unwrap_or_else(|_e| 0); } +#[clippy::msrv = "1.69"] +fn msrv_1_69() { + let opt: Option = Some(1); + + let _ = opt.map(|x| x > 5).unwrap_or(false); +} + +#[clippy::msrv = "1.70"] +fn msrv_1_70() { + let opt: Option = Some(1); + + let _ = opt.map(|x| x > 5).unwrap_or(false); +} + mod issue_10579 { // Different variations of the same issue. fn v1() { diff --git a/tests/ui/map_unwrap_or.stderr b/tests/ui/map_unwrap_or.stderr index 6f23d2e4f88..9f4a4a9ae6b 100644 --- a/tests/ui/map_unwrap_or.stderr +++ b/tests/ui/map_unwrap_or.stderr @@ -164,5 +164,29 @@ error: called `map().unwrap_or_else()` on a `Result` value. This can be do LL | let _ = res.map(|x| x + 1).unwrap_or_else(|_e| 0); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `res.map_or_else(|_e| 0, |x| x + 1)` -error: aborting due to 13 previous errors +error: called `map().unwrap_or()` on an `Option` value. This can be done more directly by calling `map_or(, )` instead + --> $DIR/map_unwrap_or.rs:106:13 + | +LL | let _ = opt.map(|x| x > 5).unwrap_or(false); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: use `map_or(, )` instead + | +LL - let _ = opt.map(|x| x > 5).unwrap_or(false); +LL + let _ = opt.map_or(false, |x| x > 5); + | + +error: called `map().unwrap_or(false)` on an `Option` value. This can be done more directly by calling `is_some_and()` instead + --> $DIR/map_unwrap_or.rs:113:13 + | +LL | let _ = opt.map(|x| x > 5).unwrap_or(false); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: use `is_some_and()` instead + | +LL - let _ = opt.map(|x| x > 5).unwrap_or(false); +LL + let _ = opt.is_some_and(|x| x > 5); + | + +error: aborting due to 15 previous errors From b832175b2d51a02fdac3bb8110b71f9a1e1d30b4 Mon Sep 17 00:00:00 2001 From: darklyspaced Date: Mon, 26 Jun 2023 14:05:41 +0800 Subject: [PATCH 269/310] now passes dogfood by wrapping unwrap_recv and unwrap_arg into a tuple was previously failing due to `check` having to many arguments. --- clippy_lints/src/methods/mod.rs | 2 +- clippy_lints/src/methods/option_map_unwrap_or.rs | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/clippy_lints/src/methods/mod.rs b/clippy_lints/src/methods/mod.rs index b1d3b61aea3..cdabb168912 100644 --- a/clippy_lints/src/methods/mod.rs +++ b/clippy_lints/src/methods/mod.rs @@ -3906,7 +3906,7 @@ impl Methods { manual_saturating_arithmetic::check(cx, expr, lhs, rhs, u_arg, &arith["checked_".len()..]); }, Some(("map", m_recv, [m_arg], span, _)) => { - option_map_unwrap_or::check(cx, expr, m_recv, m_arg, recv, u_arg, span, &self.msrv); + option_map_unwrap_or::check(cx, expr, m_recv, m_arg, (recv, u_arg), span, &self.msrv); }, Some(("then_some", t_recv, [t_arg], _, _)) => { obfuscated_if_else::check(cx, expr, t_recv, t_arg, u_arg); diff --git a/clippy_lints/src/methods/option_map_unwrap_or.rs b/clippy_lints/src/methods/option_map_unwrap_or.rs index 4387090fe23..b0d902e6088 100644 --- a/clippy_lints/src/methods/option_map_unwrap_or.rs +++ b/clippy_lints/src/methods/option_map_unwrap_or.rs @@ -25,11 +25,11 @@ pub(super) fn check<'tcx>( expr: &rustc_hir::Expr<'_>, recv: &rustc_hir::Expr<'_>, map_arg: &'tcx rustc_hir::Expr<'_>, - unwrap_recv: &rustc_hir::Expr<'_>, - unwrap_arg: &'tcx rustc_hir::Expr<'_>, + unwrap: (&rustc_hir::Expr<'_>, &'tcx rustc_hir::Expr<'_>), map_span: Span, msrv: &Msrv, ) { + let (unwrap_recv, unwrap_arg) = unwrap; // lint if the caller of `map()` is an `Option` if is_type_diagnostic_item(cx, cx.typeck_results().expr_ty(recv), sym::Option) { if !is_copy(cx, cx.typeck_results().expr_ty(unwrap_arg)) { From c378bf9ddf10e191fce5753a02a09bb0ab8961fb Mon Sep 17 00:00:00 2001 From: darklyspaced Date: Mon, 26 Jun 2023 14:43:36 +0800 Subject: [PATCH 270/310] Revert "now passes dogfood by wrapping unwrap_recv and unwrap_arg into a tuple" This reverts commit 7b91844a3207d90d4200a7b53d0ae1a7a1dca73a. --- clippy_lints/src/methods/mod.rs | 2 +- clippy_lints/src/methods/option_map_unwrap_or.rs | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/clippy_lints/src/methods/mod.rs b/clippy_lints/src/methods/mod.rs index cdabb168912..b1d3b61aea3 100644 --- a/clippy_lints/src/methods/mod.rs +++ b/clippy_lints/src/methods/mod.rs @@ -3906,7 +3906,7 @@ impl Methods { manual_saturating_arithmetic::check(cx, expr, lhs, rhs, u_arg, &arith["checked_".len()..]); }, Some(("map", m_recv, [m_arg], span, _)) => { - option_map_unwrap_or::check(cx, expr, m_recv, m_arg, (recv, u_arg), span, &self.msrv); + option_map_unwrap_or::check(cx, expr, m_recv, m_arg, recv, u_arg, span, &self.msrv); }, Some(("then_some", t_recv, [t_arg], _, _)) => { obfuscated_if_else::check(cx, expr, t_recv, t_arg, u_arg); diff --git a/clippy_lints/src/methods/option_map_unwrap_or.rs b/clippy_lints/src/methods/option_map_unwrap_or.rs index b0d902e6088..4387090fe23 100644 --- a/clippy_lints/src/methods/option_map_unwrap_or.rs +++ b/clippy_lints/src/methods/option_map_unwrap_or.rs @@ -25,11 +25,11 @@ pub(super) fn check<'tcx>( expr: &rustc_hir::Expr<'_>, recv: &rustc_hir::Expr<'_>, map_arg: &'tcx rustc_hir::Expr<'_>, - unwrap: (&rustc_hir::Expr<'_>, &'tcx rustc_hir::Expr<'_>), + unwrap_recv: &rustc_hir::Expr<'_>, + unwrap_arg: &'tcx rustc_hir::Expr<'_>, map_span: Span, msrv: &Msrv, ) { - let (unwrap_recv, unwrap_arg) = unwrap; // lint if the caller of `map()` is an `Option` if is_type_diagnostic_item(cx, cx.typeck_results().expr_ty(recv), sym::Option) { if !is_copy(cx, cx.typeck_results().expr_ty(unwrap_arg)) { From ca00b138b21d87cff24d085dd9d9dce2bf26b530 Mon Sep 17 00:00:00 2001 From: darklyspaced Date: Mon, 26 Jun 2023 14:47:05 +0800 Subject: [PATCH 271/310] ignore too_many_arguments on `check` --- clippy_lints/src/methods/option_map_unwrap_or.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/clippy_lints/src/methods/option_map_unwrap_or.rs b/clippy_lints/src/methods/option_map_unwrap_or.rs index 4387090fe23..e836a1395a2 100644 --- a/clippy_lints/src/methods/option_map_unwrap_or.rs +++ b/clippy_lints/src/methods/option_map_unwrap_or.rs @@ -20,6 +20,7 @@ use rustc_span::sym; use super::MAP_UNWRAP_OR; /// lint use of `map().unwrap_or()` for `Option`s +#[expect(clippy::too_many_arguments)] pub(super) fn check<'tcx>( cx: &LateContext<'tcx>, expr: &rustc_hir::Expr<'_>, From a693cbc1bca16c753dfb1aa853e970bd2028634c Mon Sep 17 00:00:00 2001 From: darklyspaced Date: Tue, 27 Jun 2023 11:28:45 +0800 Subject: [PATCH 272/310] changed msrv name for consistency & changed nested if for style --- clippy_lints/src/methods/option_map_unwrap_or.rs | 13 ++++--------- clippy_utils/src/msrvs.rs | 2 +- 2 files changed, 5 insertions(+), 10 deletions(-) diff --git a/clippy_lints/src/methods/option_map_unwrap_or.rs b/clippy_lints/src/methods/option_map_unwrap_or.rs index e836a1395a2..f4f158c0439 100644 --- a/clippy_lints/src/methods/option_map_unwrap_or.rs +++ b/clippy_lints/src/methods/option_map_unwrap_or.rs @@ -77,15 +77,10 @@ pub(super) fn check<'tcx>( return; } - let mut suggest_is_some_and = false; - // argument to `unwrap_or` is false & is_some_and is stabilised; should suggest using `is_some_and` - if msrv.meets(msrvs::OPT_IS_SOME_AND) { - if let ExprKind::Lit(unwrap_lit) = &unwrap_arg.kind { - if let rustc_ast::LitKind::Bool(false) = unwrap_lit.node { - suggest_is_some_and = true; - } - } - } + // is_some_and is stabilised && `unwrap_or` argument is false; suggest `is_some_and` instead + let suggest_is_some_and = msrv.meets(msrvs::OPTION_IS_SOME_AND) + && matches!(&unwrap_arg.kind, ExprKind::Lit(lit) + if matches!(lit.node, rustc_ast::LitKind::Bool(false))); let mut applicability = Applicability::MachineApplicable; // get snippet for unwrap_or() diff --git a/clippy_utils/src/msrvs.rs b/clippy_utils/src/msrvs.rs index 1541dc8392c..5aacca45146 100644 --- a/clippy_utils/src/msrvs.rs +++ b/clippy_utils/src/msrvs.rs @@ -19,7 +19,7 @@ macro_rules! msrv_aliases { // names may refer to stabilized feature flags or library items msrv_aliases! { - 1,70,0 { OPT_IS_SOME_AND } + 1,70,0 { OPTION_IS_SOME_AND } 1,68,0 { PATH_MAIN_SEPARATOR_STR } 1,65,0 { LET_ELSE, POINTER_CAST_CONSTNESS } 1,62,0 { BOOL_THEN_SOME, DEFAULT_ENUM_ATTRIBUTE } From 1bf74fc303d77be3ceef5b030d9fd73ca6031298 Mon Sep 17 00:00:00 2001 From: Centri3 <114838443+Centri3@users.noreply.github.com> Date: Sat, 3 Jun 2023 18:07:36 -0500 Subject: [PATCH 273/310] add `needless_raw_string_hashes` lint add semicolon in doctest --- CHANGELOG.md | 1 + clippy_lints/src/declared_lints.rs | 1 + clippy_lints/src/lib.rs | 1 + .../src/needless_raw_string_hashes.rs | 73 ++++++++++++++++++ src/main.rs | 4 +- tests/ui/format.fixed | 1 + tests/ui/format.rs | 1 + tests/ui/needless_raw_string_hashes.fixed | 19 +++++ tests/ui/needless_raw_string_hashes.rs | 19 +++++ tests/ui/needless_raw_string_hashes.stderr | 76 +++++++++++++++++++ tests/ui/regex.rs | 2 +- tests/ui/single_char_add_str.fixed | 1 + tests/ui/single_char_add_str.rs | 1 + tests/ui/single_char_add_str.stderr | 30 ++++---- tests/ui/single_char_pattern.fixed | 2 +- tests/ui/single_char_pattern.rs | 2 +- tests/ui/string_lit_as_bytes.fixed | 2 +- tests/ui/string_lit_as_bytes.rs | 2 +- 18 files changed, 216 insertions(+), 22 deletions(-) create mode 100644 clippy_lints/src/needless_raw_string_hashes.rs create mode 100644 tests/ui/needless_raw_string_hashes.fixed create mode 100644 tests/ui/needless_raw_string_hashes.rs create mode 100644 tests/ui/needless_raw_string_hashes.stderr diff --git a/CHANGELOG.md b/CHANGELOG.md index 941efb1abff..7cb820b0c43 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5048,6 +5048,7 @@ Released 2018-09-13 [`needless_pass_by_value`]: https://rust-lang.github.io/rust-clippy/master/index.html#needless_pass_by_value [`needless_question_mark`]: https://rust-lang.github.io/rust-clippy/master/index.html#needless_question_mark [`needless_range_loop`]: https://rust-lang.github.io/rust-clippy/master/index.html#needless_range_loop +[`needless_raw_string_hashes`]: https://rust-lang.github.io/rust-clippy/master/index.html#needless_raw_string_hashes [`needless_return`]: https://rust-lang.github.io/rust-clippy/master/index.html#needless_return [`needless_splitn`]: https://rust-lang.github.io/rust-clippy/master/index.html#needless_splitn [`needless_update`]: https://rust-lang.github.io/rust-clippy/master/index.html#needless_update diff --git a/clippy_lints/src/declared_lints.rs b/clippy_lints/src/declared_lints.rs index 0eec18a91bc..8753bcee5ce 100644 --- a/clippy_lints/src/declared_lints.rs +++ b/clippy_lints/src/declared_lints.rs @@ -469,6 +469,7 @@ pub(crate) static LINTS: &[&crate::LintInfo] = &[ crate::needless_parens_on_range_literals::NEEDLESS_PARENS_ON_RANGE_LITERALS_INFO, crate::needless_pass_by_value::NEEDLESS_PASS_BY_VALUE_INFO, crate::needless_question_mark::NEEDLESS_QUESTION_MARK_INFO, + crate::needless_raw_string_hashes::NEEDLESS_RAW_STRING_HASHES_INFO, crate::needless_update::NEEDLESS_UPDATE_INFO, crate::neg_cmp_op_on_partial_ord::NEG_CMP_OP_ON_PARTIAL_ORD_INFO, crate::neg_multiply::NEG_MULTIPLY_INFO, diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index 6d77b828f14..aadba6581a1 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -230,6 +230,7 @@ mod needless_late_init; mod needless_parens_on_range_literals; mod needless_pass_by_value; mod needless_question_mark; +mod needless_raw_string_hashes; mod needless_update; mod neg_cmp_op_on_partial_ord; mod neg_multiply; diff --git a/clippy_lints/src/needless_raw_string_hashes.rs b/clippy_lints/src/needless_raw_string_hashes.rs new file mode 100644 index 00000000000..85dffa5613d --- /dev/null +++ b/clippy_lints/src/needless_raw_string_hashes.rs @@ -0,0 +1,73 @@ +use clippy_utils::diagnostics::span_lint_and_sugg; +use rustc_ast::{ + ast::{Expr, ExprKind}, + token::LitKind, +}; +use rustc_errors::Applicability; +use rustc_lint::{EarlyContext, EarlyLintPass, LintContext}; +use rustc_middle::lint::in_external_macro; +use rustc_session::{declare_lint_pass, declare_tool_lint}; + +declare_clippy_lint! { + /// ### What it does + /// Checks for raw string literals with an unnecessary amount of hashes around them. + /// + /// ### Why is this bad? + /// It's just unnecessary, and makes it look like there's more escaping needed than is actually + /// necessary. + /// + /// ### Example + /// ```rust + /// let r = r###"Hello, "world"!"###; + /// ``` + /// Use instead: + /// ```rust + /// let r = r#"Hello, "world"!"#; + /// ``` + #[clippy::version = "1.72.0"] + pub NEEDLESS_RAW_STRING_HASHES, + complexity, + "suggests reducing the number of hashes around a raw string literal" +} +declare_lint_pass!(NeedlessRawStringHashes => [NEEDLESS_RAW_STRING_HASHES]); + +impl EarlyLintPass for NeedlessRawStringHashes { + fn check_expr(&mut self, cx: &EarlyContext<'_>, expr: &Expr) { + if_chain! { + if !in_external_macro(cx.sess(), expr.span); + if let ExprKind::Lit(lit) = expr.kind; + if let LitKind::StrRaw(num) | LitKind::ByteStrRaw(num) | LitKind::CStrRaw(num) = lit.kind; + then { + let str = lit.symbol.as_str(); + let mut lowest = 0; + + for i in (0..num).rev() { + if str.contains(&format!("\"{}", "#".repeat(i as usize))) { + lowest = i + 1; + break; + } + } + + if lowest < num { + let hashes = "#".repeat(lowest as usize); + let prefix = match lit.kind { + LitKind::StrRaw(..) => "r", + LitKind::ByteStrRaw(..) => "br", + LitKind::CStrRaw(..) => "cr", + _ => unreachable!(), + }; + + span_lint_and_sugg( + cx, + NEEDLESS_RAW_STRING_HASHES, + expr.span, + "unnecessary hashes around raw string literal", + "try", + format!(r#"{prefix}{hashes}"{}"{hashes}"#, lit.symbol), + Applicability::MachineApplicable, + ); + } + } + } + } +} diff --git a/src/main.rs b/src/main.rs index 300c84a1442..fd0da5a170b 100644 --- a/src/main.rs +++ b/src/main.rs @@ -6,7 +6,7 @@ use std::env; use std::path::PathBuf; use std::process::{self, Command}; -const CARGO_CLIPPY_HELP: &str = r#"Checks a package to catch common mistakes and improve your Rust code. +const CARGO_CLIPPY_HELP: &str = r"Checks a package to catch common mistakes and improve your Rust code. Usage: cargo clippy [options] [--] [...] @@ -31,7 +31,7 @@ with: You can use tool lints to allow or deny lints from your code, e.g.: #[allow(clippy::needless_lifetimes)] -"#; +"; fn show_help() { println!("{CARGO_CLIPPY_HELP}"); diff --git a/tests/ui/format.fixed b/tests/ui/format.fixed index f214cabef67..2e24e07ea26 100644 --- a/tests/ui/format.fixed +++ b/tests/ui/format.fixed @@ -7,6 +7,7 @@ clippy::to_string_in_format_args, clippy::needless_borrow, clippy::uninlined_format_args, + clippy::needless_raw_string_hashes, clippy::useless_vec )] diff --git a/tests/ui/format.rs b/tests/ui/format.rs index d9b28a4f7c0..0e64a310b01 100644 --- a/tests/ui/format.rs +++ b/tests/ui/format.rs @@ -7,6 +7,7 @@ clippy::to_string_in_format_args, clippy::needless_borrow, clippy::uninlined_format_args, + clippy::needless_raw_string_hashes, clippy::useless_vec )] diff --git a/tests/ui/needless_raw_string_hashes.fixed b/tests/ui/needless_raw_string_hashes.fixed new file mode 100644 index 00000000000..43616860a2e --- /dev/null +++ b/tests/ui/needless_raw_string_hashes.fixed @@ -0,0 +1,19 @@ +//@run-rustfix +#![allow(clippy::no_effect, unused)] +#![warn(clippy::needless_raw_string_hashes)] +#![feature(c_str_literals)] + +fn main() { + r"aaa"; + r#"Hello "world"!"#; + r####" "### "## "# "####; + r###" "aa" "# "## "###; + br"aaa"; + br#"Hello "world"!"#; + br####" "### "## "# "####; + br###" "aa" "# "## "###; + cr"aaa"; + cr#"Hello "world"!"#; + cr####" "### "## "# "####; + cr###" "aa" "# "## "###; +} diff --git a/tests/ui/needless_raw_string_hashes.rs b/tests/ui/needless_raw_string_hashes.rs new file mode 100644 index 00000000000..e2d85c52e78 --- /dev/null +++ b/tests/ui/needless_raw_string_hashes.rs @@ -0,0 +1,19 @@ +//@run-rustfix +#![allow(clippy::no_effect, unused)] +#![warn(clippy::needless_raw_string_hashes)] +#![feature(c_str_literals)] + +fn main() { + r#"aaa"#; + r##"Hello "world"!"##; + r######" "### "## "# "######; + r######" "aa" "# "## "######; + br#"aaa"#; + br##"Hello "world"!"##; + br######" "### "## "# "######; + br######" "aa" "# "## "######; + cr#"aaa"#; + cr##"Hello "world"!"##; + cr######" "### "## "# "######; + cr######" "aa" "# "## "######; +} diff --git a/tests/ui/needless_raw_string_hashes.stderr b/tests/ui/needless_raw_string_hashes.stderr new file mode 100644 index 00000000000..44b878cec40 --- /dev/null +++ b/tests/ui/needless_raw_string_hashes.stderr @@ -0,0 +1,76 @@ +error: unnecessary hashes around raw string literal + --> $DIR/needless_raw_string_hashes.rs:7:5 + | +LL | r#"aaa"#; + | ^^^^^^^^ help: try: `r"aaa"` + | + = note: `-D clippy::needless-raw-string-hashes` implied by `-D warnings` + +error: unnecessary hashes around raw string literal + --> $DIR/needless_raw_string_hashes.rs:8:5 + | +LL | r##"Hello "world"!"##; + | ^^^^^^^^^^^^^^^^^^^^^ help: try: `r#"Hello "world"!"#` + +error: unnecessary hashes around raw string literal + --> $DIR/needless_raw_string_hashes.rs:9:5 + | +LL | r######" "### "## "# "######; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `r####" "### "## "# "####` + +error: unnecessary hashes around raw string literal + --> $DIR/needless_raw_string_hashes.rs:10:5 + | +LL | r######" "aa" "# "## "######; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `r###" "aa" "# "## "###` + +error: unnecessary hashes around raw string literal + --> $DIR/needless_raw_string_hashes.rs:11:5 + | +LL | br#"aaa"#; + | ^^^^^^^^^ help: try: `br"aaa"` + +error: unnecessary hashes around raw string literal + --> $DIR/needless_raw_string_hashes.rs:12:5 + | +LL | br##"Hello "world"!"##; + | ^^^^^^^^^^^^^^^^^^^^^^ help: try: `br#"Hello "world"!"#` + +error: unnecessary hashes around raw string literal + --> $DIR/needless_raw_string_hashes.rs:13:5 + | +LL | br######" "### "## "# "######; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `br####" "### "## "# "####` + +error: unnecessary hashes around raw string literal + --> $DIR/needless_raw_string_hashes.rs:14:5 + | +LL | br######" "aa" "# "## "######; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `br###" "aa" "# "## "###` + +error: unnecessary hashes around raw string literal + --> $DIR/needless_raw_string_hashes.rs:15:5 + | +LL | cr#"aaa"#; + | ^^^^^^^^^ help: try: `cr"aaa"` + +error: unnecessary hashes around raw string literal + --> $DIR/needless_raw_string_hashes.rs:16:5 + | +LL | cr##"Hello "world"!"##; + | ^^^^^^^^^^^^^^^^^^^^^^ help: try: `cr#"Hello "world"!"#` + +error: unnecessary hashes around raw string literal + --> $DIR/needless_raw_string_hashes.rs:17:5 + | +LL | cr######" "### "## "# "######; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `cr####" "### "## "# "####` + +error: unnecessary hashes around raw string literal + --> $DIR/needless_raw_string_hashes.rs:18:5 + | +LL | cr######" "aa" "# "## "######; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `cr###" "aa" "# "## "###` + +error: aborting due to 12 previous errors + diff --git a/tests/ui/regex.rs b/tests/ui/regex.rs index 1c8e47ab594..3b208651946 100644 --- a/tests/ui/regex.rs +++ b/tests/ui/regex.rs @@ -1,4 +1,4 @@ -#![allow(unused, clippy::needless_borrow)] +#![allow(unused, clippy::needless_raw_string_hashes, clippy::needless_borrow)] #![warn(clippy::invalid_regex, clippy::trivial_regex)] extern crate regex; diff --git a/tests/ui/single_char_add_str.fixed b/tests/ui/single_char_add_str.fixed index cbcf1ab21c9..2d4c0841219 100644 --- a/tests/ui/single_char_add_str.fixed +++ b/tests/ui/single_char_add_str.fixed @@ -1,5 +1,6 @@ //@run-rustfix #![warn(clippy::single_char_add_str)] +#![allow(clippy::needless_raw_string_hashes)] macro_rules! get_string { () => { diff --git a/tests/ui/single_char_add_str.rs b/tests/ui/single_char_add_str.rs index a1f005cc833..463b19da09e 100644 --- a/tests/ui/single_char_add_str.rs +++ b/tests/ui/single_char_add_str.rs @@ -1,5 +1,6 @@ //@run-rustfix #![warn(clippy::single_char_add_str)] +#![allow(clippy::needless_raw_string_hashes)] macro_rules! get_string { () => { diff --git a/tests/ui/single_char_add_str.stderr b/tests/ui/single_char_add_str.stderr index 55d91583ad0..3f93c18470e 100644 --- a/tests/ui/single_char_add_str.stderr +++ b/tests/ui/single_char_add_str.stderr @@ -1,5 +1,5 @@ error: calling `push_str()` using a single-character string literal - --> $DIR/single_char_add_str.rs:14:5 + --> $DIR/single_char_add_str.rs:15:5 | LL | string.push_str("R"); | ^^^^^^^^^^^^^^^^^^^^ help: consider using `push` with a character literal: `string.push('R')` @@ -7,85 +7,85 @@ LL | string.push_str("R"); = note: `-D clippy::single-char-add-str` implied by `-D warnings` error: calling `push_str()` using a single-character string literal - --> $DIR/single_char_add_str.rs:15:5 + --> $DIR/single_char_add_str.rs:16:5 | LL | string.push_str("'"); | ^^^^^^^^^^^^^^^^^^^^ help: consider using `push` with a character literal: `string.push('/'')` error: calling `push_str()` using a single-character string literal - --> $DIR/single_char_add_str.rs:20:5 + --> $DIR/single_char_add_str.rs:21:5 | LL | string.push_str("/x52"); | ^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `push` with a character literal: `string.push('/x52')` error: calling `push_str()` using a single-character string literal - --> $DIR/single_char_add_str.rs:21:5 + --> $DIR/single_char_add_str.rs:22:5 | LL | string.push_str("/u{0052}"); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `push` with a character literal: `string.push('/u{0052}')` error: calling `push_str()` using a single-character string literal - --> $DIR/single_char_add_str.rs:22:5 + --> $DIR/single_char_add_str.rs:23:5 | LL | string.push_str(r##"a"##); | ^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `push` with a character literal: `string.push('a')` error: calling `push_str()` using a single-character string literal - --> $DIR/single_char_add_str.rs:24:5 + --> $DIR/single_char_add_str.rs:25:5 | LL | get_string!().push_str("ö"); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `push` with a character literal: `get_string!().push('ö')` error: calling `insert_str()` using a single-character string literal - --> $DIR/single_char_add_str.rs:29:5 + --> $DIR/single_char_add_str.rs:30:5 | LL | string.insert_str(0, "R"); | ^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `insert` with a character literal: `string.insert(0, 'R')` error: calling `insert_str()` using a single-character string literal - --> $DIR/single_char_add_str.rs:30:5 + --> $DIR/single_char_add_str.rs:31:5 | LL | string.insert_str(1, "'"); | ^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `insert` with a character literal: `string.insert(1, '/'')` error: calling `insert_str()` using a single-character string literal - --> $DIR/single_char_add_str.rs:35:5 + --> $DIR/single_char_add_str.rs:36:5 | LL | string.insert_str(0, "/x52"); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `insert` with a character literal: `string.insert(0, '/x52')` error: calling `insert_str()` using a single-character string literal - --> $DIR/single_char_add_str.rs:36:5 + --> $DIR/single_char_add_str.rs:37:5 | LL | string.insert_str(0, "/u{0052}"); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `insert` with a character literal: `string.insert(0, '/u{0052}')` error: calling `insert_str()` using a single-character string literal - --> $DIR/single_char_add_str.rs:38:5 + --> $DIR/single_char_add_str.rs:39:5 | LL | string.insert_str(x, r##"a"##); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `insert` with a character literal: `string.insert(x, 'a')` error: calling `insert_str()` using a single-character string literal - --> $DIR/single_char_add_str.rs:40:5 + --> $DIR/single_char_add_str.rs:41:5 | LL | string.insert_str(Y, r##"a"##); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `insert` with a character literal: `string.insert(Y, 'a')` error: calling `insert_str()` using a single-character string literal - --> $DIR/single_char_add_str.rs:41:5 + --> $DIR/single_char_add_str.rs:42:5 | LL | string.insert_str(Y, r##"""##); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `insert` with a character literal: `string.insert(Y, '"')` error: calling `insert_str()` using a single-character string literal - --> $DIR/single_char_add_str.rs:42:5 + --> $DIR/single_char_add_str.rs:43:5 | LL | string.insert_str(Y, r##"'"##); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `insert` with a character literal: `string.insert(Y, '/'')` error: calling `insert_str()` using a single-character string literal - --> $DIR/single_char_add_str.rs:44:5 + --> $DIR/single_char_add_str.rs:45:5 | LL | get_string!().insert_str(1, "?"); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `insert` with a character literal: `get_string!().insert(1, '?')` diff --git a/tests/ui/single_char_pattern.fixed b/tests/ui/single_char_pattern.fixed index dba89872070..f1dc3ea9894 100644 --- a/tests/ui/single_char_pattern.fixed +++ b/tests/ui/single_char_pattern.fixed @@ -1,6 +1,6 @@ //@run-rustfix -#![allow(unused_must_use)] +#![allow(clippy::needless_raw_string_hashes, unused_must_use)] use std::collections::HashSet; diff --git a/tests/ui/single_char_pattern.rs b/tests/ui/single_char_pattern.rs index 6a145a14bfd..00b38498001 100644 --- a/tests/ui/single_char_pattern.rs +++ b/tests/ui/single_char_pattern.rs @@ -1,6 +1,6 @@ //@run-rustfix -#![allow(unused_must_use)] +#![allow(clippy::needless_raw_string_hashes, unused_must_use)] use std::collections::HashSet; diff --git a/tests/ui/string_lit_as_bytes.fixed b/tests/ui/string_lit_as_bytes.fixed index 3fc11b8b088..0edd81acc7a 100644 --- a/tests/ui/string_lit_as_bytes.fixed +++ b/tests/ui/string_lit_as_bytes.fixed @@ -1,7 +1,7 @@ //@run-rustfix //@aux-build:macro_rules.rs -#![allow(dead_code, unused_variables)] +#![allow(clippy::needless_raw_string_hashes, dead_code, unused_variables)] #![warn(clippy::string_lit_as_bytes)] #[macro_use] diff --git a/tests/ui/string_lit_as_bytes.rs b/tests/ui/string_lit_as_bytes.rs index 7d54acf630e..2647f02f0e9 100644 --- a/tests/ui/string_lit_as_bytes.rs +++ b/tests/ui/string_lit_as_bytes.rs @@ -1,7 +1,7 @@ //@run-rustfix //@aux-build:macro_rules.rs -#![allow(dead_code, unused_variables)] +#![allow(clippy::needless_raw_string_hashes, dead_code, unused_variables)] #![warn(clippy::string_lit_as_bytes)] #[macro_use] From bc744eb82bdf9c4ecb21ade5d7b3516f14da29ad Mon Sep 17 00:00:00 2001 From: Centri3 <114838443+Centri3@users.noreply.github.com> Date: Thu, 8 Jun 2023 06:55:47 -0500 Subject: [PATCH 274/310] new lint `needless_raw_string` + refactor a bit Thanks, #112373, for the snippet at line 75! --- CHANGELOG.md | 1 + clippy_lints/src/declared_lints.rs | 3 +- clippy_lints/src/lib.rs | 2 +- .../src/needless_raw_string_hashes.rs | 73 ------------ clippy_lints/src/raw_strings.rs | 109 ++++++++++++++++++ clippy_lints/src/utils/conf.rs | 6 +- .../almost_standard_lint_formulation.rs | 2 +- src/main.rs | 2 +- tests/lint_message_convention.rs | 30 ++--- .../conf_disallowed_methods.rs | 1 + .../conf_disallowed_methods.stderr | 28 ++--- .../toml_unknown_key/conf_unknown_key.stderr | 2 + tests/ui/format.stderr | 30 ++--- tests/ui/needless_raw_string.fixed | 16 +++ tests/ui/needless_raw_string.rs | 16 +++ tests/ui/needless_raw_string.stderr | 22 ++++ tests/ui/needless_raw_string_hashes.fixed | 2 +- tests/ui/needless_raw_string_hashes.rs | 2 +- tests/ui/regex.rs | 7 +- tests/ui/regex.stderr | 48 ++++---- 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/write_literal_2.rs | 2 +- tests/ui/write_literal_2.stderr | 10 +- 26 files changed, 267 insertions(+), 155 deletions(-) delete mode 100644 clippy_lints/src/needless_raw_string_hashes.rs create mode 100644 clippy_lints/src/raw_strings.rs create mode 100644 tests/ui/needless_raw_string.fixed create mode 100644 tests/ui/needless_raw_string.rs create mode 100644 tests/ui/needless_raw_string.stderr diff --git a/CHANGELOG.md b/CHANGELOG.md index 7cb820b0c43..5b17072df40 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5048,6 +5048,7 @@ Released 2018-09-13 [`needless_pass_by_value`]: https://rust-lang.github.io/rust-clippy/master/index.html#needless_pass_by_value [`needless_question_mark`]: https://rust-lang.github.io/rust-clippy/master/index.html#needless_question_mark [`needless_range_loop`]: https://rust-lang.github.io/rust-clippy/master/index.html#needless_range_loop +[`needless_raw_string`]: https://rust-lang.github.io/rust-clippy/master/index.html#needless_raw_string [`needless_raw_string_hashes`]: https://rust-lang.github.io/rust-clippy/master/index.html#needless_raw_string_hashes [`needless_return`]: https://rust-lang.github.io/rust-clippy/master/index.html#needless_return [`needless_splitn`]: https://rust-lang.github.io/rust-clippy/master/index.html#needless_splitn diff --git a/clippy_lints/src/declared_lints.rs b/clippy_lints/src/declared_lints.rs index 8753bcee5ce..c67ed14b3b0 100644 --- a/clippy_lints/src/declared_lints.rs +++ b/clippy_lints/src/declared_lints.rs @@ -469,7 +469,6 @@ pub(crate) static LINTS: &[&crate::LintInfo] = &[ crate::needless_parens_on_range_literals::NEEDLESS_PARENS_ON_RANGE_LITERALS_INFO, crate::needless_pass_by_value::NEEDLESS_PASS_BY_VALUE_INFO, crate::needless_question_mark::NEEDLESS_QUESTION_MARK_INFO, - crate::needless_raw_string_hashes::NEEDLESS_RAW_STRING_HASHES_INFO, crate::needless_update::NEEDLESS_UPDATE_INFO, crate::neg_cmp_op_on_partial_ord::NEG_CMP_OP_ON_PARTIAL_ORD_INFO, crate::neg_multiply::NEG_MULTIPLY_INFO, @@ -541,6 +540,8 @@ pub(crate) static LINTS: &[&crate::LintInfo] = &[ crate::ranges::RANGE_MINUS_ONE_INFO, crate::ranges::RANGE_PLUS_ONE_INFO, crate::ranges::REVERSED_EMPTY_RANGES_INFO, + crate::raw_strings::NEEDLESS_RAW_STRING_INFO, + crate::raw_strings::NEEDLESS_RAW_STRING_HASHES_INFO, crate::rc_clone_in_vec_init::RC_CLONE_IN_VEC_INIT_INFO, crate::read_zero_byte_vec::READ_ZERO_BYTE_VEC_INFO, crate::redundant_async_block::REDUNDANT_ASYNC_BLOCK_INFO, diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index aadba6581a1..e1a7eedd93e 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -230,7 +230,6 @@ mod needless_late_init; mod needless_parens_on_range_literals; mod needless_pass_by_value; mod needless_question_mark; -mod needless_raw_string_hashes; mod needless_update; mod neg_cmp_op_on_partial_ord; mod neg_multiply; @@ -263,6 +262,7 @@ mod pub_use; mod question_mark; mod question_mark_used; mod ranges; +mod raw_strings; mod rc_clone_in_vec_init; mod read_zero_byte_vec; mod redundant_async_block; diff --git a/clippy_lints/src/needless_raw_string_hashes.rs b/clippy_lints/src/needless_raw_string_hashes.rs deleted file mode 100644 index 85dffa5613d..00000000000 --- a/clippy_lints/src/needless_raw_string_hashes.rs +++ /dev/null @@ -1,73 +0,0 @@ -use clippy_utils::diagnostics::span_lint_and_sugg; -use rustc_ast::{ - ast::{Expr, ExprKind}, - token::LitKind, -}; -use rustc_errors::Applicability; -use rustc_lint::{EarlyContext, EarlyLintPass, LintContext}; -use rustc_middle::lint::in_external_macro; -use rustc_session::{declare_lint_pass, declare_tool_lint}; - -declare_clippy_lint! { - /// ### What it does - /// Checks for raw string literals with an unnecessary amount of hashes around them. - /// - /// ### Why is this bad? - /// It's just unnecessary, and makes it look like there's more escaping needed than is actually - /// necessary. - /// - /// ### Example - /// ```rust - /// let r = r###"Hello, "world"!"###; - /// ``` - /// Use instead: - /// ```rust - /// let r = r#"Hello, "world"!"#; - /// ``` - #[clippy::version = "1.72.0"] - pub NEEDLESS_RAW_STRING_HASHES, - complexity, - "suggests reducing the number of hashes around a raw string literal" -} -declare_lint_pass!(NeedlessRawStringHashes => [NEEDLESS_RAW_STRING_HASHES]); - -impl EarlyLintPass for NeedlessRawStringHashes { - fn check_expr(&mut self, cx: &EarlyContext<'_>, expr: &Expr) { - if_chain! { - if !in_external_macro(cx.sess(), expr.span); - if let ExprKind::Lit(lit) = expr.kind; - if let LitKind::StrRaw(num) | LitKind::ByteStrRaw(num) | LitKind::CStrRaw(num) = lit.kind; - then { - let str = lit.symbol.as_str(); - let mut lowest = 0; - - for i in (0..num).rev() { - if str.contains(&format!("\"{}", "#".repeat(i as usize))) { - lowest = i + 1; - break; - } - } - - if lowest < num { - let hashes = "#".repeat(lowest as usize); - let prefix = match lit.kind { - LitKind::StrRaw(..) => "r", - LitKind::ByteStrRaw(..) => "br", - LitKind::CStrRaw(..) => "cr", - _ => unreachable!(), - }; - - span_lint_and_sugg( - cx, - NEEDLESS_RAW_STRING_HASHES, - expr.span, - "unnecessary hashes around raw string literal", - "try", - format!(r#"{prefix}{hashes}"{}"{hashes}"#, lit.symbol), - Applicability::MachineApplicable, - ); - } - } - } - } -} diff --git a/clippy_lints/src/raw_strings.rs b/clippy_lints/src/raw_strings.rs new file mode 100644 index 00000000000..52814693f3c --- /dev/null +++ b/clippy_lints/src/raw_strings.rs @@ -0,0 +1,109 @@ +use clippy_utils::{diagnostics::span_lint_and_sugg, source::snippet}; +use rustc_ast::{ + ast::{Expr, ExprKind}, + token::LitKind, +}; +use rustc_errors::Applicability; +use rustc_lint::{EarlyContext, EarlyLintPass, LintContext}; +use rustc_middle::lint::in_external_macro; +use rustc_session::{declare_tool_lint, impl_lint_pass}; + +declare_clippy_lint! { + /// ### What it does + /// Checks for raw string literals where a string literal can be used instead. + /// + /// ### Why is this bad? + /// It's just unnecessary. + /// + /// ### Example + /// ```rust + /// let r = r"Hello, world!"; + /// ``` + /// Use instead: + /// ```rust + /// let r = "Hello, world!"; + /// ``` + #[clippy::version = "1.72.0"] + pub NEEDLESS_RAW_STRING, + complexity, + "suggests using a string literal when a raw string literal is unnecessary" +} +declare_clippy_lint! { + /// ### What it does + /// Checks for raw string literals with an unnecessary amount of hashes around them. + /// + /// ### Why is this bad? + /// It's just unnecessary, and makes it look like there's more escaping needed than is actually + /// necessary. + /// + /// ### Example + /// ```rust + /// let r = r###"Hello, "world"!"###; + /// ``` + /// Use instead: + /// ```rust + /// let r = r#"Hello, "world"!"#; + /// ``` + #[clippy::version = "1.72.0"] + pub NEEDLESS_RAW_STRING_HASHES, + complexity, + "suggests reducing the number of hashes around a raw string literal" +} +impl_lint_pass!(RawStrings => [NEEDLESS_RAW_STRING, NEEDLESS_RAW_STRING_HASHES]); + +pub struct RawStrings { + pub needless_raw_string_hashes_allow_one: bool, +} + +impl EarlyLintPass for RawStrings { + fn check_expr(&mut self, cx: &EarlyContext<'_>, expr: &Expr) { + if !in_external_macro(cx.sess(), expr.span) + && let ExprKind::Lit(lit) = expr.kind + && let LitKind::StrRaw(num) | LitKind::ByteStrRaw(num) | LitKind::CStrRaw(num) = lit.kind + { + let prefix = match lit.kind { + LitKind::StrRaw(..) => "r", + LitKind::ByteStrRaw(..) => "br", + LitKind::CStrRaw(..) => "cr", + _ => unreachable!(), + }; + if !snippet(cx, expr.span, prefix).trim().starts_with(prefix) { + return; + } + + #[allow(clippy::cast_possible_truncation)] + let req = lit.symbol.as_str().as_bytes() + .split(|&b| b == b'"') + .skip(1) + .map(|bs| 1 + bs.iter().take_while(|&&b| b == b'#').count() as u8) + .max() + .unwrap_or(0); + + if req < num { + let hashes = "#".repeat(req as usize); + + span_lint_and_sugg( + cx, + NEEDLESS_RAW_STRING_HASHES, + expr.span, + "unnecessary hashes around raw string literal", + "try", + format!(r#"{prefix}{hashes}"{}"{hashes}"#, lit.symbol), + Applicability::MachineApplicable, + ); + } + + if !lit.symbol.as_str().contains(['\\', '"']) { + span_lint_and_sugg( + cx, + NEEDLESS_RAW_STRING, + expr.span, + "unnecessary raw string literal", + "try", + format!("{}\"{}\"", prefix.replace('r', ""), lit.symbol), + Applicability::MachineApplicable, + ); + } + } + } +} diff --git a/clippy_lints/src/utils/conf.rs b/clippy_lints/src/utils/conf.rs index 12197666b30..9f88960f7ce 100644 --- a/clippy_lints/src/utils/conf.rs +++ b/clippy_lints/src/utils/conf.rs @@ -543,10 +543,14 @@ define_Conf! { /// /// Whether to accept a safety comment to be placed above the statement containing the `unsafe` block (accept_comment_above_statement: bool = false), - /// Lint: UNDOCUMENTED_UNSAFE_BLOCKS. + /// Lint: UNDOCUMENTED_UNSAFE_BLOCKS. /// /// Whether to accept a safety comment to be placed above the attributes for the `unsafe` block (accept_comment_above_attributes: bool = false), + /// Lint: UNNECESSARY_RAW_STRING_HASHES. + /// + /// Whether to allow `r#""#` when `r""` can be used + (allow_one_hash_in_raw_string: bool = false), } /// Search for the configuration file. diff --git a/clippy_lints/src/utils/internal_lints/almost_standard_lint_formulation.rs b/clippy_lints/src/utils/internal_lints/almost_standard_lint_formulation.rs index e4cb5316a98..570a88a0ed2 100644 --- a/clippy_lints/src/utils/internal_lints/almost_standard_lint_formulation.rs +++ b/clippy_lints/src/utils/internal_lints/almost_standard_lint_formulation.rs @@ -35,7 +35,7 @@ struct StandardFormulations<'a> { impl AlmostStandardFormulation { pub fn new() -> Self { let standard_formulations = vec![StandardFormulations { - wrong_pattern: Regex::new(r"^(Check for|Detects? uses?)").unwrap(), + wrong_pattern: Regex::new("^(Check for|Detects? uses?)").unwrap(), correction: "Checks for", }]; Self { standard_formulations } diff --git a/src/main.rs b/src/main.rs index fd0da5a170b..cdc85cb33ca 100644 --- a/src/main.rs +++ b/src/main.rs @@ -6,7 +6,7 @@ use std::env; use std::path::PathBuf; use std::process::{self, Command}; -const CARGO_CLIPPY_HELP: &str = r"Checks a package to catch common mistakes and improve your Rust code. +const CARGO_CLIPPY_HELP: &str = "Checks a package to catch common mistakes and improve your Rust code. Usage: cargo clippy [options] [--] [...] diff --git a/tests/lint_message_convention.rs b/tests/lint_message_convention.rs index 8feea800fdb..15e5cdd6992 100644 --- a/tests/lint_message_convention.rs +++ b/tests/lint_message_convention.rs @@ -20,16 +20,16 @@ impl Message { // also no punctuation (except for "?" ?) at the end of a line static REGEX_SET: LazyLock = LazyLock::new(|| { RegexSet::new([ - r"error: [A-Z]", - r"help: [A-Z]", - r"warning: [A-Z]", - r"note: [A-Z]", - r"try this: [A-Z]", - r"error: .*[.!]$", - r"help: .*[.!]$", - r"warning: .*[.!]$", - r"note: .*[.!]$", - r"try this: .*[.!]$", + "error: [A-Z]", + "help: [A-Z]", + "warning: [A-Z]", + "note: [A-Z]", + "try this: [A-Z]", + "error: .*[.!]$", + "help: .*[.!]$", + "warning: .*[.!]$", + "note: .*[.!]$", + "try this: .*[.!]$", ]) .unwrap() }); @@ -39,11 +39,11 @@ impl Message { static EXCEPTIONS_SET: LazyLock = LazyLock::new(|| { RegexSet::new([ r"\.\.\.$", - r".*C-like enum variant discriminant is not portable to 32-bit targets", - r".*Intel x86 assembly syntax used", - r".*AT&T x86 assembly syntax used", - r"note: Clippy version: .*", - r"the compiler unexpectedly panicked. this is a bug.", + ".*C-like enum variant discriminant is not portable to 32-bit targets", + ".*Intel x86 assembly syntax used", + ".*AT&T x86 assembly syntax used", + "note: Clippy version: .*", + "the compiler unexpectedly panicked. this is a bug.", ]) .unwrap() }); 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 ebbc7fea328..d26bc72787b 100644 --- a/tests/ui-toml/toml_disallowed_methods/conf_disallowed_methods.rs +++ b/tests/ui-toml/toml_disallowed_methods/conf_disallowed_methods.rs @@ -1,5 +1,6 @@ //@compile-flags: --crate-name conf_disallowed_methods +#![allow(clippy::needless_raw_string)] #![warn(clippy::disallowed_methods)] #![allow(clippy::useless_vec)] diff --git a/tests/ui-toml/toml_disallowed_methods/conf_disallowed_methods.stderr b/tests/ui-toml/toml_disallowed_methods/conf_disallowed_methods.stderr index 3dc83a40780..fc137c225d8 100644 --- a/tests/ui-toml/toml_disallowed_methods/conf_disallowed_methods.stderr +++ b/tests/ui-toml/toml_disallowed_methods/conf_disallowed_methods.stderr @@ -1,5 +1,5 @@ error: use of a disallowed method `regex::Regex::new` - --> $DIR/conf_disallowed_methods.rs:34:14 + --> $DIR/conf_disallowed_methods.rs:35:14 | LL | let re = Regex::new(r"ab.*c").unwrap(); | ^^^^^^^^^^^^^^^^^^^^ @@ -7,7 +7,7 @@ LL | let re = Regex::new(r"ab.*c").unwrap(); = note: `-D clippy::disallowed-methods` implied by `-D warnings` error: use of a disallowed method `regex::Regex::is_match` - --> $DIR/conf_disallowed_methods.rs:35:5 + --> $DIR/conf_disallowed_methods.rs:36:5 | LL | re.is_match("abc"); | ^^^^^^^^^^^^^^^^^^ @@ -15,73 +15,73 @@ LL | re.is_match("abc"); = note: no matching allowed (from clippy.toml) error: use of a disallowed method `std::iter::Iterator::sum` - --> $DIR/conf_disallowed_methods.rs:38:5 + --> $DIR/conf_disallowed_methods.rs:39:5 | LL | a.iter().sum::(); | ^^^^^^^^^^^^^^^^^^^^^ error: use of a disallowed method `slice::sort_unstable` - --> $DIR/conf_disallowed_methods.rs:40:5 + --> $DIR/conf_disallowed_methods.rs:41:5 | LL | a.sort_unstable(); | ^^^^^^^^^^^^^^^^^ error: use of a disallowed method `f32::clamp` - --> $DIR/conf_disallowed_methods.rs:42:13 + --> $DIR/conf_disallowed_methods.rs:43:13 | LL | let _ = 2.0f32.clamp(3.0f32, 4.0f32); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: use of a disallowed method `regex::Regex::new` - --> $DIR/conf_disallowed_methods.rs:45:61 + --> $DIR/conf_disallowed_methods.rs:46:61 | LL | let indirect: fn(&str) -> Result = Regex::new; | ^^^^^^^^^^ error: use of a disallowed method `f32::clamp` - --> $DIR/conf_disallowed_methods.rs:48:28 + --> $DIR/conf_disallowed_methods.rs:49:28 | LL | let in_call = Box::new(f32::clamp); | ^^^^^^^^^^ error: use of a disallowed method `regex::Regex::new` - --> $DIR/conf_disallowed_methods.rs:49:53 + --> $DIR/conf_disallowed_methods.rs:50:53 | LL | let in_method_call = ["^", "$"].into_iter().map(Regex::new); | ^^^^^^^^^^ error: use of a disallowed method `futures::stream::select_all` - --> $DIR/conf_disallowed_methods.rs:52:31 + --> $DIR/conf_disallowed_methods.rs:53:31 | LL | let same_name_as_module = select_all(vec![empty::<()>()]); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: use of a disallowed method `conf_disallowed_methods::local_fn` - --> $DIR/conf_disallowed_methods.rs:54:5 + --> $DIR/conf_disallowed_methods.rs:55:5 | LL | local_fn(); | ^^^^^^^^^^ error: use of a disallowed method `conf_disallowed_methods::local_mod::f` - --> $DIR/conf_disallowed_methods.rs:55:5 + --> $DIR/conf_disallowed_methods.rs:56:5 | LL | local_mod::f(); | ^^^^^^^^^^^^^^ error: use of a disallowed method `conf_disallowed_methods::Struct::method` - --> $DIR/conf_disallowed_methods.rs:57:5 + --> $DIR/conf_disallowed_methods.rs:58:5 | LL | s.method(); | ^^^^^^^^^^ error: use of a disallowed method `conf_disallowed_methods::Trait::provided_method` - --> $DIR/conf_disallowed_methods.rs:58:5 + --> $DIR/conf_disallowed_methods.rs:59:5 | LL | s.provided_method(); | ^^^^^^^^^^^^^^^^^^^ error: use of a disallowed method `conf_disallowed_methods::Trait::implemented_method` - --> $DIR/conf_disallowed_methods.rs:59:5 + --> $DIR/conf_disallowed_methods.rs:60:5 | LL | s.implemented_method(); | ^^^^^^^^^^^^^^^^^^^^^^ 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 69678057917..8724dc29d29 100644 --- a/tests/ui-toml/toml_unknown_key/conf_unknown_key.stderr +++ b/tests/ui-toml/toml_unknown_key/conf_unknown_key.stderr @@ -4,6 +4,7 @@ error: error reading Clippy's configuration file: unknown field `foobar`, expect allow-dbg-in-tests allow-expect-in-tests allow-mixed-uninlined-format-args + allow-one-hash-in-raw-string allow-print-in-tests allow-private-module-inception allow-unwrap-in-tests @@ -72,6 +73,7 @@ error: error reading Clippy's configuration file: unknown field `barfoo`, expect allow-dbg-in-tests allow-expect-in-tests allow-mixed-uninlined-format-args + allow-one-hash-in-raw-string allow-print-in-tests allow-private-module-inception allow-unwrap-in-tests diff --git a/tests/ui/format.stderr b/tests/ui/format.stderr index f456c11924e..78a11a3354f 100644 --- a/tests/ui/format.stderr +++ b/tests/ui/format.stderr @@ -1,5 +1,5 @@ error: useless use of `format!` - --> $DIR/format.rs:20:5 + --> $DIR/format.rs:21:5 | LL | format!("foo"); | ^^^^^^^^^^^^^^ help: consider using `.to_string()`: `"foo".to_string()` @@ -7,19 +7,19 @@ LL | format!("foo"); = note: `-D clippy::useless-format` implied by `-D warnings` error: useless use of `format!` - --> $DIR/format.rs:21:5 + --> $DIR/format.rs:22:5 | LL | format!("{{}}"); | ^^^^^^^^^^^^^^^ help: consider using `.to_string()`: `"{}".to_string()` error: useless use of `format!` - --> $DIR/format.rs:22:5 + --> $DIR/format.rs:23:5 | LL | format!("{{}} abc {{}}"); | ^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `.to_string()`: `"{} abc {}".to_string()` error: useless use of `format!` - --> $DIR/format.rs:23:5 + --> $DIR/format.rs:24:5 | LL | / format!( LL | | r##"foo {{}} @@ -34,67 +34,67 @@ LL ~ " bar"##.to_string(); | error: useless use of `format!` - --> $DIR/format.rs:28:13 + --> $DIR/format.rs:29:13 | LL | let _ = format!(""); | ^^^^^^^^^^^ help: consider using `String::new()`: `String::new()` error: useless use of `format!` - --> $DIR/format.rs:30:5 + --> $DIR/format.rs:31:5 | LL | format!("{}", "foo"); | ^^^^^^^^^^^^^^^^^^^^ help: consider using `.to_string()`: `"foo".to_string()` error: useless use of `format!` - --> $DIR/format.rs:38:5 + --> $DIR/format.rs:39:5 | LL | format!("{}", arg); | ^^^^^^^^^^^^^^^^^^ help: consider using `.to_string()`: `arg.to_string()` error: useless use of `format!` - --> $DIR/format.rs:68:5 + --> $DIR/format.rs:69:5 | LL | format!("{}", 42.to_string()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `.to_string()`: `42.to_string()` error: useless use of `format!` - --> $DIR/format.rs:70:5 + --> $DIR/format.rs:71:5 | LL | format!("{}", x.display().to_string()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `.to_string()`: `x.display().to_string()` error: useless use of `format!` - --> $DIR/format.rs:74:18 + --> $DIR/format.rs:75:18 | LL | let _ = Some(format!("{}", a + "bar")); | ^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `.to_string()`: `a + "bar"` error: useless use of `format!` - --> $DIR/format.rs:78:22 + --> $DIR/format.rs:79:22 | LL | let _s: String = format!("{}", &*v.join("/n")); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `.to_string()`: `(&*v.join("/n")).to_string()` error: useless use of `format!` - --> $DIR/format.rs:84:13 + --> $DIR/format.rs:85:13 | LL | let _ = format!("{x}"); | ^^^^^^^^^^^^^^ help: consider using `.to_string()`: `x.to_string()` error: useless use of `format!` - --> $DIR/format.rs:86:13 + --> $DIR/format.rs:87:13 | LL | let _ = format!("{y}", y = x); | ^^^^^^^^^^^^^^^^^^^^^ help: consider using `.to_string()`: `x.to_string()` error: useless use of `format!` - --> $DIR/format.rs:90:13 + --> $DIR/format.rs:91:13 | LL | let _ = format!("{abc}"); | ^^^^^^^^^^^^^^^^ help: consider using `.to_string()`: `abc.to_string()` error: useless use of `format!` - --> $DIR/format.rs:92:13 + --> $DIR/format.rs:93:13 | LL | let _ = format!("{xx}"); | ^^^^^^^^^^^^^^^ help: consider using `.to_string()`: `xx.to_string()` diff --git a/tests/ui/needless_raw_string.fixed b/tests/ui/needless_raw_string.fixed new file mode 100644 index 00000000000..ffc1644335d --- /dev/null +++ b/tests/ui/needless_raw_string.fixed @@ -0,0 +1,16 @@ +//@run-rustfix +#![allow(clippy::needless_raw_string_hashes, clippy::no_effect, unused)] +#![warn(clippy::needless_raw_string)] +#![feature(c_str_literals)] + +fn main() { + "aaa"; + r#""aaa""#; + r#"\s"#; + b"aaa"; + br#""aaa""#; + br#"\s"#; + c"aaa"; + cr#""aaa""#; + cr#"\s"#; +} diff --git a/tests/ui/needless_raw_string.rs b/tests/ui/needless_raw_string.rs new file mode 100644 index 00000000000..b06b9a0ec85 --- /dev/null +++ b/tests/ui/needless_raw_string.rs @@ -0,0 +1,16 @@ +//@run-rustfix +#![allow(clippy::needless_raw_string_hashes, clippy::no_effect, unused)] +#![warn(clippy::needless_raw_string)] +#![feature(c_str_literals)] + +fn main() { + r#"aaa"#; + r#""aaa""#; + r#"\s"#; + br#"aaa"#; + br#""aaa""#; + br#"\s"#; + cr#"aaa"#; + cr#""aaa""#; + cr#"\s"#; +} diff --git a/tests/ui/needless_raw_string.stderr b/tests/ui/needless_raw_string.stderr new file mode 100644 index 00000000000..3eb699dea36 --- /dev/null +++ b/tests/ui/needless_raw_string.stderr @@ -0,0 +1,22 @@ +error: unnecessary raw string literal + --> $DIR/needless_raw_string.rs:7:5 + | +LL | r#"aaa"#; + | ^^^^^^^^ help: try: `"aaa"` + | + = note: `-D clippy::needless-raw-string` implied by `-D warnings` + +error: unnecessary raw string literal + --> $DIR/needless_raw_string.rs:10:5 + | +LL | br#"aaa"#; + | ^^^^^^^^^ help: try: `b"aaa"` + +error: unnecessary raw string literal + --> $DIR/needless_raw_string.rs:13:5 + | +LL | cr#"aaa"#; + | ^^^^^^^^^ help: try: `c"aaa"` + +error: aborting due to 3 previous errors + diff --git a/tests/ui/needless_raw_string_hashes.fixed b/tests/ui/needless_raw_string_hashes.fixed index 43616860a2e..1bfb573719d 100644 --- a/tests/ui/needless_raw_string_hashes.fixed +++ b/tests/ui/needless_raw_string_hashes.fixed @@ -1,5 +1,5 @@ //@run-rustfix -#![allow(clippy::no_effect, unused)] +#![allow(clippy::needless_raw_string, clippy::no_effect, unused)] #![warn(clippy::needless_raw_string_hashes)] #![feature(c_str_literals)] diff --git a/tests/ui/needless_raw_string_hashes.rs b/tests/ui/needless_raw_string_hashes.rs index e2d85c52e78..dedd774ea0a 100644 --- a/tests/ui/needless_raw_string_hashes.rs +++ b/tests/ui/needless_raw_string_hashes.rs @@ -1,5 +1,5 @@ //@run-rustfix -#![allow(clippy::no_effect, unused)] +#![allow(clippy::needless_raw_string, clippy::no_effect, unused)] #![warn(clippy::needless_raw_string_hashes)] #![feature(c_str_literals)] diff --git a/tests/ui/regex.rs b/tests/ui/regex.rs index 3b208651946..850c9813462 100644 --- a/tests/ui/regex.rs +++ b/tests/ui/regex.rs @@ -1,4 +1,9 @@ -#![allow(unused, clippy::needless_raw_string_hashes, clippy::needless_borrow)] +#![allow( + unused, + clippy::needless_raw_string, + clippy::needless_raw_string_hashes, + clippy::needless_borrow +)] #![warn(clippy::invalid_regex, clippy::trivial_regex)] extern crate regex; diff --git a/tests/ui/regex.stderr b/tests/ui/regex.stderr index c74dc8108fe..21f1cb44460 100644 --- a/tests/ui/regex.stderr +++ b/tests/ui/regex.stderr @@ -1,5 +1,5 @@ error: trivial regex - --> $DIR/regex.rs:13:45 + --> $DIR/regex.rs:18:45 | LL | let pipe_in_wrong_position = Regex::new("|"); | ^^^ @@ -8,7 +8,7 @@ LL | let pipe_in_wrong_position = Regex::new("|"); = note: `-D clippy::trivial-regex` implied by `-D warnings` error: trivial regex - --> $DIR/regex.rs:14:60 + --> $DIR/regex.rs:19:60 | LL | let pipe_in_wrong_position_builder = RegexBuilder::new("|"); | ^^^ @@ -16,7 +16,7 @@ LL | let pipe_in_wrong_position_builder = RegexBuilder::new("|"); = help: the regex is unlikely to be useful as it is error: regex syntax error: invalid character class range, the start must be <= the end - --> $DIR/regex.rs:15:42 + --> $DIR/regex.rs:20:42 | LL | let wrong_char_ranice = Regex::new("[z-a]"); | ^^^ @@ -24,7 +24,7 @@ LL | let wrong_char_ranice = Regex::new("[z-a]"); = note: `-D clippy::invalid-regex` implied by `-D warnings` error: regex syntax error: invalid character class range, the start must be <= the end - --> $DIR/regex.rs:16:37 + --> $DIR/regex.rs:21:37 | LL | let some_unicode = Regex::new("[é-è]"); | ^^^ @@ -33,13 +33,13 @@ error: regex parse error: ( ^ error: unclosed group - --> $DIR/regex.rs:18:33 + --> $DIR/regex.rs:23:33 | LL | let some_regex = Regex::new(OPENING_PAREN); | ^^^^^^^^^^^^^ error: trivial regex - --> $DIR/regex.rs:20:53 + --> $DIR/regex.rs:25:53 | LL | let binary_pipe_in_wrong_position = BRegex::new("|"); | ^^^ @@ -50,7 +50,7 @@ error: regex parse error: ( ^ error: unclosed group - --> $DIR/regex.rs:21:41 + --> $DIR/regex.rs:26:41 | LL | let some_binary_regex = BRegex::new(OPENING_PAREN); | ^^^^^^^^^^^^^ @@ -59,7 +59,7 @@ error: regex parse error: ( ^ error: unclosed group - --> $DIR/regex.rs:22:56 + --> $DIR/regex.rs:27:56 | LL | let some_binary_regex_builder = BRegexBuilder::new(OPENING_PAREN); | ^^^^^^^^^^^^^ @@ -68,7 +68,7 @@ error: regex parse error: ( ^ error: unclosed group - --> $DIR/regex.rs:34:37 + --> $DIR/regex.rs:39:37 | LL | let set_error = RegexSet::new(&[OPENING_PAREN, r"[a-z]+/.(com|org|net)"]); | ^^^^^^^^^^^^^ @@ -77,7 +77,7 @@ error: regex parse error: ( ^ error: unclosed group - --> $DIR/regex.rs:35:39 + --> $DIR/regex.rs:40:39 | LL | let bset_error = BRegexSet::new(&[OPENING_PAREN, r"[a-z]+/.(com|org|net)"]); | ^^^^^^^^^^^^^ @@ -86,7 +86,7 @@ error: regex parse error: /b/c ^^ error: unrecognized escape sequence - --> $DIR/regex.rs:42:42 + --> $DIR/regex.rs:47:42 | LL | let escaped_string_span = Regex::new("//b//c"); | ^^^^^^^^ @@ -94,19 +94,19 @@ LL | let escaped_string_span = Regex::new("//b//c"); = help: consider using a raw string literal: `r".."` error: regex syntax error: duplicate flag - --> $DIR/regex.rs:44:34 + --> $DIR/regex.rs:49:34 | LL | let aux_span = Regex::new("(?ixi)"); | ^ ^ error: regex syntax error: pattern can match invalid UTF-8 - --> $DIR/regex.rs:49:53 + --> $DIR/regex.rs:54:53 | LL | let invalid_utf8_should_lint = Regex::new("(?-u)."); | ^ error: trivial regex - --> $DIR/regex.rs:53:33 + --> $DIR/regex.rs:58:33 | LL | let trivial_eq = Regex::new("^foobar$"); | ^^^^^^^^^^ @@ -114,7 +114,7 @@ LL | let trivial_eq = Regex::new("^foobar$"); = help: consider using `==` on `str`s error: trivial regex - --> $DIR/regex.rs:55:48 + --> $DIR/regex.rs:60:48 | LL | let trivial_eq_builder = RegexBuilder::new("^foobar$"); | ^^^^^^^^^^ @@ -122,7 +122,7 @@ LL | let trivial_eq_builder = RegexBuilder::new("^foobar$"); = help: consider using `==` on `str`s error: trivial regex - --> $DIR/regex.rs:57:42 + --> $DIR/regex.rs:62:42 | LL | let trivial_starts_with = Regex::new("^foobar"); | ^^^^^^^^^ @@ -130,7 +130,7 @@ LL | let trivial_starts_with = Regex::new("^foobar"); = help: consider using `str::starts_with` error: trivial regex - --> $DIR/regex.rs:59:40 + --> $DIR/regex.rs:64:40 | LL | let trivial_ends_with = Regex::new("foobar$"); | ^^^^^^^^^ @@ -138,7 +138,7 @@ LL | let trivial_ends_with = Regex::new("foobar$"); = help: consider using `str::ends_with` error: trivial regex - --> $DIR/regex.rs:61:39 + --> $DIR/regex.rs:66:39 | LL | let trivial_contains = Regex::new("foobar"); | ^^^^^^^^ @@ -146,7 +146,7 @@ LL | let trivial_contains = Regex::new("foobar"); = help: consider using `str::contains` error: trivial regex - --> $DIR/regex.rs:63:39 + --> $DIR/regex.rs:68:39 | LL | let trivial_contains = Regex::new(NOT_A_REAL_REGEX); | ^^^^^^^^^^^^^^^^ @@ -154,7 +154,7 @@ LL | let trivial_contains = Regex::new(NOT_A_REAL_REGEX); = help: consider using `str::contains` error: trivial regex - --> $DIR/regex.rs:65:40 + --> $DIR/regex.rs:70:40 | LL | let trivial_backslash = Regex::new("a//.b"); | ^^^^^^^ @@ -162,7 +162,7 @@ LL | let trivial_backslash = Regex::new("a//.b"); = help: consider using `str::contains` error: trivial regex - --> $DIR/regex.rs:68:36 + --> $DIR/regex.rs:73:36 | LL | let trivial_empty = Regex::new(""); | ^^ @@ -170,7 +170,7 @@ LL | let trivial_empty = Regex::new(""); = help: the regex is unlikely to be useful as it is error: trivial regex - --> $DIR/regex.rs:70:36 + --> $DIR/regex.rs:75:36 | LL | let trivial_empty = Regex::new("^"); | ^^^ @@ -178,7 +178,7 @@ LL | let trivial_empty = Regex::new("^"); = help: the regex is unlikely to be useful as it is error: trivial regex - --> $DIR/regex.rs:72:36 + --> $DIR/regex.rs:77:36 | LL | let trivial_empty = Regex::new("^$"); | ^^^^ @@ -186,7 +186,7 @@ LL | let trivial_empty = Regex::new("^$"); = help: consider using `str::is_empty` error: trivial regex - --> $DIR/regex.rs:74:44 + --> $DIR/regex.rs:79:44 | LL | let binary_trivial_empty = BRegex::new("^$"); | ^^^^ diff --git a/tests/ui/single_char_add_str.fixed b/tests/ui/single_char_add_str.fixed index 2d4c0841219..ee0177776bf 100644 --- a/tests/ui/single_char_add_str.fixed +++ b/tests/ui/single_char_add_str.fixed @@ -1,6 +1,6 @@ //@run-rustfix #![warn(clippy::single_char_add_str)] -#![allow(clippy::needless_raw_string_hashes)] +#![allow(clippy::needless_raw_string, clippy::needless_raw_string_hashes)] macro_rules! get_string { () => { diff --git a/tests/ui/single_char_add_str.rs b/tests/ui/single_char_add_str.rs index 463b19da09e..e3b7d8597c2 100644 --- a/tests/ui/single_char_add_str.rs +++ b/tests/ui/single_char_add_str.rs @@ -1,6 +1,6 @@ //@run-rustfix #![warn(clippy::single_char_add_str)] -#![allow(clippy::needless_raw_string_hashes)] +#![allow(clippy::needless_raw_string, clippy::needless_raw_string_hashes)] macro_rules! get_string { () => { diff --git a/tests/ui/single_char_pattern.fixed b/tests/ui/single_char_pattern.fixed index f1dc3ea9894..920d43318ae 100644 --- a/tests/ui/single_char_pattern.fixed +++ b/tests/ui/single_char_pattern.fixed @@ -1,6 +1,6 @@ //@run-rustfix -#![allow(clippy::needless_raw_string_hashes, unused_must_use)] +#![allow(clippy::needless_raw_string, clippy::needless_raw_string_hashes, unused_must_use)] use std::collections::HashSet; diff --git a/tests/ui/single_char_pattern.rs b/tests/ui/single_char_pattern.rs index 00b38498001..3a53084e30b 100644 --- a/tests/ui/single_char_pattern.rs +++ b/tests/ui/single_char_pattern.rs @@ -1,6 +1,6 @@ //@run-rustfix -#![allow(clippy::needless_raw_string_hashes, unused_must_use)] +#![allow(clippy::needless_raw_string, clippy::needless_raw_string_hashes, unused_must_use)] use std::collections::HashSet; diff --git a/tests/ui/write_literal_2.rs b/tests/ui/write_literal_2.rs index 55a11daa1d3..1d9b9603bd8 100644 --- a/tests/ui/write_literal_2.rs +++ b/tests/ui/write_literal_2.rs @@ -1,5 +1,5 @@ #![allow(unused_must_use)] -#![warn(clippy::write_literal)] +#![warn(clippy::needless_raw_string, clippy::write_literal)] use std::io::Write; diff --git a/tests/ui/write_literal_2.stderr b/tests/ui/write_literal_2.stderr index bf22738480d..a69d031b011 100644 --- a/tests/ui/write_literal_2.stderr +++ b/tests/ui/write_literal_2.stderr @@ -1,3 +1,11 @@ +error: unnecessary raw string literal + --> $DIR/write_literal_2.rs:10:24 + | +LL | writeln!(v, r"{}", r"{hello}"); + | ^^^^^^^^^^ help: try: `"{hello}"` + | + = note: `-D clippy::needless-raw-string` implied by `-D warnings` + error: literal with an empty format string --> $DIR/write_literal_2.rs:9:23 | @@ -186,5 +194,5 @@ error: literal with an empty format string LL | writeln!(v, r#"{}{}"#, '#', '"'); // hard mode | ^^^ -error: aborting due to 17 previous errors +error: aborting due to 18 previous errors From ec765d951611c680e9351cd04c959568979ce231 Mon Sep 17 00:00:00 2001 From: Catherine <114838443+Centri3@users.noreply.github.com> Date: Thu, 8 Jun 2023 07:24:16 -0500 Subject: [PATCH 275/310] Update raw_strings.rs --- clippy_lints/src/raw_strings.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clippy_lints/src/raw_strings.rs b/clippy_lints/src/raw_strings.rs index 52814693f3c..81afe18ebc6 100644 --- a/clippy_lints/src/raw_strings.rs +++ b/clippy_lints/src/raw_strings.rs @@ -71,7 +71,7 @@ impl EarlyLintPass for RawStrings { return; } - #[allow(clippy::cast_possible_truncation)] + #[expect(clippy::cast_possible_truncation)] let req = lit.symbol.as_str().as_bytes() .split(|&b| b == b'"') .skip(1) From cb52d19ce106f2ba2c4e1cca860757170c1db2ed Mon Sep 17 00:00:00 2001 From: Centri3 <114838443+Centri3@users.noreply.github.com> Date: Fri, 9 Jun 2023 21:40:09 -0500 Subject: [PATCH 276/310] don't lint `needless_raw_string_hashes` when it's unnecessary --- CHANGELOG.md | 1 + book/src/lint_configuration.md | 10 +++++++++ clippy_lints/src/raw_strings.rs | 26 ++++++++++++---------- tests/ui/needless_raw_string_hashes.fixed | 6 ++--- tests/ui/needless_raw_string_hashes.stderr | 24 +++----------------- 5 files changed, 31 insertions(+), 36 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 5b17072df40..e81e87bf077 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5414,4 +5414,5 @@ Released 2018-09-13 [`min-ident-chars-threshold`]: https://doc.rust-lang.org/clippy/lint_configuration.html#min-ident-chars-threshold [`accept-comment-above-statement`]: https://doc.rust-lang.org/clippy/lint_configuration.html#accept-comment-above-statement [`accept-comment-above-attributes`]: https://doc.rust-lang.org/clippy/lint_configuration.html#accept-comment-above-attributes +[`allow-one-hash-in-raw-string`]: https://doc.rust-lang.org/clippy/lint_configuration.html#allow-one-hash-in-raw-string diff --git a/book/src/lint_configuration.md b/book/src/lint_configuration.md index 9bf7b1949c4..efb48131502 100644 --- a/book/src/lint_configuration.md +++ b/book/src/lint_configuration.md @@ -717,3 +717,13 @@ Whether to accept a safety comment to be placed above the attributes for the `un * [`undocumented_unsafe_blocks`](https://rust-lang.github.io/rust-clippy/master/index.html#undocumented_unsafe_blocks) +## `allow-one-hash-in-raw-string` +Whether to allow `r#""#` when `r""` can be used + +**Default Value:** `false` (`bool`) + +--- +**Affected lints:** +* [`unnecessary_raw_string_hashes`](https://rust-lang.github.io/rust-clippy/master/index.html#unnecessary_raw_string_hashes) + + diff --git a/clippy_lints/src/raw_strings.rs b/clippy_lints/src/raw_strings.rs index 81afe18ebc6..b465c7566f0 100644 --- a/clippy_lints/src/raw_strings.rs +++ b/clippy_lints/src/raw_strings.rs @@ -71,6 +71,20 @@ impl EarlyLintPass for RawStrings { return; } + if !lit.symbol.as_str().contains(['\\', '"']) { + span_lint_and_sugg( + cx, + NEEDLESS_RAW_STRING, + expr.span, + "unnecessary raw string literal", + "try", + format!("{}\"{}\"", prefix.replace('r', ""), lit.symbol), + Applicability::MachineApplicable, + ); + + return; + } + #[expect(clippy::cast_possible_truncation)] let req = lit.symbol.as_str().as_bytes() .split(|&b| b == b'"') @@ -92,18 +106,6 @@ impl EarlyLintPass for RawStrings { Applicability::MachineApplicable, ); } - - if !lit.symbol.as_str().contains(['\\', '"']) { - span_lint_and_sugg( - cx, - NEEDLESS_RAW_STRING, - expr.span, - "unnecessary raw string literal", - "try", - format!("{}\"{}\"", prefix.replace('r', ""), lit.symbol), - Applicability::MachineApplicable, - ); - } } } } diff --git a/tests/ui/needless_raw_string_hashes.fixed b/tests/ui/needless_raw_string_hashes.fixed index 1bfb573719d..8d443dabcb7 100644 --- a/tests/ui/needless_raw_string_hashes.fixed +++ b/tests/ui/needless_raw_string_hashes.fixed @@ -4,15 +4,15 @@ #![feature(c_str_literals)] fn main() { - r"aaa"; + r#"aaa"#; r#"Hello "world"!"#; r####" "### "## "# "####; r###" "aa" "# "## "###; - br"aaa"; + br#"aaa"#; br#"Hello "world"!"#; br####" "### "## "# "####; br###" "aa" "# "## "###; - cr"aaa"; + cr#"aaa"#; cr#"Hello "world"!"#; cr####" "### "## "# "####; cr###" "aa" "# "## "###; diff --git a/tests/ui/needless_raw_string_hashes.stderr b/tests/ui/needless_raw_string_hashes.stderr index 44b878cec40..dff47a2d042 100644 --- a/tests/ui/needless_raw_string_hashes.stderr +++ b/tests/ui/needless_raw_string_hashes.stderr @@ -1,16 +1,10 @@ -error: unnecessary hashes around raw string literal - --> $DIR/needless_raw_string_hashes.rs:7:5 - | -LL | r#"aaa"#; - | ^^^^^^^^ help: try: `r"aaa"` - | - = note: `-D clippy::needless-raw-string-hashes` implied by `-D warnings` - error: unnecessary hashes around raw string literal --> $DIR/needless_raw_string_hashes.rs:8:5 | LL | r##"Hello "world"!"##; | ^^^^^^^^^^^^^^^^^^^^^ help: try: `r#"Hello "world"!"#` + | + = note: `-D clippy::needless-raw-string-hashes` implied by `-D warnings` error: unnecessary hashes around raw string literal --> $DIR/needless_raw_string_hashes.rs:9:5 @@ -24,12 +18,6 @@ error: unnecessary hashes around raw string literal LL | r######" "aa" "# "## "######; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `r###" "aa" "# "## "###` -error: unnecessary hashes around raw string literal - --> $DIR/needless_raw_string_hashes.rs:11:5 - | -LL | br#"aaa"#; - | ^^^^^^^^^ help: try: `br"aaa"` - error: unnecessary hashes around raw string literal --> $DIR/needless_raw_string_hashes.rs:12:5 | @@ -48,12 +36,6 @@ error: unnecessary hashes around raw string literal LL | br######" "aa" "# "## "######; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `br###" "aa" "# "## "###` -error: unnecessary hashes around raw string literal - --> $DIR/needless_raw_string_hashes.rs:15:5 - | -LL | cr#"aaa"#; - | ^^^^^^^^^ help: try: `cr"aaa"` - error: unnecessary hashes around raw string literal --> $DIR/needless_raw_string_hashes.rs:16:5 | @@ -72,5 +54,5 @@ error: unnecessary hashes around raw string literal LL | cr######" "aa" "# "## "######; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `cr###" "aa" "# "## "###` -error: aborting due to 12 previous errors +error: aborting due to 9 previous errors From 8cb6c86996a8ea9e35a4e1c0c38a5a4da00b95dc Mon Sep 17 00:00:00 2001 From: Centri3 <114838443+Centri3@users.noreply.github.com> Date: Thu, 15 Jun 2023 14:15:10 -0500 Subject: [PATCH 277/310] change category and refactor Update raw_strings.rs Revert "new lints for visibility" This reverts commit 0e5a537d209727169769dc19cf86aef27122c092. new lints for visibility --- CHANGELOG.md | 4 +- book/src/lint_configuration.md | 2 +- clippy_lints/src/declared_lints.rs | 2 +- clippy_lints/src/lib.rs | 6 ++ clippy_lints/src/raw_strings.rs | 64 ++++++++++++++----- clippy_lints/src/utils/conf.rs | 2 +- tests/compile-test.rs | 2 +- .../conf_disallowed_methods.rs | 2 +- .../toml_unknown_key/conf_unknown_key.stderr | 4 +- tests/ui/needless_raw_string.fixed | 2 +- tests/ui/needless_raw_string.rs | 2 +- tests/ui/needless_raw_string.stderr | 2 +- tests/ui/needless_raw_string_hashes.fixed | 2 +- tests/ui/needless_raw_string_hashes.rs | 2 +- tests/ui/regex.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/write_literal_2.rs | 2 +- tests/ui/write_literal_2.stderr | 2 +- 21 files changed, 75 insertions(+), 37 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index e81e87bf077..a7284a70a1f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5048,8 +5048,8 @@ Released 2018-09-13 [`needless_pass_by_value`]: https://rust-lang.github.io/rust-clippy/master/index.html#needless_pass_by_value [`needless_question_mark`]: https://rust-lang.github.io/rust-clippy/master/index.html#needless_question_mark [`needless_range_loop`]: https://rust-lang.github.io/rust-clippy/master/index.html#needless_range_loop -[`needless_raw_string`]: https://rust-lang.github.io/rust-clippy/master/index.html#needless_raw_string [`needless_raw_string_hashes`]: https://rust-lang.github.io/rust-clippy/master/index.html#needless_raw_string_hashes +[`needless_raw_strings`]: https://rust-lang.github.io/rust-clippy/master/index.html#needless_raw_strings [`needless_return`]: https://rust-lang.github.io/rust-clippy/master/index.html#needless_return [`needless_splitn`]: https://rust-lang.github.io/rust-clippy/master/index.html#needless_splitn [`needless_update`]: https://rust-lang.github.io/rust-clippy/master/index.html#needless_update @@ -5414,5 +5414,5 @@ Released 2018-09-13 [`min-ident-chars-threshold`]: https://doc.rust-lang.org/clippy/lint_configuration.html#min-ident-chars-threshold [`accept-comment-above-statement`]: https://doc.rust-lang.org/clippy/lint_configuration.html#accept-comment-above-statement [`accept-comment-above-attributes`]: https://doc.rust-lang.org/clippy/lint_configuration.html#accept-comment-above-attributes -[`allow-one-hash-in-raw-string`]: https://doc.rust-lang.org/clippy/lint_configuration.html#allow-one-hash-in-raw-string +[`allow-one-hash-in-raw-strings`]: https://doc.rust-lang.org/clippy/lint_configuration.html#allow-one-hash-in-raw-strings diff --git a/book/src/lint_configuration.md b/book/src/lint_configuration.md index efb48131502..293195e858c 100644 --- a/book/src/lint_configuration.md +++ b/book/src/lint_configuration.md @@ -717,7 +717,7 @@ Whether to accept a safety comment to be placed above the attributes for the `un * [`undocumented_unsafe_blocks`](https://rust-lang.github.io/rust-clippy/master/index.html#undocumented_unsafe_blocks) -## `allow-one-hash-in-raw-string` +## `allow-one-hash-in-raw-strings` Whether to allow `r#""#` when `r""` can be used **Default Value:** `false` (`bool`) diff --git a/clippy_lints/src/declared_lints.rs b/clippy_lints/src/declared_lints.rs index c67ed14b3b0..dbd4a53d836 100644 --- a/clippy_lints/src/declared_lints.rs +++ b/clippy_lints/src/declared_lints.rs @@ -540,7 +540,7 @@ pub(crate) static LINTS: &[&crate::LintInfo] = &[ crate::ranges::RANGE_MINUS_ONE_INFO, crate::ranges::RANGE_PLUS_ONE_INFO, crate::ranges::REVERSED_EMPTY_RANGES_INFO, - crate::raw_strings::NEEDLESS_RAW_STRING_INFO, + crate::raw_strings::NEEDLESS_RAW_STRINGS_INFO, crate::raw_strings::NEEDLESS_RAW_STRING_HASHES_INFO, crate::rc_clone_in_vec_init::RC_CLONE_IN_VEC_INIT_INFO, crate::read_zero_byte_vec::READ_ZERO_BYTE_VEC_INFO, diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index e1a7eedd93e..d926b7b84ea 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -1062,6 +1062,12 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: def_id_to_usage: rustc_data_structures::fx::FxHashMap::default(), }) }); + let needless_raw_string_hashes_allow_one = conf.allow_one_hash_in_raw_strings; + store.register_early_pass(move || { + Box::new(raw_strings::RawStrings { + needless_raw_string_hashes_allow_one, + }) + }); // add lints here, do not remove this comment, it's used in `new_lint` } diff --git a/clippy_lints/src/raw_strings.rs b/clippy_lints/src/raw_strings.rs index b465c7566f0..f45bb1ef3e1 100644 --- a/clippy_lints/src/raw_strings.rs +++ b/clippy_lints/src/raw_strings.rs @@ -1,3 +1,5 @@ +use std::{iter::once, ops::ControlFlow}; + use clippy_utils::{diagnostics::span_lint_and_sugg, source::snippet}; use rustc_ast::{ ast::{Expr, ExprKind}, @@ -13,7 +15,8 @@ declare_clippy_lint! { /// Checks for raw string literals where a string literal can be used instead. /// /// ### Why is this bad? - /// It's just unnecessary. + /// It's just unnecessary, but there are many cases where using a raw string literal is more + /// idiomatic than a string literal, so it's opt-in. /// /// ### Example /// ```rust @@ -24,8 +27,8 @@ declare_clippy_lint! { /// let r = "Hello, world!"; /// ``` #[clippy::version = "1.72.0"] - pub NEEDLESS_RAW_STRING, - complexity, + pub NEEDLESS_RAW_STRINGS, + restriction, "suggests using a string literal when a raw string literal is unnecessary" } declare_clippy_lint! { @@ -46,10 +49,10 @@ declare_clippy_lint! { /// ``` #[clippy::version = "1.72.0"] pub NEEDLESS_RAW_STRING_HASHES, - complexity, + style, "suggests reducing the number of hashes around a raw string literal" } -impl_lint_pass!(RawStrings => [NEEDLESS_RAW_STRING, NEEDLESS_RAW_STRING_HASHES]); +impl_lint_pass!(RawStrings => [NEEDLESS_RAW_STRINGS, NEEDLESS_RAW_STRING_HASHES]); pub struct RawStrings { pub needless_raw_string_hashes_allow_one: bool, @@ -59,8 +62,9 @@ impl EarlyLintPass for RawStrings { fn check_expr(&mut self, cx: &EarlyContext<'_>, expr: &Expr) { if !in_external_macro(cx.sess(), expr.span) && let ExprKind::Lit(lit) = expr.kind - && let LitKind::StrRaw(num) | LitKind::ByteStrRaw(num) | LitKind::CStrRaw(num) = lit.kind + && let LitKind::StrRaw(max) | LitKind::ByteStrRaw(max) | LitKind::CStrRaw(max) = lit.kind { + let str = lit.symbol.as_str(); let prefix = match lit.kind { LitKind::StrRaw(..) => "r", LitKind::ByteStrRaw(..) => "br", @@ -71,10 +75,10 @@ impl EarlyLintPass for RawStrings { return; } - if !lit.symbol.as_str().contains(['\\', '"']) { + if !str.contains(['\\', '"']) { span_lint_and_sugg( cx, - NEEDLESS_RAW_STRING, + NEEDLESS_RAW_STRINGS, expr.span, "unnecessary raw string literal", "try", @@ -85,15 +89,43 @@ impl EarlyLintPass for RawStrings { return; } - #[expect(clippy::cast_possible_truncation)] - let req = lit.symbol.as_str().as_bytes() - .split(|&b| b == b'"') - .skip(1) - .map(|bs| 1 + bs.iter().take_while(|&&b| b == b'#').count() as u8) - .max() - .unwrap_or(0); + let req = { + let mut following_quote = false; + let mut req = 0; + // `once` so a raw string ending in hashes is still checked + let num = str.as_bytes().iter().chain(once(&0)).try_fold(0u8, |acc, &b| { + match b { + b'"' => (following_quote, req) = (true, 1), + // I'm a bit surprised the compiler didn't optimize this out, there's no + // branch but it still ends up doing an unnecessary comparison, it's: + // - cmp r9b,1h + // - sbb cl,-1h + // which will add 1 if it's true. With this change, it becomes: + // - add cl,r9b + // isn't that so much nicer? + b'#' => req += u8::from(following_quote), + _ => { + if following_quote { + following_quote = false; - if req < num { + if req == max { + return ControlFlow::Break(req); + } + + return ControlFlow::Continue(acc.max(req)); + } + }, + } + + ControlFlow::Continue(acc) + }); + + match num { + ControlFlow::Continue(num) | ControlFlow::Break(num) => num, + } + }; + + if req < max { let hashes = "#".repeat(req as usize); span_lint_and_sugg( diff --git a/clippy_lints/src/utils/conf.rs b/clippy_lints/src/utils/conf.rs index 9f88960f7ce..9be94920f96 100644 --- a/clippy_lints/src/utils/conf.rs +++ b/clippy_lints/src/utils/conf.rs @@ -550,7 +550,7 @@ define_Conf! { /// Lint: UNNECESSARY_RAW_STRING_HASHES. /// /// Whether to allow `r#""#` when `r""` can be used - (allow_one_hash_in_raw_string: bool = false), + (allow_one_hash_in_raw_strings: bool = false), } /// Search for the configuration file. diff --git a/tests/compile-test.rs b/tests/compile-test.rs index c5e8622bc85..13013f646e5 100644 --- a/tests/compile-test.rs +++ b/tests/compile-test.rs @@ -50,7 +50,7 @@ fn base_config(test_dir: &str) -> compiletest::Config { config.program.args.push("-Dwarnings".into()); // Normalize away slashes in windows paths. - config.stderr_filter(r#"\\"#, "/"); + config.stderr_filter(r"\\", "/"); //config.build_base = profile_path.join("test").join(test_dir); config.program.program = profile_path.join(if cfg!(windows) { 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 d26bc72787b..63fdea710cb 100644 --- a/tests/ui-toml/toml_disallowed_methods/conf_disallowed_methods.rs +++ b/tests/ui-toml/toml_disallowed_methods/conf_disallowed_methods.rs @@ -1,6 +1,6 @@ //@compile-flags: --crate-name conf_disallowed_methods -#![allow(clippy::needless_raw_string)] +#![allow(clippy::needless_raw_strings)] #![warn(clippy::disallowed_methods)] #![allow(clippy::useless_vec)] 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 8724dc29d29..6ba26e97730 100644 --- a/tests/ui-toml/toml_unknown_key/conf_unknown_key.stderr +++ b/tests/ui-toml/toml_unknown_key/conf_unknown_key.stderr @@ -4,7 +4,7 @@ error: error reading Clippy's configuration file: unknown field `foobar`, expect allow-dbg-in-tests allow-expect-in-tests allow-mixed-uninlined-format-args - allow-one-hash-in-raw-string + allow-one-hash-in-raw-strings allow-print-in-tests allow-private-module-inception allow-unwrap-in-tests @@ -73,7 +73,7 @@ error: error reading Clippy's configuration file: unknown field `barfoo`, expect allow-dbg-in-tests allow-expect-in-tests allow-mixed-uninlined-format-args - allow-one-hash-in-raw-string + allow-one-hash-in-raw-strings allow-print-in-tests allow-private-module-inception allow-unwrap-in-tests diff --git a/tests/ui/needless_raw_string.fixed b/tests/ui/needless_raw_string.fixed index ffc1644335d..6438e46977b 100644 --- a/tests/ui/needless_raw_string.fixed +++ b/tests/ui/needless_raw_string.fixed @@ -1,6 +1,6 @@ //@run-rustfix #![allow(clippy::needless_raw_string_hashes, clippy::no_effect, unused)] -#![warn(clippy::needless_raw_string)] +#![warn(clippy::needless_raw_strings)] #![feature(c_str_literals)] fn main() { diff --git a/tests/ui/needless_raw_string.rs b/tests/ui/needless_raw_string.rs index b06b9a0ec85..f7ddc68265e 100644 --- a/tests/ui/needless_raw_string.rs +++ b/tests/ui/needless_raw_string.rs @@ -1,6 +1,6 @@ //@run-rustfix #![allow(clippy::needless_raw_string_hashes, clippy::no_effect, unused)] -#![warn(clippy::needless_raw_string)] +#![warn(clippy::needless_raw_strings)] #![feature(c_str_literals)] fn main() { diff --git a/tests/ui/needless_raw_string.stderr b/tests/ui/needless_raw_string.stderr index 3eb699dea36..0179978b7b0 100644 --- a/tests/ui/needless_raw_string.stderr +++ b/tests/ui/needless_raw_string.stderr @@ -4,7 +4,7 @@ error: unnecessary raw string literal LL | r#"aaa"#; | ^^^^^^^^ help: try: `"aaa"` | - = note: `-D clippy::needless-raw-string` implied by `-D warnings` + = note: `-D clippy::needless-raw-strings` implied by `-D warnings` error: unnecessary raw string literal --> $DIR/needless_raw_string.rs:10:5 diff --git a/tests/ui/needless_raw_string_hashes.fixed b/tests/ui/needless_raw_string_hashes.fixed index 8d443dabcb7..e4d7d8fb017 100644 --- a/tests/ui/needless_raw_string_hashes.fixed +++ b/tests/ui/needless_raw_string_hashes.fixed @@ -1,5 +1,5 @@ //@run-rustfix -#![allow(clippy::needless_raw_string, clippy::no_effect, unused)] +#![allow(clippy::no_effect, unused)] #![warn(clippy::needless_raw_string_hashes)] #![feature(c_str_literals)] diff --git a/tests/ui/needless_raw_string_hashes.rs b/tests/ui/needless_raw_string_hashes.rs index dedd774ea0a..e2d85c52e78 100644 --- a/tests/ui/needless_raw_string_hashes.rs +++ b/tests/ui/needless_raw_string_hashes.rs @@ -1,5 +1,5 @@ //@run-rustfix -#![allow(clippy::needless_raw_string, clippy::no_effect, unused)] +#![allow(clippy::no_effect, unused)] #![warn(clippy::needless_raw_string_hashes)] #![feature(c_str_literals)] diff --git a/tests/ui/regex.rs b/tests/ui/regex.rs index 850c9813462..89d1d949454 100644 --- a/tests/ui/regex.rs +++ b/tests/ui/regex.rs @@ -1,6 +1,6 @@ #![allow( unused, - clippy::needless_raw_string, + clippy::needless_raw_strings, clippy::needless_raw_string_hashes, clippy::needless_borrow )] diff --git a/tests/ui/single_char_add_str.fixed b/tests/ui/single_char_add_str.fixed index ee0177776bf..cb301c8bc15 100644 --- a/tests/ui/single_char_add_str.fixed +++ b/tests/ui/single_char_add_str.fixed @@ -1,6 +1,6 @@ //@run-rustfix #![warn(clippy::single_char_add_str)] -#![allow(clippy::needless_raw_string, clippy::needless_raw_string_hashes)] +#![allow(clippy::needless_raw_strings, clippy::needless_raw_string_hashes)] macro_rules! get_string { () => { diff --git a/tests/ui/single_char_add_str.rs b/tests/ui/single_char_add_str.rs index e3b7d8597c2..99baf35ac29 100644 --- a/tests/ui/single_char_add_str.rs +++ b/tests/ui/single_char_add_str.rs @@ -1,6 +1,6 @@ //@run-rustfix #![warn(clippy::single_char_add_str)] -#![allow(clippy::needless_raw_string, clippy::needless_raw_string_hashes)] +#![allow(clippy::needless_raw_strings, clippy::needless_raw_string_hashes)] macro_rules! get_string { () => { diff --git a/tests/ui/single_char_pattern.fixed b/tests/ui/single_char_pattern.fixed index 920d43318ae..7ae62231acc 100644 --- a/tests/ui/single_char_pattern.fixed +++ b/tests/ui/single_char_pattern.fixed @@ -1,6 +1,6 @@ //@run-rustfix -#![allow(clippy::needless_raw_string, clippy::needless_raw_string_hashes, unused_must_use)] +#![allow(clippy::needless_raw_strings, clippy::needless_raw_string_hashes, unused_must_use)] use std::collections::HashSet; diff --git a/tests/ui/single_char_pattern.rs b/tests/ui/single_char_pattern.rs index 3a53084e30b..0604624e767 100644 --- a/tests/ui/single_char_pattern.rs +++ b/tests/ui/single_char_pattern.rs @@ -1,6 +1,6 @@ //@run-rustfix -#![allow(clippy::needless_raw_string, clippy::needless_raw_string_hashes, unused_must_use)] +#![allow(clippy::needless_raw_strings, clippy::needless_raw_string_hashes, unused_must_use)] use std::collections::HashSet; diff --git a/tests/ui/write_literal_2.rs b/tests/ui/write_literal_2.rs index 1d9b9603bd8..805127e2750 100644 --- a/tests/ui/write_literal_2.rs +++ b/tests/ui/write_literal_2.rs @@ -1,5 +1,5 @@ #![allow(unused_must_use)] -#![warn(clippy::needless_raw_string, clippy::write_literal)] +#![warn(clippy::needless_raw_strings, clippy::write_literal)] use std::io::Write; diff --git a/tests/ui/write_literal_2.stderr b/tests/ui/write_literal_2.stderr index a69d031b011..18591250aad 100644 --- a/tests/ui/write_literal_2.stderr +++ b/tests/ui/write_literal_2.stderr @@ -4,7 +4,7 @@ error: unnecessary raw string literal LL | writeln!(v, r"{}", r"{hello}"); | ^^^^^^^^^^ help: try: `"{hello}"` | - = note: `-D clippy::needless-raw-string` implied by `-D warnings` + = note: `-D clippy::needless-raw-strings` implied by `-D warnings` error: literal with an empty format string --> $DIR/write_literal_2.rs:9:23 From 9a8347ded53a14fb381f404abd32302e59ef20a9 Mon Sep 17 00:00:00 2001 From: Catherine <114838443+Centri3@users.noreply.github.com> Date: Fri, 23 Jun 2023 06:02:39 -0500 Subject: [PATCH 278/310] New lint [`redundant_rest_pattern`] --- CHANGELOG.md | 1 + clippy_lints/src/declared_lints.rs | 1 + clippy_lints/src/methods/needless_collect.rs | 2 +- clippy_lints/src/methods/str_splitn.rs | 2 +- clippy_lints/src/misc_early/mod.rs | 31 ++++++++++++++ .../src/misc_early/redundant_rest_pattern.rs | 26 ++++++++++++ clippy_utils/src/sugg.rs | 2 +- tests/ui/manual_let_else_match.rs | 2 +- tests/ui/match_on_vec_items.rs | 2 +- tests/ui/redundant_rest_pattern.fixed | 27 +++++++++++++ tests/ui/redundant_rest_pattern.rs | 27 +++++++++++++ tests/ui/redundant_rest_pattern.stderr | 40 +++++++++++++++++++ 12 files changed, 158 insertions(+), 5 deletions(-) create mode 100644 clippy_lints/src/misc_early/redundant_rest_pattern.rs create mode 100644 tests/ui/redundant_rest_pattern.fixed create mode 100644 tests/ui/redundant_rest_pattern.rs create mode 100644 tests/ui/redundant_rest_pattern.stderr diff --git a/CHANGELOG.md b/CHANGELOG.md index 941efb1abff..6350d9c118f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5141,6 +5141,7 @@ Released 2018-09-13 [`redundant_pattern`]: https://rust-lang.github.io/rust-clippy/master/index.html#redundant_pattern [`redundant_pattern_matching`]: https://rust-lang.github.io/rust-clippy/master/index.html#redundant_pattern_matching [`redundant_pub_crate`]: https://rust-lang.github.io/rust-clippy/master/index.html#redundant_pub_crate +[`redundant_rest_pattern`]: https://rust-lang.github.io/rust-clippy/master/index.html#redundant_rest_pattern [`redundant_slicing`]: https://rust-lang.github.io/rust-clippy/master/index.html#redundant_slicing [`redundant_static_lifetimes`]: https://rust-lang.github.io/rust-clippy/master/index.html#redundant_static_lifetimes [`redundant_type_annotations`]: https://rust-lang.github.io/rust-clippy/master/index.html#redundant_type_annotations diff --git a/clippy_lints/src/declared_lints.rs b/clippy_lints/src/declared_lints.rs index 0eec18a91bc..13b0f9d5ee3 100644 --- a/clippy_lints/src/declared_lints.rs +++ b/clippy_lints/src/declared_lints.rs @@ -431,6 +431,7 @@ pub(crate) static LINTS: &[&crate::LintInfo] = &[ crate::misc_early::DUPLICATE_UNDERSCORE_ARGUMENT_INFO, crate::misc_early::MIXED_CASE_HEX_LITERALS_INFO, crate::misc_early::REDUNDANT_PATTERN_INFO, + crate::misc_early::REDUNDANT_REST_PATTERN_INFO, crate::misc_early::SEPARATED_LITERAL_SUFFIX_INFO, crate::misc_early::UNNEEDED_FIELD_PATTERN_INFO, crate::misc_early::UNNEEDED_WILDCARD_PATTERN_INFO, diff --git a/clippy_lints/src/methods/needless_collect.rs b/clippy_lints/src/methods/needless_collect.rs index 99f810c27cf..3c3919dffe5 100644 --- a/clippy_lints/src/methods/needless_collect.rs +++ b/clippy_lints/src/methods/needless_collect.rs @@ -322,7 +322,7 @@ impl<'tcx> Visitor<'tcx> for IterFunctionVisitor<'_, 'tcx> { fn visit_expr(&mut self, expr: &'tcx Expr<'tcx>) { // Check function calls on our collection - if let ExprKind::MethodCall(method_name, recv, [args @ ..], _) = &expr.kind { + if let ExprKind::MethodCall(method_name, recv, args, _) = &expr.kind { if method_name.ident.name == sym!(collect) && is_trait_method(self.cx, expr, sym::Iterator) { self.current_mutably_captured_ids = get_captured_ids(self.cx, self.cx.typeck_results().expr_ty(recv)); self.visit_expr(recv); diff --git a/clippy_lints/src/methods/str_splitn.rs b/clippy_lints/src/methods/str_splitn.rs index 5ea12c44184..88a3c2620a4 100644 --- a/clippy_lints/src/methods/str_splitn.rs +++ b/clippy_lints/src/methods/str_splitn.rs @@ -289,7 +289,7 @@ fn parse_iter_usage<'tcx>( ) -> Option { let (kind, span) = match iter.next() { Some((_, Node::Expr(e))) if e.span.ctxt() == ctxt => { - let ExprKind::MethodCall(name, _, [args @ ..], _) = e.kind else { + let ExprKind::MethodCall(name, _, args, _) = e.kind else { return None; }; let did = cx.typeck_results().type_dependent_def_id(e.hir_id)?; diff --git a/clippy_lints/src/misc_early/mod.rs b/clippy_lints/src/misc_early/mod.rs index 78253ab6cdc..fcf19f17958 100644 --- a/clippy_lints/src/misc_early/mod.rs +++ b/clippy_lints/src/misc_early/mod.rs @@ -3,6 +3,7 @@ mod double_neg; mod literal_suffix; mod mixed_case_hex_literals; mod redundant_pattern; +mod redundant_rest_pattern; mod unneeded_field_pattern; mod unneeded_wildcard_pattern; mod zero_prefixed_literal; @@ -318,6 +319,34 @@ declare_clippy_lint! { "tuple patterns with a wildcard pattern (`_`) is next to a rest pattern (`..`)" } +declare_clippy_lint! { + /// ### What it does + /// Checks for `[all @ ..]` patterns. + /// + /// ### Why is this bad? + /// In all cases, `all` works fine and can often make code simpler, as you possibly won't need + /// to convert from say a `Vec` to a slice by dereferencing. + /// + /// ### Example + /// ```rust,ignore + /// if let [all @ ..] = &*v { + /// // NOTE: Type is a slice here + /// println!("all elements: {all:#?}"); + /// } + /// ``` + /// Use instead: + /// ```rust,ignore + /// if let all = v { + /// // NOTE: Type is a `Vec` here + /// println!("all elements: {all:#?}"); + /// } + /// ``` + #[clippy::version = "1.72.0"] + pub REDUNDANT_REST_PATTERN, + complexity, + "checks for `[all @ ..]` where `all` would suffice" +} + declare_lint_pass!(MiscEarlyLints => [ UNNEEDED_FIELD_PATTERN, DUPLICATE_UNDERSCORE_ARGUMENT, @@ -329,6 +358,7 @@ declare_lint_pass!(MiscEarlyLints => [ BUILTIN_TYPE_SHADOW, REDUNDANT_PATTERN, UNNEEDED_WILDCARD_PATTERN, + REDUNDANT_REST_PATTERN, ]); impl EarlyLintPass for MiscEarlyLints { @@ -345,6 +375,7 @@ impl EarlyLintPass for MiscEarlyLints { unneeded_field_pattern::check(cx, pat); redundant_pattern::check(cx, pat); + redundant_rest_pattern::check(cx, pat); unneeded_wildcard_pattern::check(cx, pat); } diff --git a/clippy_lints/src/misc_early/redundant_rest_pattern.rs b/clippy_lints/src/misc_early/redundant_rest_pattern.rs new file mode 100644 index 00000000000..87e1ed8317c --- /dev/null +++ b/clippy_lints/src/misc_early/redundant_rest_pattern.rs @@ -0,0 +1,26 @@ +use clippy_utils::diagnostics::span_lint_and_sugg; +use rustc_ast::{Pat, PatKind}; +use rustc_errors::Applicability; +use rustc_lint::{EarlyContext, LintContext}; +use rustc_middle::lint::in_external_macro; + +use super::REDUNDANT_REST_PATTERN; + +pub(super) fn check(cx: &EarlyContext<'_>, pat: &Pat) { + if !in_external_macro(cx.sess(), pat.span) + && let PatKind::Slice(slice) = &pat.kind + && let [one] = &**slice + && let PatKind::Ident(annotation, ident, Some(rest)) = &one.kind + && let PatKind::Rest = rest.kind + { + span_lint_and_sugg( + cx, + REDUNDANT_REST_PATTERN, + pat.span, + "using a rest pattern to bind an entire slice to a local", + "this is better represented with just the binding", + format!("{}{ident}", annotation.prefix_str()), + Applicability::MachineApplicable, + ); + } +} diff --git a/clippy_utils/src/sugg.rs b/clippy_utils/src/sugg.rs index f477524eec5..bc3e58169e6 100644 --- a/clippy_utils/src/sugg.rs +++ b/clippy_utils/src/sugg.rs @@ -942,7 +942,7 @@ impl<'tcx> Delegate<'tcx> for DerefDelegate<'_, 'tcx> { }, // item is used in a call // i.e.: `Call`: `|x| please(x)` or `MethodCall`: `|x| [1, 2, 3].contains(x)` - ExprKind::Call(_, [call_args @ ..]) | ExprKind::MethodCall(_, _, [call_args @ ..], _) => { + ExprKind::Call(_, call_args) | ExprKind::MethodCall(_, _, call_args, _) => { let expr = self.cx.tcx.hir().expect_expr(cmt.hir_id); let arg_ty_kind = self.cx.typeck_results().expr_ty(expr).kind(); diff --git a/tests/ui/manual_let_else_match.rs b/tests/ui/manual_let_else_match.rs index 07cd5a53a7c..073094ea789 100644 --- a/tests/ui/manual_let_else_match.rs +++ b/tests/ui/manual_let_else_match.rs @@ -1,5 +1,5 @@ #![allow(unused_braces, unused_variables, dead_code)] -#![allow(clippy::collapsible_else_if, clippy::let_unit_value)] +#![allow(clippy::collapsible_else_if, clippy::let_unit_value, clippy::redundant_rest_pattern)] #![warn(clippy::manual_let_else)] // Ensure that we don't conflict with match -> if let lints #![warn(clippy::single_match_else, clippy::single_match)] diff --git a/tests/ui/match_on_vec_items.rs b/tests/ui/match_on_vec_items.rs index d82a736963a..fe214904365 100644 --- a/tests/ui/match_on_vec_items.rs +++ b/tests/ui/match_on_vec_items.rs @@ -1,5 +1,5 @@ #![warn(clippy::match_on_vec_items)] -#![allow(clippy::useless_vec)] +#![allow(clippy::redundant_rest_pattern, clippy::useless_vec)] fn match_with_wildcard() { let arr = vec![0, 1, 2, 3]; diff --git a/tests/ui/redundant_rest_pattern.fixed b/tests/ui/redundant_rest_pattern.fixed new file mode 100644 index 00000000000..d9a98622c42 --- /dev/null +++ b/tests/ui/redundant_rest_pattern.fixed @@ -0,0 +1,27 @@ +//@run-rustfix +//@aux-build:proc_macros.rs +#![allow(irrefutable_let_patterns, unused)] +#![warn(clippy::redundant_rest_pattern)] + +#[macro_use] +extern crate proc_macros; + +fn main() { + if let a = [()] {} + if let ref a = [()] {} + if let mut a = [()] {} + if let ref mut a = [()] {} + let v = vec![()]; + if let a = &*v {} + let s = &[()]; + if let a = s {} + // Don't lint + if let [..] = &*v {} + if let [a] = &*v {} + if let [()] = &*v {} + if let [first, rest @ ..] = &*v {} + if let a = [()] {} + external! { + if let [a @ ..] = [()] {} + } +} diff --git a/tests/ui/redundant_rest_pattern.rs b/tests/ui/redundant_rest_pattern.rs new file mode 100644 index 00000000000..60a12bfd6fb --- /dev/null +++ b/tests/ui/redundant_rest_pattern.rs @@ -0,0 +1,27 @@ +//@run-rustfix +//@aux-build:proc_macros.rs +#![allow(irrefutable_let_patterns, unused)] +#![warn(clippy::redundant_rest_pattern)] + +#[macro_use] +extern crate proc_macros; + +fn main() { + if let [a @ ..] = [()] {} + if let [ref a @ ..] = [()] {} + if let [mut a @ ..] = [()] {} + if let [ref mut a @ ..] = [()] {} + let v = vec![()]; + if let [a @ ..] = &*v {} + let s = &[()]; + if let [a @ ..] = s {} + // Don't lint + if let [..] = &*v {} + if let [a] = &*v {} + if let [()] = &*v {} + if let [first, rest @ ..] = &*v {} + if let a = [()] {} + external! { + if let [a @ ..] = [()] {} + } +} diff --git a/tests/ui/redundant_rest_pattern.stderr b/tests/ui/redundant_rest_pattern.stderr new file mode 100644 index 00000000000..630909a0a16 --- /dev/null +++ b/tests/ui/redundant_rest_pattern.stderr @@ -0,0 +1,40 @@ +error: using a rest pattern to bind an entire slice to a local + --> $DIR/redundant_rest_pattern.rs:10:12 + | +LL | if let [a @ ..] = [()] {} + | ^^^^^^^^ help: this is better represented with just the binding: `a` + | + = note: `-D clippy::redundant-rest-pattern` implied by `-D warnings` + +error: using a rest pattern to bind an entire slice to a local + --> $DIR/redundant_rest_pattern.rs:11:12 + | +LL | if let [ref a @ ..] = [()] {} + | ^^^^^^^^^^^^ help: this is better represented with just the binding: `ref a` + +error: using a rest pattern to bind an entire slice to a local + --> $DIR/redundant_rest_pattern.rs:12:12 + | +LL | if let [mut a @ ..] = [()] {} + | ^^^^^^^^^^^^ help: this is better represented with just the binding: `mut a` + +error: using a rest pattern to bind an entire slice to a local + --> $DIR/redundant_rest_pattern.rs:13:12 + | +LL | if let [ref mut a @ ..] = [()] {} + | ^^^^^^^^^^^^^^^^ help: this is better represented with just the binding: `ref mut a` + +error: using a rest pattern to bind an entire slice to a local + --> $DIR/redundant_rest_pattern.rs:15:12 + | +LL | if let [a @ ..] = &*v {} + | ^^^^^^^^ help: this is better represented with just the binding: `a` + +error: using a rest pattern to bind an entire slice to a local + --> $DIR/redundant_rest_pattern.rs:17:12 + | +LL | if let [a @ ..] = s {} + | ^^^^^^^^ help: this is better represented with just the binding: `a` + +error: aborting due to 6 previous errors + From e9ced12512f0a63667884c0eac10c99d437f31f7 Mon Sep 17 00:00:00 2001 From: Catherine <114838443+Centri3@users.noreply.github.com> Date: Tue, 27 Jun 2023 06:09:28 -0500 Subject: [PATCH 279/310] Rename the lint --- CHANGELOG.md | 2 +- clippy_lints/src/declared_lints.rs | 2 +- clippy_lints/src/misc_early/mod.rs | 8 ++++---- ...pattern.rs => redundant_at_rest_pattern.rs} | 4 ++-- tests/ui/manual_let_else_match.rs | 6 +++++- tests/ui/manual_let_else_match.stderr | 18 +++++++++--------- tests/ui/match_on_vec_items.rs | 2 +- ...n.fixed => redundant_at_rest_pattern.fixed} | 4 ++-- ...pattern.rs => redundant_at_rest_pattern.rs} | 4 ++-- ...stderr => redundant_at_rest_pattern.stderr} | 14 +++++++------- 10 files changed, 34 insertions(+), 30 deletions(-) rename clippy_lints/src/misc_early/{redundant_rest_pattern.rs => redundant_at_rest_pattern.rs} (91%) rename tests/ui/{redundant_rest_pattern.fixed => redundant_at_rest_pattern.fixed} (86%) rename tests/ui/{redundant_rest_pattern.rs => redundant_at_rest_pattern.rs} (87%) rename tests/ui/{redundant_rest_pattern.stderr => redundant_at_rest_pattern.stderr} (77%) diff --git a/CHANGELOG.md b/CHANGELOG.md index 6350d9c118f..7b2179bddfd 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5131,6 +5131,7 @@ Released 2018-09-13 [`recursive_format_impl`]: https://rust-lang.github.io/rust-clippy/master/index.html#recursive_format_impl [`redundant_allocation`]: https://rust-lang.github.io/rust-clippy/master/index.html#redundant_allocation [`redundant_async_block`]: https://rust-lang.github.io/rust-clippy/master/index.html#redundant_async_block +[`redundant_at_rest_pattern`]: https://rust-lang.github.io/rust-clippy/master/index.html#redundant_at_rest_pattern [`redundant_clone`]: https://rust-lang.github.io/rust-clippy/master/index.html#redundant_clone [`redundant_closure`]: https://rust-lang.github.io/rust-clippy/master/index.html#redundant_closure [`redundant_closure_call`]: https://rust-lang.github.io/rust-clippy/master/index.html#redundant_closure_call @@ -5141,7 +5142,6 @@ Released 2018-09-13 [`redundant_pattern`]: https://rust-lang.github.io/rust-clippy/master/index.html#redundant_pattern [`redundant_pattern_matching`]: https://rust-lang.github.io/rust-clippy/master/index.html#redundant_pattern_matching [`redundant_pub_crate`]: https://rust-lang.github.io/rust-clippy/master/index.html#redundant_pub_crate -[`redundant_rest_pattern`]: https://rust-lang.github.io/rust-clippy/master/index.html#redundant_rest_pattern [`redundant_slicing`]: https://rust-lang.github.io/rust-clippy/master/index.html#redundant_slicing [`redundant_static_lifetimes`]: https://rust-lang.github.io/rust-clippy/master/index.html#redundant_static_lifetimes [`redundant_type_annotations`]: https://rust-lang.github.io/rust-clippy/master/index.html#redundant_type_annotations diff --git a/clippy_lints/src/declared_lints.rs b/clippy_lints/src/declared_lints.rs index 13b0f9d5ee3..19014888114 100644 --- a/clippy_lints/src/declared_lints.rs +++ b/clippy_lints/src/declared_lints.rs @@ -430,8 +430,8 @@ pub(crate) static LINTS: &[&crate::LintInfo] = &[ crate::misc_early::DOUBLE_NEG_INFO, crate::misc_early::DUPLICATE_UNDERSCORE_ARGUMENT_INFO, crate::misc_early::MIXED_CASE_HEX_LITERALS_INFO, + crate::misc_early::REDUNDANT_AT_REST_PATTERN_INFO, crate::misc_early::REDUNDANT_PATTERN_INFO, - crate::misc_early::REDUNDANT_REST_PATTERN_INFO, crate::misc_early::SEPARATED_LITERAL_SUFFIX_INFO, crate::misc_early::UNNEEDED_FIELD_PATTERN_INFO, crate::misc_early::UNNEEDED_WILDCARD_PATTERN_INFO, diff --git a/clippy_lints/src/misc_early/mod.rs b/clippy_lints/src/misc_early/mod.rs index fcf19f17958..cff8538095d 100644 --- a/clippy_lints/src/misc_early/mod.rs +++ b/clippy_lints/src/misc_early/mod.rs @@ -2,8 +2,8 @@ mod builtin_type_shadow; mod double_neg; mod literal_suffix; mod mixed_case_hex_literals; +mod redundant_at_rest_pattern; mod redundant_pattern; -mod redundant_rest_pattern; mod unneeded_field_pattern; mod unneeded_wildcard_pattern; mod zero_prefixed_literal; @@ -342,7 +342,7 @@ declare_clippy_lint! { /// } /// ``` #[clippy::version = "1.72.0"] - pub REDUNDANT_REST_PATTERN, + pub REDUNDANT_AT_REST_PATTERN, complexity, "checks for `[all @ ..]` where `all` would suffice" } @@ -358,7 +358,7 @@ declare_lint_pass!(MiscEarlyLints => [ BUILTIN_TYPE_SHADOW, REDUNDANT_PATTERN, UNNEEDED_WILDCARD_PATTERN, - REDUNDANT_REST_PATTERN, + REDUNDANT_AT_REST_PATTERN, ]); impl EarlyLintPass for MiscEarlyLints { @@ -375,7 +375,7 @@ impl EarlyLintPass for MiscEarlyLints { unneeded_field_pattern::check(cx, pat); redundant_pattern::check(cx, pat); - redundant_rest_pattern::check(cx, pat); + redundant_at_rest_pattern::check(cx, pat); unneeded_wildcard_pattern::check(cx, pat); } diff --git a/clippy_lints/src/misc_early/redundant_rest_pattern.rs b/clippy_lints/src/misc_early/redundant_at_rest_pattern.rs similarity index 91% rename from clippy_lints/src/misc_early/redundant_rest_pattern.rs rename to clippy_lints/src/misc_early/redundant_at_rest_pattern.rs index 87e1ed8317c..0c81ee5eced 100644 --- a/clippy_lints/src/misc_early/redundant_rest_pattern.rs +++ b/clippy_lints/src/misc_early/redundant_at_rest_pattern.rs @@ -4,7 +4,7 @@ use rustc_errors::Applicability; use rustc_lint::{EarlyContext, LintContext}; use rustc_middle::lint::in_external_macro; -use super::REDUNDANT_REST_PATTERN; +use super::REDUNDANT_AT_REST_PATTERN; pub(super) fn check(cx: &EarlyContext<'_>, pat: &Pat) { if !in_external_macro(cx.sess(), pat.span) @@ -15,7 +15,7 @@ pub(super) fn check(cx: &EarlyContext<'_>, pat: &Pat) { { span_lint_and_sugg( cx, - REDUNDANT_REST_PATTERN, + REDUNDANT_AT_REST_PATTERN, pat.span, "using a rest pattern to bind an entire slice to a local", "this is better represented with just the binding", diff --git a/tests/ui/manual_let_else_match.rs b/tests/ui/manual_let_else_match.rs index 073094ea789..73ff69eec4e 100644 --- a/tests/ui/manual_let_else_match.rs +++ b/tests/ui/manual_let_else_match.rs @@ -1,5 +1,9 @@ #![allow(unused_braces, unused_variables, dead_code)] -#![allow(clippy::collapsible_else_if, clippy::let_unit_value, clippy::redundant_rest_pattern)] +#![allow( + clippy::collapsible_else_if, + clippy::let_unit_value, + clippy::redundant_at_rest_pattern +)] #![warn(clippy::manual_let_else)] // Ensure that we don't conflict with match -> if let lints #![warn(clippy::single_match_else, clippy::single_match)] diff --git a/tests/ui/manual_let_else_match.stderr b/tests/ui/manual_let_else_match.stderr index ead2f28e609..3fd9a637605 100644 --- a/tests/ui/manual_let_else_match.stderr +++ b/tests/ui/manual_let_else_match.stderr @@ -1,5 +1,5 @@ error: this could be rewritten as `let...else` - --> $DIR/manual_let_else_match.rs:32:5 + --> $DIR/manual_let_else_match.rs:36:5 | LL | / let v = match g() { LL | | Some(v_some) => v_some, @@ -10,7 +10,7 @@ LL | | }; = note: `-D clippy::manual-let-else` implied by `-D warnings` error: this could be rewritten as `let...else` - --> $DIR/manual_let_else_match.rs:37:5 + --> $DIR/manual_let_else_match.rs:41:5 | LL | / let v = match g() { LL | | Some(v_some) => v_some, @@ -19,7 +19,7 @@ LL | | }; | |______^ help: consider writing: `let Some(v) = g() else { return };` error: this could be rewritten as `let...else` - --> $DIR/manual_let_else_match.rs:44:9 + --> $DIR/manual_let_else_match.rs:48:9 | LL | / let v = match h() { LL | | (Some(v), None) | (None, Some(v)) => v, @@ -28,7 +28,7 @@ LL | | }; | |__________^ help: consider writing: `let ((Some(v), None) | (None, Some(v))) = h() else { continue };` error: this could be rewritten as `let...else` - --> $DIR/manual_let_else_match.rs:49:9 + --> $DIR/manual_let_else_match.rs:53:9 | LL | / let v = match build_enum() { LL | | Variant::Bar(v) | Variant::Baz(v) => v, @@ -37,7 +37,7 @@ LL | | }; | |__________^ help: consider writing: `let (Variant::Bar(v) | Variant::Baz(v)) = build_enum() else { continue };` error: this could be rewritten as `let...else` - --> $DIR/manual_let_else_match.rs:57:5 + --> $DIR/manual_let_else_match.rs:61:5 | LL | / let v = match f() { LL | | Ok(v) => v, @@ -46,7 +46,7 @@ LL | | }; | |______^ help: consider writing: `let Ok(v) = f() else { return };` error: this could be rewritten as `let...else` - --> $DIR/manual_let_else_match.rs:63:5 + --> $DIR/manual_let_else_match.rs:67:5 | LL | / let v = match f().map_err(|_| ()) { LL | | Ok(v) => v, @@ -55,7 +55,7 @@ LL | | }; | |______^ help: consider writing: `let Ok(v) = f().map_err(|_| ()) else { return };` error: this could be rewritten as `let...else` - --> $DIR/manual_let_else_match.rs:70:5 + --> $DIR/manual_let_else_match.rs:74:5 | LL | / let _value = match f { LL | | Variant::Bar(v) | Variant::Baz(v) => v, @@ -64,7 +64,7 @@ LL | | }; | |______^ help: consider writing: `let (Variant::Bar(_value) | Variant::Baz(_value)) = f else { return };` error: this could be rewritten as `let...else` - --> $DIR/manual_let_else_match.rs:75:5 + --> $DIR/manual_let_else_match.rs:79:5 | LL | / let _value = match Some(build_enum()) { LL | | Some(Variant::Bar(v) | Variant::Baz(v)) => v, @@ -73,7 +73,7 @@ LL | | }; | |______^ help: consider writing: `let Some(Variant::Bar(_value) | Variant::Baz(_value)) = Some(build_enum()) else { return };` error: this could be rewritten as `let...else` - --> $DIR/manual_let_else_match.rs:81:5 + --> $DIR/manual_let_else_match.rs:85:5 | LL | / let data = match data.as_slice() { LL | | [data @ .., 0, 0, 0, 0] | [data @ .., 0, 0] | [data @ .., 0] => data, diff --git a/tests/ui/match_on_vec_items.rs b/tests/ui/match_on_vec_items.rs index fe214904365..cf9c279cd2f 100644 --- a/tests/ui/match_on_vec_items.rs +++ b/tests/ui/match_on_vec_items.rs @@ -1,5 +1,5 @@ #![warn(clippy::match_on_vec_items)] -#![allow(clippy::redundant_rest_pattern, clippy::useless_vec)] +#![allow(clippy::redundant_at_rest_pattern, clippy::useless_vec)] fn match_with_wildcard() { let arr = vec![0, 1, 2, 3]; diff --git a/tests/ui/redundant_rest_pattern.fixed b/tests/ui/redundant_at_rest_pattern.fixed similarity index 86% rename from tests/ui/redundant_rest_pattern.fixed rename to tests/ui/redundant_at_rest_pattern.fixed index d9a98622c42..080cf13b5da 100644 --- a/tests/ui/redundant_rest_pattern.fixed +++ b/tests/ui/redundant_at_rest_pattern.fixed @@ -1,7 +1,7 @@ //@run-rustfix -//@aux-build:proc_macros.rs +//@aux-build:proc_macros.rs:proc-macro #![allow(irrefutable_let_patterns, unused)] -#![warn(clippy::redundant_rest_pattern)] +#![warn(clippy::redundant_at_rest_pattern)] #[macro_use] extern crate proc_macros; diff --git a/tests/ui/redundant_rest_pattern.rs b/tests/ui/redundant_at_rest_pattern.rs similarity index 87% rename from tests/ui/redundant_rest_pattern.rs rename to tests/ui/redundant_at_rest_pattern.rs index 60a12bfd6fb..a8a80282956 100644 --- a/tests/ui/redundant_rest_pattern.rs +++ b/tests/ui/redundant_at_rest_pattern.rs @@ -1,7 +1,7 @@ //@run-rustfix -//@aux-build:proc_macros.rs +//@aux-build:proc_macros.rs:proc-macro #![allow(irrefutable_let_patterns, unused)] -#![warn(clippy::redundant_rest_pattern)] +#![warn(clippy::redundant_at_rest_pattern)] #[macro_use] extern crate proc_macros; diff --git a/tests/ui/redundant_rest_pattern.stderr b/tests/ui/redundant_at_rest_pattern.stderr similarity index 77% rename from tests/ui/redundant_rest_pattern.stderr rename to tests/ui/redundant_at_rest_pattern.stderr index 630909a0a16..e2a4d9ffd57 100644 --- a/tests/ui/redundant_rest_pattern.stderr +++ b/tests/ui/redundant_at_rest_pattern.stderr @@ -1,37 +1,37 @@ error: using a rest pattern to bind an entire slice to a local - --> $DIR/redundant_rest_pattern.rs:10:12 + --> $DIR/redundant_at_rest_pattern.rs:10:12 | LL | if let [a @ ..] = [()] {} | ^^^^^^^^ help: this is better represented with just the binding: `a` | - = note: `-D clippy::redundant-rest-pattern` implied by `-D warnings` + = note: `-D clippy::redundant-at-rest-pattern` implied by `-D warnings` error: using a rest pattern to bind an entire slice to a local - --> $DIR/redundant_rest_pattern.rs:11:12 + --> $DIR/redundant_at_rest_pattern.rs:11:12 | LL | if let [ref a @ ..] = [()] {} | ^^^^^^^^^^^^ help: this is better represented with just the binding: `ref a` error: using a rest pattern to bind an entire slice to a local - --> $DIR/redundant_rest_pattern.rs:12:12 + --> $DIR/redundant_at_rest_pattern.rs:12:12 | LL | if let [mut a @ ..] = [()] {} | ^^^^^^^^^^^^ help: this is better represented with just the binding: `mut a` error: using a rest pattern to bind an entire slice to a local - --> $DIR/redundant_rest_pattern.rs:13:12 + --> $DIR/redundant_at_rest_pattern.rs:13:12 | LL | if let [ref mut a @ ..] = [()] {} | ^^^^^^^^^^^^^^^^ help: this is better represented with just the binding: `ref mut a` error: using a rest pattern to bind an entire slice to a local - --> $DIR/redundant_rest_pattern.rs:15:12 + --> $DIR/redundant_at_rest_pattern.rs:15:12 | LL | if let [a @ ..] = &*v {} | ^^^^^^^^ help: this is better represented with just the binding: `a` error: using a rest pattern to bind an entire slice to a local - --> $DIR/redundant_rest_pattern.rs:17:12 + --> $DIR/redundant_at_rest_pattern.rs:17:12 | LL | if let [a @ ..] = s {} | ^^^^^^^^ help: this is better represented with just the binding: `a` From 2ac2dc1cfa136df6367c18596704cf268f856dcc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=AE=B8=E6=9D=B0=E5=8F=8B=20Jieyou=20Xu=20=28Joe=29?= Date: Fri, 23 Jun 2023 05:56:09 +0800 Subject: [PATCH 280/310] Provide more context for `rustc +nightly -Zunstable-options` on stable --- src/driver.rs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/driver.rs b/src/driver.rs index 3c5b6e12b96..f3cc94aeff0 100644 --- a/src/driver.rs +++ b/src/driver.rs @@ -16,6 +16,8 @@ extern crate rustc_session; extern crate rustc_span; use rustc_interface::interface; +use rustc_session::EarlyErrorHandler; +use rustc_session::config::ErrorOutputType; use rustc_session::parse::ParseSess; use rustc_span::symbol::Symbol; @@ -187,7 +189,9 @@ const BUG_REPORT_URL: &str = "https://github.com/rust-lang/rust-clippy/issues/ne #[allow(clippy::too_many_lines)] pub fn main() { - rustc_driver::init_rustc_env_logger(); + let handler = EarlyErrorHandler::new(ErrorOutputType::default()); + + rustc_driver::init_rustc_env_logger(&handler); rustc_driver::install_ice_hook(BUG_REPORT_URL, |handler| { // FIXME: this macro calls unwrap internally but is called in a panicking context! It's not From 76de5560faf576d9d19a32fa4175da3b43c757bd Mon Sep 17 00:00:00 2001 From: Alex Macleod Date: Tue, 27 Jun 2023 16:39:13 +0000 Subject: [PATCH 281/310] Add BLESS for compile-test and some cleanup --- book/src/development/adding_lints.md | 2 +- clippy_test_deps/Cargo.toml | 2 -- tests/compile-test.rs | 3 +-- 3 files changed, 2 insertions(+), 5 deletions(-) diff --git a/book/src/development/adding_lints.md b/book/src/development/adding_lints.md index cfcb060c46e..a0db8089250 100644 --- a/book/src/development/adding_lints.md +++ b/book/src/development/adding_lints.md @@ -414,7 +414,7 @@ fn is_foo_fn(fn_kind: FnKind<'_>) -> bool { Now we should also run the full test suite with `cargo test`. At this point running `cargo test` should produce the expected output. Remember to run `cargo -dev bless` to update the `.stderr` file. +bless` to update the `.stderr` file. `cargo test` (as opposed to `cargo uitest`) will also ensure that our lint implementation is not violating any Clippy lints itself. diff --git a/clippy_test_deps/Cargo.toml b/clippy_test_deps/Cargo.toml index 6d053253fc3..362c08e0d77 100644 --- a/clippy_test_deps/Cargo.toml +++ b/clippy_test_deps/Cargo.toml @@ -6,7 +6,6 @@ edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] -clap = { version = "4.1.4", features = ["derive"] } clippy_utils = { path = "../clippy_utils" } derive-new = "0.5" if_chain = "1.0" @@ -17,7 +16,6 @@ syn = { version = "2.0", features = ["full"] } futures = "0.3" parking_lot = "0.12" tokio = { version = "1", features = ["io-util"] } -rustc-semver = "1.1" regex = "1.5" clippy_lints = { path = "../clippy_lints" } diff --git a/tests/compile-test.rs b/tests/compile-test.rs index c5e8622bc85..3ea33c3d233 100644 --- a/tests/compile-test.rs +++ b/tests/compile-test.rs @@ -24,7 +24,7 @@ fn base_config(test_dir: &str) -> compiletest::Config { mode: TestMode::Yolo, stderr_filters: vec![], stdout_filters: vec![], - output_conflict_handling: if std::env::args().any(|arg| arg == "--bless") { + output_conflict_handling: if var_os("BLESS").is_some() || env::args().any(|arg| arg == "--bless") { compiletest::OutputConflictHandling::Bless } else { compiletest::OutputConflictHandling::Error("cargo test -- -- --bless".into()) @@ -295,7 +295,6 @@ fn rustfix_coverage_known_exceptions_accuracy() { let rs_path = Path::new("tests/ui").join(filename); assert!(rs_path.exists(), "`{}` does not exist", rs_path.display()); let fixed_path = rs_path.with_extension("fixed"); - println!("{}", fixed_path.display()); assert!(!fixed_path.exists(), "`{}` exists", fixed_path.display()); } } From 95ab05de25a32ceaff8ee3e2869638fabd6eff94 Mon Sep 17 00:00:00 2001 From: Alex Macleod Date: Tue, 27 Jun 2023 18:25:35 +0000 Subject: [PATCH 282/310] Fix compile-test under cargo nextest --- tests/compile-test.rs | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/tests/compile-test.rs b/tests/compile-test.rs index 13013f646e5..745faaddda6 100644 --- a/tests/compile-test.rs +++ b/tests/compile-test.rs @@ -212,6 +212,15 @@ fn run_ui_cargo() { } fn main() { + // Support being run by cargo nextest - https://nexte.st/book/custom-test-harnesses.html + if env::args().any(|arg| arg == "--list") { + if !env::args().any(|arg| arg == "--ignored") { + println!("compile_test: test"); + } + + return; + } + set_var("CLIPPY_DISABLE_DOCS_LINKS", "true"); run_ui(); run_ui_toml(); From a43bfefd19a3af040b6cbc5cc607814d9250689a Mon Sep 17 00:00:00 2001 From: y21 <30553356+y21@users.noreply.github.com> Date: Tue, 27 Jun 2023 22:00:00 +0200 Subject: [PATCH 283/310] [`unused_async`]: don't lint on async trait impls --- clippy_lints/src/unused_async.rs | 18 ++++++++++++++++-- tests/ui/unused_async.rs | 14 ++++++++++++++ tests/ui/unused_async.stderr | 8 ++++---- 3 files changed, 34 insertions(+), 6 deletions(-) diff --git a/clippy_lints/src/unused_async.rs b/clippy_lints/src/unused_async.rs index 117dda09222..21153973dff 100644 --- a/clippy_lints/src/unused_async.rs +++ b/clippy_lints/src/unused_async.rs @@ -1,6 +1,6 @@ use clippy_utils::diagnostics::span_lint_and_then; use rustc_hir::intravisit::{walk_body, walk_expr, walk_fn, FnKind, Visitor}; -use rustc_hir::{Body, Expr, ExprKind, FnDecl, YieldSource}; +use rustc_hir::{Body, Expr, ExprKind, FnDecl, ItemKind, Node, YieldSource}; use rustc_lint::{LateContext, LateLintPass}; use rustc_middle::hir::nested_filter; use rustc_session::{declare_lint_pass, declare_tool_lint}; @@ -81,6 +81,20 @@ impl<'a, 'tcx> Visitor<'tcx> for AsyncFnVisitor<'a, 'tcx> { } } +/// Checks if the `def_id` belongs to a function and that function is part of a trait impl, +/// in which case we shouldn't lint because `async` is part of the trait definition and therefore +/// can't be removed. +fn is_in_trait_impl(cx: &LateContext<'_>, def_id: LocalDefId) -> bool { + if let Some(hir_id) = cx.tcx.opt_local_def_id_to_hir_id(def_id) + && let Node::Item(item) = cx.tcx.hir().get_parent(hir_id) + && let ItemKind::Impl(imp) = item.kind + { + imp.of_trait.is_some() + } else { + false + } +} + impl<'tcx> LateLintPass<'tcx> for UnusedAsync { fn check_fn( &mut self, @@ -91,7 +105,7 @@ impl<'tcx> LateLintPass<'tcx> for UnusedAsync { span: Span, def_id: LocalDefId, ) { - if !span.from_expansion() && fn_kind.asyncness().is_async() { + if !span.from_expansion() && fn_kind.asyncness().is_async() && !is_in_trait_impl(cx, def_id) { let mut visitor = AsyncFnVisitor { cx, found_await: false, diff --git a/tests/ui/unused_async.rs b/tests/ui/unused_async.rs index bfaa5dadfa5..69e46ab4736 100644 --- a/tests/ui/unused_async.rs +++ b/tests/ui/unused_async.rs @@ -1,4 +1,6 @@ #![warn(clippy::unused_async)] +#![feature(async_fn_in_trait)] +#![allow(incomplete_features)] use std::future::Future; use std::pin::Pin; @@ -23,6 +25,18 @@ mod issue10800 { } } +mod issue10459 { + trait HasAsyncMethod { + async fn do_something() -> u32; + } + + impl HasAsyncMethod for () { + async fn do_something() -> u32 { + 1 + } + } +} + async fn foo() -> i32 { 4 } diff --git a/tests/ui/unused_async.stderr b/tests/ui/unused_async.stderr index 8ac2066a6b2..ffae8366b88 100644 --- a/tests/ui/unused_async.stderr +++ b/tests/ui/unused_async.stderr @@ -1,5 +1,5 @@ error: unused `async` for function with no await statements - --> $DIR/unused_async.rs:11:5 + --> $DIR/unused_async.rs:13:5 | LL | / async fn async_block_await() { LL | | async { @@ -10,14 +10,14 @@ LL | | } | = help: consider removing the `async` from this function note: `await` used in an async block, which does not require the enclosing function to be `async` - --> $DIR/unused_async.rs:13:23 + --> $DIR/unused_async.rs:15:23 | LL | ready(()).await; | ^^^^^ = note: `-D clippy::unused-async` implied by `-D warnings` error: unused `async` for function with no await statements - --> $DIR/unused_async.rs:26:1 + --> $DIR/unused_async.rs:40:1 | LL | / async fn foo() -> i32 { LL | | 4 @@ -27,7 +27,7 @@ LL | | } = help: consider removing the `async` from this function error: unused `async` for function with no await statements - --> $DIR/unused_async.rs:37:5 + --> $DIR/unused_async.rs:51:5 | LL | / async fn unused(&self) -> i32 { LL | | 1 From 1d4afc5d8201e591e0019883c0c2c6a0ae93f13b Mon Sep 17 00:00:00 2001 From: y21 <30553356+y21@users.noreply.github.com> Date: Fri, 16 Jun 2023 21:39:02 +0200 Subject: [PATCH 284/310] new lint: `manual_range_pattern` --- CHANGELOG.md | 1 + clippy_lints/src/declared_lints.rs | 1 + clippy_lints/src/lib.rs | 2 + clippy_lints/src/manual_range_pattern.rs | 123 +++++++++++++++++++++++ tests/ui/manual_range_pattern.fixed | 35 +++++++ tests/ui/manual_range_pattern.rs | 35 +++++++ tests/ui/manual_range_pattern.stderr | 51 ++++++++++ tests/ui/unnested_or_patterns.fixed | 3 +- tests/ui/unnested_or_patterns.rs | 3 +- tests/ui/unnested_or_patterns.stderr | 34 +++---- tests/ui/unnested_or_patterns2.fixed | 7 +- tests/ui/unnested_or_patterns2.rs | 7 +- tests/ui/unnested_or_patterns2.stderr | 16 +-- 13 files changed, 289 insertions(+), 29 deletions(-) create mode 100644 clippy_lints/src/manual_range_pattern.rs create mode 100644 tests/ui/manual_range_pattern.fixed create mode 100644 tests/ui/manual_range_pattern.rs create mode 100644 tests/ui/manual_range_pattern.stderr diff --git a/CHANGELOG.md b/CHANGELOG.md index a7284a70a1f..045c269d62a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4949,6 +4949,7 @@ Released 2018-09-13 [`manual_non_exhaustive`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_non_exhaustive [`manual_ok_or`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_ok_or [`manual_range_contains`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_range_contains +[`manual_range_pattern`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_range_pattern [`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 diff --git a/clippy_lints/src/declared_lints.rs b/clippy_lints/src/declared_lints.rs index dbd4a53d836..53d92c089ea 100644 --- a/clippy_lints/src/declared_lints.rs +++ b/clippy_lints/src/declared_lints.rs @@ -278,6 +278,7 @@ pub(crate) static LINTS: &[&crate::LintInfo] = &[ crate::manual_let_else::MANUAL_LET_ELSE_INFO, crate::manual_main_separator_str::MANUAL_MAIN_SEPARATOR_STR_INFO, crate::manual_non_exhaustive::MANUAL_NON_EXHAUSTIVE_INFO, + crate::manual_range_pattern::MANUAL_RANGE_PATTERN_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, diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index d926b7b84ea..d23dd29f815 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -188,6 +188,7 @@ mod manual_is_ascii_check; mod manual_let_else; mod manual_main_separator_str; mod manual_non_exhaustive; +mod manual_range_pattern; mod manual_rem_euclid; mod manual_retain; mod manual_slice_size_calculation; @@ -1068,6 +1069,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: needless_raw_string_hashes_allow_one, }) }); + store.register_late_pass(|_| Box::new(manual_range_pattern::ManualRangePattern)); // add lints here, do not remove this comment, it's used in `new_lint` } diff --git a/clippy_lints/src/manual_range_pattern.rs b/clippy_lints/src/manual_range_pattern.rs new file mode 100644 index 00000000000..0ef75792b7a --- /dev/null +++ b/clippy_lints/src/manual_range_pattern.rs @@ -0,0 +1,123 @@ +use clippy_utils::diagnostics::span_lint_and_sugg; +use rustc_ast::LitKind; +use rustc_data_structures::fx::FxHashSet; +use rustc_errors::Applicability; +use rustc_hir::Expr; +use rustc_hir::ExprKind; +use rustc_hir::PatKind; +use rustc_hir::RangeEnd; +use rustc_lint::LintContext; +use rustc_lint::{LateContext, LateLintPass}; +use rustc_middle::lint::in_external_macro; +use rustc_session::{declare_lint_pass, declare_tool_lint}; + +declare_clippy_lint! { + /// ### What it does + /// Looks for combined OR patterns that are all contained in a specific range, + /// e.g. `6 | 4 | 5 | 9 | 7 | 8` can be rewritten as `4..=9`. + /// + /// ### Why is this bad? + /// Using an explicit range is more concise and easier to read. + /// + /// ### Example + /// ```rust + /// let x = 6; + /// let foo = matches!(x, 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10); + /// ``` + /// Use instead: + /// ```rust + /// let x = 6; + /// let foo = matches!(x, 1..=10); + /// ``` + #[clippy::version = "1.72.0"] + pub MANUAL_RANGE_PATTERN, + complexity, + "manually writing range patterns using a combined OR pattern (`|`)" +} +declare_lint_pass!(ManualRangePattern => [MANUAL_RANGE_PATTERN]); + +fn expr_as_u128(expr: &Expr<'_>) -> Option { + if let ExprKind::Lit(lit) = expr.kind + && let LitKind::Int(num, _) = lit.node + { + Some(num) + } else { + None + } +} + +impl LateLintPass<'_> for ManualRangePattern { + fn check_pat(&mut self, cx: &LateContext<'_>, pat: &'_ rustc_hir::Pat<'_>) { + if in_external_macro(cx.sess(), pat.span) { + return; + } + + // a pattern like 1 | 2 seems fine, lint if there are at least 3 alternatives + if let PatKind::Or(pats) = pat.kind + && pats.len() >= 3 + { + let mut min = u128::MAX; + let mut max = 0; + let mut numbers_found = FxHashSet::default(); + let mut ranges_found = Vec::new(); + + for pat in pats { + if let PatKind::Lit(lit) = pat.kind + && let Some(num) = expr_as_u128(lit) + { + numbers_found.insert(num); + + min = min.min(num); + max = max.max(num); + } else if let PatKind::Range(Some(left), Some(right), end) = pat.kind + && let Some(left) = expr_as_u128(left) + && let Some(right) = expr_as_u128(right) + && right >= left + { + min = min.min(left); + max = max.max(right); + ranges_found.push(left..=match end { + RangeEnd::Included => right, + RangeEnd::Excluded => right - 1, + }); + } else { + return; + } + } + + let contains_whole_range = 'contains: { + let mut num = min; + while num <= max { + if numbers_found.contains(&num) { + num += 1; + } + // Given a list of (potentially overlapping) ranges like: + // 1..=5, 3..=7, 6..=10 + // We want to find the range with the highest end that still contains the current number + else if let Some(range) = ranges_found + .iter() + .filter(|range| range.contains(&num)) + .max_by_key(|range| range.end()) + { + num = range.end() + 1; + } else { + break 'contains false; + } + } + break 'contains true; + }; + + if contains_whole_range { + span_lint_and_sugg( + cx, + MANUAL_RANGE_PATTERN, + pat.span, + "this OR pattern can be rewritten using a range", + "try", + format!("{min}..={max}"), + Applicability::MachineApplicable, + ); + } + } + } +} diff --git a/tests/ui/manual_range_pattern.fixed b/tests/ui/manual_range_pattern.fixed new file mode 100644 index 00000000000..14a5f822d60 --- /dev/null +++ b/tests/ui/manual_range_pattern.fixed @@ -0,0 +1,35 @@ +//@run-rustfix + +#![allow(unused)] +#![warn(clippy::manual_range_pattern)] +#![feature(exclusive_range_pattern)] + +fn main() { + let f = 6; + + let _ = matches!(f, 1..=10); + let _ = matches!(f, 1..=10); + let _ = matches!(f, 4 | 2 | 3 | 1 | 5 | 6 | 9 | 8 | 10); // 7 is missing + let _ = matches!(f, | 4); + let _ = matches!(f, 4 | 5); + let _ = matches!(f, 1 | 2147483647); + let _ = matches!(f, 0 | 2147483647); + let _ = matches!(f, -2147483647 | 2147483647); + let _ = matches!(f, 1 | (2..=4)); + let _ = matches!(f, 1 | (2..4)); + let _ = matches!(f, 1..=48324729); + let _ = matches!(f, 0..=48324730); + let _ = matches!(f, 0..=3); + #[allow(clippy::match_like_matches_macro)] + let _ = match f { + 1..=10 => true, + _ => false, + }; + + macro_rules! mac { + ($e:expr) => { + matches!($e, 1..=10) + }; + } + mac!(f); +} diff --git a/tests/ui/manual_range_pattern.rs b/tests/ui/manual_range_pattern.rs new file mode 100644 index 00000000000..ea63953af04 --- /dev/null +++ b/tests/ui/manual_range_pattern.rs @@ -0,0 +1,35 @@ +//@run-rustfix + +#![allow(unused)] +#![warn(clippy::manual_range_pattern)] +#![feature(exclusive_range_pattern)] + +fn main() { + let f = 6; + + let _ = matches!(f, 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10); + let _ = matches!(f, 4 | 2 | 3 | 1 | 5 | 6 | 9 | 7 | 8 | 10); + let _ = matches!(f, 4 | 2 | 3 | 1 | 5 | 6 | 9 | 8 | 10); // 7 is missing + let _ = matches!(f, | 4); + let _ = matches!(f, 4 | 5); + let _ = matches!(f, 1 | 2147483647); + let _ = matches!(f, 0 | 2147483647); + let _ = matches!(f, -2147483647 | 2147483647); + let _ = matches!(f, 1 | (2..=4)); + let _ = matches!(f, 1 | (2..4)); + let _ = matches!(f, (1..=10) | (2..=13) | (14..=48324728) | 48324729); + let _ = matches!(f, 0 | (1..=10) | 48324730 | (2..=13) | (14..=48324728) | 48324729); + let _ = matches!(f, 0..=1 | 0..=2 | 0..=3); + #[allow(clippy::match_like_matches_macro)] + let _ = match f { + 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 => true, + _ => false, + }; + + macro_rules! mac { + ($e:expr) => { + matches!($e, 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10) + }; + } + mac!(f); +} diff --git a/tests/ui/manual_range_pattern.stderr b/tests/ui/manual_range_pattern.stderr new file mode 100644 index 00000000000..a8969ede4e0 --- /dev/null +++ b/tests/ui/manual_range_pattern.stderr @@ -0,0 +1,51 @@ +error: this OR pattern can be rewritten using a range + --> $DIR/manual_range_pattern.rs:10:25 + | +LL | let _ = matches!(f, 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `1..=10` + | + = note: `-D clippy::manual-range-pattern` implied by `-D warnings` + +error: this OR pattern can be rewritten using a range + --> $DIR/manual_range_pattern.rs:11:25 + | +LL | let _ = matches!(f, 4 | 2 | 3 | 1 | 5 | 6 | 9 | 7 | 8 | 10); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `1..=10` + +error: this OR pattern can be rewritten using a range + --> $DIR/manual_range_pattern.rs:20:25 + | +LL | let _ = matches!(f, (1..=10) | (2..=13) | (14..=48324728) | 48324729); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `1..=48324729` + +error: this OR pattern can be rewritten using a range + --> $DIR/manual_range_pattern.rs:21:25 + | +LL | let _ = matches!(f, 0 | (1..=10) | 48324730 | (2..=13) | (14..=48324728) | 48324729); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `0..=48324730` + +error: this OR pattern can be rewritten using a range + --> $DIR/manual_range_pattern.rs:22:25 + | +LL | let _ = matches!(f, 0..=1 | 0..=2 | 0..=3); + | ^^^^^^^^^^^^^^^^^^^^^ help: try: `0..=3` + +error: this OR pattern can be rewritten using a range + --> $DIR/manual_range_pattern.rs:25:9 + | +LL | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 => true, + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `1..=10` + +error: this OR pattern can be rewritten using a range + --> $DIR/manual_range_pattern.rs:31:26 + | +LL | matches!($e, 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10) + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `1..=10` +... +LL | mac!(f); + | ------- 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 7 previous errors + diff --git a/tests/ui/unnested_or_patterns.fixed b/tests/ui/unnested_or_patterns.fixed index 4ce6e866695..ca999f241f7 100644 --- a/tests/ui/unnested_or_patterns.fixed +++ b/tests/ui/unnested_or_patterns.fixed @@ -6,7 +6,8 @@ clippy::cognitive_complexity, clippy::match_ref_pats, clippy::upper_case_acronyms, - clippy::needless_if + clippy::needless_if, + clippy::manual_range_pattern )] #![allow(unreachable_patterns, irrefutable_let_patterns, unused)] diff --git a/tests/ui/unnested_or_patterns.rs b/tests/ui/unnested_or_patterns.rs index 07d60fac082..a09c3c66090 100644 --- a/tests/ui/unnested_or_patterns.rs +++ b/tests/ui/unnested_or_patterns.rs @@ -6,7 +6,8 @@ clippy::cognitive_complexity, clippy::match_ref_pats, clippy::upper_case_acronyms, - clippy::needless_if + clippy::needless_if, + clippy::manual_range_pattern )] #![allow(unreachable_patterns, irrefutable_let_patterns, unused)] diff --git a/tests/ui/unnested_or_patterns.stderr b/tests/ui/unnested_or_patterns.stderr index d7b582fc8bd..b997e4ce85f 100644 --- a/tests/ui/unnested_or_patterns.stderr +++ b/tests/ui/unnested_or_patterns.stderr @@ -1,5 +1,5 @@ error: unnested or-patterns - --> $DIR/unnested_or_patterns.rs:17:12 + --> $DIR/unnested_or_patterns.rs:18:12 | LL | if let box 0 | box 2 = Box::new(0) {} | ^^^^^^^^^^^^^ @@ -11,7 +11,7 @@ LL | if let box (0 | 2) = Box::new(0) {} | ~~~~~~~~~~~ error: unnested or-patterns - --> $DIR/unnested_or_patterns.rs:18:12 + --> $DIR/unnested_or_patterns.rs:19:12 | LL | if let box ((0 | 1)) | box (2 | 3) | box 4 = Box::new(0) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -22,7 +22,7 @@ LL | if let box (0 | 1 | 2 | 3 | 4) = Box::new(0) {} | ~~~~~~~~~~~~~~~~~~~~~~~ error: unnested or-patterns - --> $DIR/unnested_or_patterns.rs:20:12 + --> $DIR/unnested_or_patterns.rs:21:12 | LL | if let Some(1) | C0 | Some(2) = None {} | ^^^^^^^^^^^^^^^^^^^^^^ @@ -33,7 +33,7 @@ LL | if let Some(1 | 2) | C0 = None {} | ~~~~~~~~~~~~~~~~ error: unnested or-patterns - --> $DIR/unnested_or_patterns.rs:21:12 + --> $DIR/unnested_or_patterns.rs:22:12 | LL | if let &mut 0 | &mut 2 = &mut 0 {} | ^^^^^^^^^^^^^^^ @@ -44,7 +44,7 @@ LL | if let &mut (0 | 2) = &mut 0 {} | ~~~~~~~~~~~~ error: unnested or-patterns - --> $DIR/unnested_or_patterns.rs:22:12 + --> $DIR/unnested_or_patterns.rs:23:12 | LL | if let x @ 0 | x @ 2 = 0 {} | ^^^^^^^^^^^^^ @@ -55,7 +55,7 @@ LL | if let x @ (0 | 2) = 0 {} | ~~~~~~~~~~~ error: unnested or-patterns - --> $DIR/unnested_or_patterns.rs:23:12 + --> $DIR/unnested_or_patterns.rs:24:12 | LL | if let (0, 1) | (0, 2) | (0, 3) = (0, 0) {} | ^^^^^^^^^^^^^^^^^^^^^^^^ @@ -66,7 +66,7 @@ LL | if let (0, 1 | 2 | 3) = (0, 0) {} | ~~~~~~~~~~~~~~ error: unnested or-patterns - --> $DIR/unnested_or_patterns.rs:24:12 + --> $DIR/unnested_or_patterns.rs:25:12 | LL | if let (1, 0) | (2, 0) | (3, 0) = (0, 0) {} | ^^^^^^^^^^^^^^^^^^^^^^^^ @@ -77,7 +77,7 @@ LL | if let (1 | 2 | 3, 0) = (0, 0) {} | ~~~~~~~~~~~~~~ error: unnested or-patterns - --> $DIR/unnested_or_patterns.rs:25:12 + --> $DIR/unnested_or_patterns.rs:26:12 | LL | if let (x, ..) | (x, 1) | (x, 2) = (0, 1) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -88,7 +88,7 @@ LL | if let (x, ..) | (x, 1 | 2) = (0, 1) {} | ~~~~~~~~~~~~~~~~~~~~ error: unnested or-patterns - --> $DIR/unnested_or_patterns.rs:26:12 + --> $DIR/unnested_or_patterns.rs:27:12 | LL | if let [0] | [1] = [0] {} | ^^^^^^^^^ @@ -99,7 +99,7 @@ LL | if let [0 | 1] = [0] {} | ~~~~~~~ error: unnested or-patterns - --> $DIR/unnested_or_patterns.rs:27:12 + --> $DIR/unnested_or_patterns.rs:28:12 | LL | if let [x, 0] | [x, 1] = [0, 1] {} | ^^^^^^^^^^^^^^^ @@ -110,7 +110,7 @@ LL | if let [x, 0 | 1] = [0, 1] {} | ~~~~~~~~~~ error: unnested or-patterns - --> $DIR/unnested_or_patterns.rs:28:12 + --> $DIR/unnested_or_patterns.rs:29:12 | LL | if let [x, 0] | [x, 1] | [x, 2] = [0, 1] {} | ^^^^^^^^^^^^^^^^^^^^^^^^ @@ -121,7 +121,7 @@ LL | if let [x, 0 | 1 | 2] = [0, 1] {} | ~~~~~~~~~~~~~~ error: unnested or-patterns - --> $DIR/unnested_or_patterns.rs:29:12 + --> $DIR/unnested_or_patterns.rs:30:12 | LL | if let [x, ..] | [x, 1] | [x, 2] = [0, 1] {} | ^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -132,7 +132,7 @@ LL | if let [x, ..] | [x, 1 | 2] = [0, 1] {} | ~~~~~~~~~~~~~~~~~~~~ error: unnested or-patterns - --> $DIR/unnested_or_patterns.rs:31:12 + --> $DIR/unnested_or_patterns.rs:32:12 | LL | if let TS(0, x) | TS(1, x) = TS(0, 0) {} | ^^^^^^^^^^^^^^^^^^^ @@ -143,7 +143,7 @@ LL | if let TS(0 | 1, x) = TS(0, 0) {} | ~~~~~~~~~~~~ error: unnested or-patterns - --> $DIR/unnested_or_patterns.rs:32:12 + --> $DIR/unnested_or_patterns.rs:33:12 | LL | if let TS(1, 0) | TS(2, 0) | TS(3, 0) = TS(0, 0) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -154,7 +154,7 @@ LL | if let TS(1 | 2 | 3, 0) = TS(0, 0) {} | ~~~~~~~~~~~~~~~~ error: unnested or-patterns - --> $DIR/unnested_or_patterns.rs:33:12 + --> $DIR/unnested_or_patterns.rs:34:12 | LL | if let TS(x, ..) | TS(x, 1) | TS(x, 2) = TS(0, 0) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -165,7 +165,7 @@ LL | if let TS(x, ..) | TS(x, 1 | 2) = TS(0, 0) {} | ~~~~~~~~~~~~~~~~~~~~~~~~ error: unnested or-patterns - --> $DIR/unnested_or_patterns.rs:38:12 + --> $DIR/unnested_or_patterns.rs:39:12 | LL | if let S { x: 0, y } | S { y, x: 1 } = (S { x: 0, y: 1 }) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -176,7 +176,7 @@ LL | if let S { x: 0 | 1, y } = (S { x: 0, y: 1 }) {} | ~~~~~~~~~~~~~~~~~ error: unnested or-patterns - --> $DIR/unnested_or_patterns.rs:49:12 + --> $DIR/unnested_or_patterns.rs:50:12 | LL | if let [1] | [53] = [0] {} | ^^^^^^^^^^ diff --git a/tests/ui/unnested_or_patterns2.fixed b/tests/ui/unnested_or_patterns2.fixed index a88d7f51ac0..ebaba019cfd 100644 --- a/tests/ui/unnested_or_patterns2.fixed +++ b/tests/ui/unnested_or_patterns2.fixed @@ -2,7 +2,12 @@ #![feature(box_patterns)] #![warn(clippy::unnested_or_patterns)] -#![allow(clippy::cognitive_complexity, clippy::match_ref_pats, clippy::needless_if)] +#![allow( + clippy::cognitive_complexity, + clippy::match_ref_pats, + clippy::needless_if, + clippy::manual_range_pattern +)] #![allow(unreachable_patterns, irrefutable_let_patterns, unused_variables)] fn main() { diff --git a/tests/ui/unnested_or_patterns2.rs b/tests/ui/unnested_or_patterns2.rs index f6029eee441..50b6ca585cf 100644 --- a/tests/ui/unnested_or_patterns2.rs +++ b/tests/ui/unnested_or_patterns2.rs @@ -2,7 +2,12 @@ #![feature(box_patterns)] #![warn(clippy::unnested_or_patterns)] -#![allow(clippy::cognitive_complexity, clippy::match_ref_pats, clippy::needless_if)] +#![allow( + clippy::cognitive_complexity, + clippy::match_ref_pats, + clippy::needless_if, + clippy::manual_range_pattern +)] #![allow(unreachable_patterns, irrefutable_let_patterns, unused_variables)] fn main() { diff --git a/tests/ui/unnested_or_patterns2.stderr b/tests/ui/unnested_or_patterns2.stderr index 41e8d3fc709..76e890b3a2e 100644 --- a/tests/ui/unnested_or_patterns2.stderr +++ b/tests/ui/unnested_or_patterns2.stderr @@ -1,5 +1,5 @@ error: unnested or-patterns - --> $DIR/unnested_or_patterns2.rs:9:12 + --> $DIR/unnested_or_patterns2.rs:14:12 | LL | if let Some(Some(0)) | Some(Some(1)) = None {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -11,7 +11,7 @@ LL | if let Some(Some(0 | 1)) = None {} | ~~~~~~~~~~~~~~~~~ error: unnested or-patterns - --> $DIR/unnested_or_patterns2.rs:10:12 + --> $DIR/unnested_or_patterns2.rs:15:12 | LL | if let Some(Some(0)) | Some(Some(1) | Some(2)) = None {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -22,7 +22,7 @@ LL | if let Some(Some(0 | 1 | 2)) = None {} | ~~~~~~~~~~~~~~~~~~~~~ error: unnested or-patterns - --> $DIR/unnested_or_patterns2.rs:11:12 + --> $DIR/unnested_or_patterns2.rs:16:12 | LL | if let Some(Some(0 | 1) | Some(2)) | Some(Some(3) | Some(4)) = None {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -33,7 +33,7 @@ LL | if let Some(Some(0 | 1 | 2 | 3 | 4)) = None {} | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ error: unnested or-patterns - --> $DIR/unnested_or_patterns2.rs:12:12 + --> $DIR/unnested_or_patterns2.rs:17:12 | LL | if let Some(Some(0) | Some(1 | 2)) = None {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -44,7 +44,7 @@ LL | if let Some(Some(0 | 1 | 2)) = None {} | ~~~~~~~~~~~~~~~~~~~~~ error: unnested or-patterns - --> $DIR/unnested_or_patterns2.rs:13:12 + --> $DIR/unnested_or_patterns2.rs:18:12 | LL | if let ((0,),) | ((1,) | (2,),) = ((0,),) {} | ^^^^^^^^^^^^^^^^^^^^^^^^ @@ -55,7 +55,7 @@ LL | if let ((0 | 1 | 2,),) = ((0,),) {} | ~~~~~~~~~~~~~~~ error: unnested or-patterns - --> $DIR/unnested_or_patterns2.rs:14:12 + --> $DIR/unnested_or_patterns2.rs:19:12 | LL | if let 0 | (1 | 2) = 0 {} | ^^^^^^^^^^^ @@ -66,7 +66,7 @@ LL | if let 0 | 1 | 2 = 0 {} | ~~~~~~~~~ error: unnested or-patterns - --> $DIR/unnested_or_patterns2.rs:15:12 + --> $DIR/unnested_or_patterns2.rs:20:12 | LL | if let box (0 | 1) | (box 2 | box (3 | 4)) = Box::new(0) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -77,7 +77,7 @@ LL | if let box (0 | 1 | 2 | 3 | 4) = Box::new(0) {} | ~~~~~~~~~~~~~~~~~~~~~~~ error: unnested or-patterns - --> $DIR/unnested_or_patterns2.rs:16:12 + --> $DIR/unnested_or_patterns2.rs:21:12 | LL | if let box box 0 | box (box 2 | box 4) = Box::new(Box::new(0)) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ From b592d39968210a94d393e2eafa3a11af3011a5a0 Mon Sep 17 00:00:00 2001 From: y21 <30553356+y21@users.noreply.github.com> Date: Tue, 20 Jun 2023 10:51:39 +0200 Subject: [PATCH 285/310] manual_range_pattern -> manual_range_patterns --- CHANGELOG.md | 2 +- clippy_lints/src/declared_lints.rs | 2 +- clippy_lints/src/lib.rs | 4 ++-- ...range_pattern.rs => manual_range_patterns.rs} | 8 ++++---- ...pattern.fixed => manual_range_patterns.fixed} | 2 +- ...range_pattern.rs => manual_range_patterns.rs} | 2 +- ...ttern.stderr => manual_range_patterns.stderr} | 16 ++++++++-------- 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 +- 11 files changed, 22 insertions(+), 22 deletions(-) rename clippy_lints/src/{manual_range_pattern.rs => manual_range_patterns.rs} (95%) rename tests/ui/{manual_range_pattern.fixed => manual_range_patterns.fixed} (95%) rename tests/ui/{manual_range_pattern.rs => manual_range_patterns.rs} (96%) rename tests/ui/{manual_range_pattern.stderr => manual_range_patterns.stderr} (83%) diff --git a/CHANGELOG.md b/CHANGELOG.md index 045c269d62a..5193db5a35d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4949,7 +4949,7 @@ Released 2018-09-13 [`manual_non_exhaustive`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_non_exhaustive [`manual_ok_or`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_ok_or [`manual_range_contains`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_range_contains -[`manual_range_pattern`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_range_pattern +[`manual_range_patterns`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_range_patterns [`manual_rem_euclid`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_rem_euclid [`manual_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 diff --git a/clippy_lints/src/declared_lints.rs b/clippy_lints/src/declared_lints.rs index 53d92c089ea..881ff9baf18 100644 --- a/clippy_lints/src/declared_lints.rs +++ b/clippy_lints/src/declared_lints.rs @@ -278,7 +278,7 @@ pub(crate) static LINTS: &[&crate::LintInfo] = &[ crate::manual_let_else::MANUAL_LET_ELSE_INFO, crate::manual_main_separator_str::MANUAL_MAIN_SEPARATOR_STR_INFO, crate::manual_non_exhaustive::MANUAL_NON_EXHAUSTIVE_INFO, - crate::manual_range_pattern::MANUAL_RANGE_PATTERN_INFO, + crate::manual_range_patterns::MANUAL_RANGE_PATTERNS_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, diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index d23dd29f815..0c71fdccae0 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -188,7 +188,7 @@ mod manual_is_ascii_check; mod manual_let_else; mod manual_main_separator_str; mod manual_non_exhaustive; -mod manual_range_pattern; +mod manual_range_patterns; mod manual_rem_euclid; mod manual_retain; mod manual_slice_size_calculation; @@ -1069,7 +1069,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: needless_raw_string_hashes_allow_one, }) }); - store.register_late_pass(|_| Box::new(manual_range_pattern::ManualRangePattern)); + store.register_late_pass(|_| Box::new(manual_range_patterns::ManualRangePatterns)); // add lints here, do not remove this comment, it's used in `new_lint` } diff --git a/clippy_lints/src/manual_range_pattern.rs b/clippy_lints/src/manual_range_patterns.rs similarity index 95% rename from clippy_lints/src/manual_range_pattern.rs rename to clippy_lints/src/manual_range_patterns.rs index 0ef75792b7a..65ff555209a 100644 --- a/clippy_lints/src/manual_range_pattern.rs +++ b/clippy_lints/src/manual_range_patterns.rs @@ -30,11 +30,11 @@ declare_clippy_lint! { /// let foo = matches!(x, 1..=10); /// ``` #[clippy::version = "1.72.0"] - pub MANUAL_RANGE_PATTERN, + pub MANUAL_RANGE_PATTERNS, complexity, "manually writing range patterns using a combined OR pattern (`|`)" } -declare_lint_pass!(ManualRangePattern => [MANUAL_RANGE_PATTERN]); +declare_lint_pass!(ManualRangePatterns => [MANUAL_RANGE_PATTERNS]); fn expr_as_u128(expr: &Expr<'_>) -> Option { if let ExprKind::Lit(lit) = expr.kind @@ -46,7 +46,7 @@ fn expr_as_u128(expr: &Expr<'_>) -> Option { } } -impl LateLintPass<'_> for ManualRangePattern { +impl LateLintPass<'_> for ManualRangePatterns { fn check_pat(&mut self, cx: &LateContext<'_>, pat: &'_ rustc_hir::Pat<'_>) { if in_external_macro(cx.sess(), pat.span) { return; @@ -110,7 +110,7 @@ impl LateLintPass<'_> for ManualRangePattern { if contains_whole_range { span_lint_and_sugg( cx, - MANUAL_RANGE_PATTERN, + MANUAL_RANGE_PATTERNS, pat.span, "this OR pattern can be rewritten using a range", "try", diff --git a/tests/ui/manual_range_pattern.fixed b/tests/ui/manual_range_patterns.fixed similarity index 95% rename from tests/ui/manual_range_pattern.fixed rename to tests/ui/manual_range_patterns.fixed index 14a5f822d60..9eee8f37187 100644 --- a/tests/ui/manual_range_pattern.fixed +++ b/tests/ui/manual_range_patterns.fixed @@ -1,7 +1,7 @@ //@run-rustfix #![allow(unused)] -#![warn(clippy::manual_range_pattern)] +#![warn(clippy::manual_range_patterns)] #![feature(exclusive_range_pattern)] fn main() { diff --git a/tests/ui/manual_range_pattern.rs b/tests/ui/manual_range_patterns.rs similarity index 96% rename from tests/ui/manual_range_pattern.rs rename to tests/ui/manual_range_patterns.rs index ea63953af04..10743a7d04c 100644 --- a/tests/ui/manual_range_pattern.rs +++ b/tests/ui/manual_range_patterns.rs @@ -1,7 +1,7 @@ //@run-rustfix #![allow(unused)] -#![warn(clippy::manual_range_pattern)] +#![warn(clippy::manual_range_patterns)] #![feature(exclusive_range_pattern)] fn main() { diff --git a/tests/ui/manual_range_pattern.stderr b/tests/ui/manual_range_patterns.stderr similarity index 83% rename from tests/ui/manual_range_pattern.stderr rename to tests/ui/manual_range_patterns.stderr index a8969ede4e0..bc9e3350164 100644 --- a/tests/ui/manual_range_pattern.stderr +++ b/tests/ui/manual_range_patterns.stderr @@ -1,43 +1,43 @@ error: this OR pattern can be rewritten using a range - --> $DIR/manual_range_pattern.rs:10:25 + --> $DIR/manual_range_patterns.rs:10:25 | LL | let _ = matches!(f, 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `1..=10` | - = note: `-D clippy::manual-range-pattern` implied by `-D warnings` + = note: `-D clippy::manual-range-patterns` implied by `-D warnings` error: this OR pattern can be rewritten using a range - --> $DIR/manual_range_pattern.rs:11:25 + --> $DIR/manual_range_patterns.rs:11:25 | LL | let _ = matches!(f, 4 | 2 | 3 | 1 | 5 | 6 | 9 | 7 | 8 | 10); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `1..=10` error: this OR pattern can be rewritten using a range - --> $DIR/manual_range_pattern.rs:20:25 + --> $DIR/manual_range_patterns.rs:20:25 | LL | let _ = matches!(f, (1..=10) | (2..=13) | (14..=48324728) | 48324729); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `1..=48324729` error: this OR pattern can be rewritten using a range - --> $DIR/manual_range_pattern.rs:21:25 + --> $DIR/manual_range_patterns.rs:21:25 | LL | let _ = matches!(f, 0 | (1..=10) | 48324730 | (2..=13) | (14..=48324728) | 48324729); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `0..=48324730` error: this OR pattern can be rewritten using a range - --> $DIR/manual_range_pattern.rs:22:25 + --> $DIR/manual_range_patterns.rs:22:25 | LL | let _ = matches!(f, 0..=1 | 0..=2 | 0..=3); | ^^^^^^^^^^^^^^^^^^^^^ help: try: `0..=3` error: this OR pattern can be rewritten using a range - --> $DIR/manual_range_pattern.rs:25:9 + --> $DIR/manual_range_patterns.rs:25:9 | LL | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 => true, | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `1..=10` error: this OR pattern can be rewritten using a range - --> $DIR/manual_range_pattern.rs:31:26 + --> $DIR/manual_range_patterns.rs:31:26 | LL | matches!($e, 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10) | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `1..=10` diff --git a/tests/ui/unnested_or_patterns.fixed b/tests/ui/unnested_or_patterns.fixed index ca999f241f7..738045595c0 100644 --- a/tests/ui/unnested_or_patterns.fixed +++ b/tests/ui/unnested_or_patterns.fixed @@ -7,7 +7,7 @@ clippy::match_ref_pats, clippy::upper_case_acronyms, clippy::needless_if, - clippy::manual_range_pattern + clippy::manual_range_patterns )] #![allow(unreachable_patterns, irrefutable_let_patterns, unused)] diff --git a/tests/ui/unnested_or_patterns.rs b/tests/ui/unnested_or_patterns.rs index a09c3c66090..9e0e7b5def9 100644 --- a/tests/ui/unnested_or_patterns.rs +++ b/tests/ui/unnested_or_patterns.rs @@ -7,7 +7,7 @@ clippy::match_ref_pats, clippy::upper_case_acronyms, clippy::needless_if, - clippy::manual_range_pattern + clippy::manual_range_patterns )] #![allow(unreachable_patterns, irrefutable_let_patterns, unused)] diff --git a/tests/ui/unnested_or_patterns2.fixed b/tests/ui/unnested_or_patterns2.fixed index ebaba019cfd..11dc3437875 100644 --- a/tests/ui/unnested_or_patterns2.fixed +++ b/tests/ui/unnested_or_patterns2.fixed @@ -6,7 +6,7 @@ clippy::cognitive_complexity, clippy::match_ref_pats, clippy::needless_if, - clippy::manual_range_pattern + clippy::manual_range_patterns )] #![allow(unreachable_patterns, irrefutable_let_patterns, unused_variables)] diff --git a/tests/ui/unnested_or_patterns2.rs b/tests/ui/unnested_or_patterns2.rs index 50b6ca585cf..b2556082741 100644 --- a/tests/ui/unnested_or_patterns2.rs +++ b/tests/ui/unnested_or_patterns2.rs @@ -6,7 +6,7 @@ clippy::cognitive_complexity, clippy::match_ref_pats, clippy::needless_if, - clippy::manual_range_pattern + clippy::manual_range_patterns )] #![allow(unreachable_patterns, irrefutable_let_patterns, unused_variables)] From 8647e29159246a1616f643ad8128ac92299a9743 Mon Sep 17 00:00:00 2001 From: Alex Macleod Date: Tue, 27 Jun 2023 20:36:05 +0000 Subject: [PATCH 286/310] Use substring matching for TESTNAME --- tests/compile-test.rs | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/tests/compile-test.rs b/tests/compile-test.rs index 745faaddda6..08d41adf9e7 100644 --- a/tests/compile-test.rs +++ b/tests/compile-test.rs @@ -64,12 +64,7 @@ fn base_config(test_dir: &str) -> compiletest::Config { fn test_filter() -> Box bool> { if let Ok(filters) = env::var("TESTNAME") { let filters: Vec<_> = filters.split(',').map(ToString::to_string).collect(); - Box::new(move |path| { - filters.is_empty() - || filters - .iter() - .any(|f| path.file_stem().map_or(false, |stem| stem == f.as_str())) - }) + Box::new(move |path| filters.iter().any(|f| path.to_string_lossy().contains(f))) } else { Box::new(|_| true) } From 3376c714ee32c1e54f8dd71332d49f200ae87294 Mon Sep 17 00:00:00 2001 From: Catherine <114838443+Centri3@users.noreply.github.com> Date: Tue, 27 Jun 2023 20:10:25 -0500 Subject: [PATCH 287/310] Add note to remove `if` statement altogether --- clippy_lints/src/misc_early/mod.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/clippy_lints/src/misc_early/mod.rs b/clippy_lints/src/misc_early/mod.rs index cff8538095d..b226b878123 100644 --- a/clippy_lints/src/misc_early/mod.rs +++ b/clippy_lints/src/misc_early/mod.rs @@ -340,6 +340,8 @@ declare_clippy_lint! { /// // NOTE: Type is a `Vec` here /// println!("all elements: {all:#?}"); /// } + /// // or + /// println!("all elements: {v:#?}"); /// ``` #[clippy::version = "1.72.0"] pub REDUNDANT_AT_REST_PATTERN, From 8296a338dba7af1db8a6aff862c4ad46402dc111 Mon Sep 17 00:00:00 2001 From: Centri3 <114838443+Centri3@users.noreply.github.com> Date: Fri, 16 Jun 2023 10:51:47 -0500 Subject: [PATCH 288/310] new lints for visibility --- CHANGELOG.md | 3 + clippy_lints/src/declared_lints.rs | 3 + clippy_lints/src/lib.rs | 2 + clippy_lints/src/visibility.rs | 127 ++++++++++++++++++++++++++ tests/ui/manual_async_fn.fixed | 2 +- tests/ui/manual_async_fn.rs | 2 +- tests/ui/needless_pub_self.fixed | 33 +++++++ tests/ui/needless_pub_self.rs | 33 +++++++ tests/ui/needless_pub_self.stderr | 22 +++++ tests/ui/pub_with_shorthand.fixed | 38 ++++++++ tests/ui/pub_with_shorthand.rs | 38 ++++++++ tests/ui/pub_with_shorthand.stderr | 28 ++++++ tests/ui/pub_without_shorthand.fixed | 38 ++++++++ tests/ui/pub_without_shorthand.rs | 38 ++++++++ tests/ui/pub_without_shorthand.stderr | 22 +++++ 15 files changed, 427 insertions(+), 2 deletions(-) create mode 100644 clippy_lints/src/visibility.rs create mode 100644 tests/ui/needless_pub_self.fixed create mode 100644 tests/ui/needless_pub_self.rs create mode 100644 tests/ui/needless_pub_self.stderr create mode 100644 tests/ui/pub_with_shorthand.fixed create mode 100644 tests/ui/pub_with_shorthand.rs create mode 100644 tests/ui/pub_with_shorthand.stderr create mode 100644 tests/ui/pub_without_shorthand.fixed create mode 100644 tests/ui/pub_without_shorthand.rs create mode 100644 tests/ui/pub_without_shorthand.stderr diff --git a/CHANGELOG.md b/CHANGELOG.md index 5193db5a35d..4debe304857 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5047,6 +5047,7 @@ Released 2018-09-13 [`needless_option_take`]: https://rust-lang.github.io/rust-clippy/master/index.html#needless_option_take [`needless_parens_on_range_literals`]: https://rust-lang.github.io/rust-clippy/master/index.html#needless_parens_on_range_literals [`needless_pass_by_value`]: https://rust-lang.github.io/rust-clippy/master/index.html#needless_pass_by_value +[`needless_pub_self`]: https://rust-lang.github.io/rust-clippy/master/index.html#needless_pub_self [`needless_question_mark`]: https://rust-lang.github.io/rust-clippy/master/index.html#needless_question_mark [`needless_range_loop`]: https://rust-lang.github.io/rust-clippy/master/index.html#needless_range_loop [`needless_raw_string_hashes`]: https://rust-lang.github.io/rust-clippy/master/index.html#needless_raw_string_hashes @@ -5121,6 +5122,8 @@ Released 2018-09-13 [`ptr_offset_with_cast`]: https://rust-lang.github.io/rust-clippy/master/index.html#ptr_offset_with_cast [`pub_enum_variant_names`]: https://rust-lang.github.io/rust-clippy/master/index.html#pub_enum_variant_names [`pub_use`]: https://rust-lang.github.io/rust-clippy/master/index.html#pub_use +[`pub_with_shorthand`]: https://rust-lang.github.io/rust-clippy/master/index.html#pub_with_shorthand +[`pub_without_shorthand`]: https://rust-lang.github.io/rust-clippy/master/index.html#pub_without_shorthand [`question_mark`]: https://rust-lang.github.io/rust-clippy/master/index.html#question_mark [`question_mark_used`]: https://rust-lang.github.io/rust-clippy/master/index.html#question_mark_used [`range_minus_one`]: https://rust-lang.github.io/rust-clippy/master/index.html#range_minus_one diff --git a/clippy_lints/src/declared_lints.rs b/clippy_lints/src/declared_lints.rs index 881ff9baf18..46f4082f0c7 100644 --- a/clippy_lints/src/declared_lints.rs +++ b/clippy_lints/src/declared_lints.rs @@ -666,6 +666,9 @@ 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::visibility::NEEDLESS_PUB_SELF_INFO, + crate::visibility::PUB_WITHOUT_SHORTHAND_INFO, + crate::visibility::PUB_WITH_SHORTHAND_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 0c71fdccae0..2f88fe8dcd5 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -338,6 +338,7 @@ mod use_self; mod useless_conversion; mod vec; mod vec_init_then_push; +mod visibility; mod wildcard_imports; mod write; mod zero_div_zero; @@ -1070,6 +1071,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: }) }); store.register_late_pass(|_| Box::new(manual_range_patterns::ManualRangePatterns)); + store.register_early_pass(|| Box::new(visibility::Visibility)); // add lints here, do not remove this comment, it's used in `new_lint` } diff --git a/clippy_lints/src/visibility.rs b/clippy_lints/src/visibility.rs new file mode 100644 index 00000000000..635d0ab9652 --- /dev/null +++ b/clippy_lints/src/visibility.rs @@ -0,0 +1,127 @@ +use clippy_utils::{diagnostics::span_lint_and_sugg, source::snippet_opt}; +use rustc_ast::ast::{Item, VisibilityKind}; +use rustc_errors::Applicability; +use rustc_lint::{EarlyContext, EarlyLintPass, LintContext}; +use rustc_middle::lint::in_external_macro; +use rustc_session::{declare_lint_pass, declare_tool_lint}; +use rustc_span::{symbol::kw, Span}; + +declare_clippy_lint! { + /// ### What it does + /// Checks for usage of `pub(self)` and `pub(in self)`. + /// + /// ### Why is this bad? + /// It's unnecessary, omitting the `pub` entirely will give the same results. + /// + /// ### Example + /// ```rust,ignore + /// pub(self) type OptBox = Option>; + /// ``` + /// Use instead: + /// ```rust,ignore + /// type OptBox = Option>; + /// ``` + #[clippy::version = "1.72.0"] + pub NEEDLESS_PUB_SELF, + complexity, + "checks for usage of `pub(self)` and `pub(in self)`." +} +declare_clippy_lint! { + /// ### What it does + /// Checks for missing usage of the `pub(in )` shorthand. + /// + /// ### Why is this bad? + /// Consistency. Use it or don't, just be consistent about it. + /// + /// ### Example + /// ```rust,ignore + /// pub(super) type OptBox = Option>; + /// ``` + /// Use instead: + /// ```rust,ignore + /// pub(in super) type OptBox = Option>; + /// ``` + #[clippy::version = "1.72.0"] + pub PUB_WITH_SHORTHAND, + restriction, + "disallows usage of the `pub()`, suggesting use of the `in` shorthand" +} +declare_clippy_lint! { + /// ### What it does + /// Checks for usage of the `pub(in )` shorthand. + /// + /// Note: As you cannot write a module's path in `pub()`, this will only trigger on + /// `pub(super)` and the like. + /// + /// ### Why is this bad? + /// Consistency. Use it or don't, just be consistent about it. + /// + /// ### Example + /// ```rust,ignore + /// pub(in super) type OptBox = Option>; + /// ``` + /// Use instead: + /// ```rust,ignore + /// pub(super) type OptBox = Option>; + /// ``` + #[clippy::version = "1.72.0"] + pub PUB_WITHOUT_SHORTHAND, + restriction, + "disallows usage of the `pub(in )` shorthand wherever possible" +} +declare_lint_pass!(Visibility => [NEEDLESS_PUB_SELF, PUB_WITH_SHORTHAND, PUB_WITHOUT_SHORTHAND]); + +impl EarlyLintPass for Visibility { + fn check_item(&mut self, cx: &EarlyContext<'_>, item: &Item) { + if !in_external_macro(cx.sess(), item.span) + && let VisibilityKind::Restricted { path, shorthand, .. } = &item.vis.kind + { + if **path == kw::SelfLower && let Some(false) = is_from_proc_macro(cx, item.vis.span) { + span_lint_and_sugg( + cx, + NEEDLESS_PUB_SELF, + item.vis.span, + &format!("unnecessary `pub({}self)`", if *shorthand { "" } else { "in " }), + "remove it", + String::new(), + Applicability::MachineApplicable, + ); + } + + if (**path == kw::Super || **path == kw::SelfLower || **path == kw::Crate) + && !*shorthand + && let [.., last] = &*path.segments + && let Some(false) = is_from_proc_macro(cx, item.vis.span) + { + span_lint_and_sugg( + cx, + PUB_WITHOUT_SHORTHAND, + item.vis.span, + "usage of `pub` with `in`", + "remove it", + format!("pub({})", last.ident), + Applicability::MachineApplicable, + ); + } + + if *shorthand + && let [.., last] = &*path.segments + && let Some(false) = is_from_proc_macro(cx, item.vis.span) + { + span_lint_and_sugg( + cx, + PUB_WITH_SHORTHAND, + item.vis.span, + "usage of `pub` without `in`", + "add it", + format!("pub(in {})", last.ident), + Applicability::MachineApplicable, + ); + } + } + } +} + +fn is_from_proc_macro(cx: &EarlyContext<'_>, span: Span) -> Option { + snippet_opt(cx, span).map(|s| !s.starts_with("pub")) +} diff --git a/tests/ui/manual_async_fn.fixed b/tests/ui/manual_async_fn.fixed index e458f0d254f..e609b4b1bdb 100644 --- a/tests/ui/manual_async_fn.fixed +++ b/tests/ui/manual_async_fn.fixed @@ -1,6 +1,6 @@ //@run-rustfix #![warn(clippy::manual_async_fn)] -#![allow(unused)] +#![allow(clippy::needless_pub_self, unused)] use std::future::Future; diff --git a/tests/ui/manual_async_fn.rs b/tests/ui/manual_async_fn.rs index dd5ca1c9b5b..6c1a9edaa11 100644 --- a/tests/ui/manual_async_fn.rs +++ b/tests/ui/manual_async_fn.rs @@ -1,6 +1,6 @@ //@run-rustfix #![warn(clippy::manual_async_fn)] -#![allow(unused)] +#![allow(clippy::needless_pub_self, unused)] use std::future::Future; diff --git a/tests/ui/needless_pub_self.fixed b/tests/ui/needless_pub_self.fixed new file mode 100644 index 00000000000..bf5e70d9a05 --- /dev/null +++ b/tests/ui/needless_pub_self.fixed @@ -0,0 +1,33 @@ +//@run-rustfix +//@aux-build:proc_macros.rs +#![feature(custom_inner_attributes)] +#![allow(unused)] +#![warn(clippy::needless_pub_self)] +#![no_main] +#![rustfmt::skip] // rustfmt will remove `in`, understandable + // but very annoying for our purposes! + +#[macro_use] +extern crate proc_macros; + + fn a() {} + fn b() {} + +pub fn c() {} +mod a { + pub(in super) fn d() {} + pub(super) fn e() {} + fn f() {} +} + +external! { + pub(self) fn g() {} + pub(in self) fn h() {} +} +with_span! { + span + pub(self) fn i() {} + pub(in self) fn j() {} +} + +// not really anything more to test. just a really simple lint overall diff --git a/tests/ui/needless_pub_self.rs b/tests/ui/needless_pub_self.rs new file mode 100644 index 00000000000..a49a6658f8b --- /dev/null +++ b/tests/ui/needless_pub_self.rs @@ -0,0 +1,33 @@ +//@run-rustfix +//@aux-build:proc_macros.rs +#![feature(custom_inner_attributes)] +#![allow(unused)] +#![warn(clippy::needless_pub_self)] +#![no_main] +#![rustfmt::skip] // rustfmt will remove `in`, understandable + // but very annoying for our purposes! + +#[macro_use] +extern crate proc_macros; + +pub(self) fn a() {} +pub(in self) fn b() {} + +pub fn c() {} +mod a { + pub(in super) fn d() {} + pub(super) fn e() {} + pub(self) fn f() {} +} + +external! { + pub(self) fn g() {} + pub(in self) fn h() {} +} +with_span! { + span + pub(self) fn i() {} + pub(in self) fn j() {} +} + +// not really anything more to test. just a really simple lint overall diff --git a/tests/ui/needless_pub_self.stderr b/tests/ui/needless_pub_self.stderr new file mode 100644 index 00000000000..3aa2feb5ecd --- /dev/null +++ b/tests/ui/needless_pub_self.stderr @@ -0,0 +1,22 @@ +error: unnecessary `pub(self)` + --> $DIR/needless_pub_self.rs:13:1 + | +LL | pub(self) fn a() {} + | ^^^^^^^^^ help: remove it + | + = note: `-D clippy::needless-pub-self` implied by `-D warnings` + +error: unnecessary `pub(in self)` + --> $DIR/needless_pub_self.rs:14:1 + | +LL | pub(in self) fn b() {} + | ^^^^^^^^^^^^ help: remove it + +error: unnecessary `pub(self)` + --> $DIR/needless_pub_self.rs:20:5 + | +LL | pub(self) fn f() {} + | ^^^^^^^^^ help: remove it + +error: aborting due to 3 previous errors + diff --git a/tests/ui/pub_with_shorthand.fixed b/tests/ui/pub_with_shorthand.fixed new file mode 100644 index 00000000000..c9487ed7fc3 --- /dev/null +++ b/tests/ui/pub_with_shorthand.fixed @@ -0,0 +1,38 @@ +//@run-rustfix +//@aux-build:proc_macros.rs +#![feature(custom_inner_attributes)] +#![allow(clippy::needless_pub_self, unused)] +#![warn(clippy::pub_with_shorthand)] +#![no_main] +#![rustfmt::skip] // rustfmt will remove `in`, understandable + // but very annoying for our purposes! + +#[macro_use] +extern crate proc_macros; + +pub(in self) fn a() {} +pub(in self) fn b() {} + +pub fn c() {} +mod a { + pub(in super) fn d() {} + pub(in super) fn e() {} + pub(in self) fn f() {} + pub(in crate) fn k() {} + pub(in crate) fn m() {} + mod b { + pub(in crate::a) fn l() {} + } +} + +external! { + pub(self) fn g() {} + pub(in self) fn h() {} +} +with_span! { + span + pub(self) fn i() {} + pub(in self) fn j() {} +} + +// not really anything more to test. just a really simple lint overall diff --git a/tests/ui/pub_with_shorthand.rs b/tests/ui/pub_with_shorthand.rs new file mode 100644 index 00000000000..e47c926520b --- /dev/null +++ b/tests/ui/pub_with_shorthand.rs @@ -0,0 +1,38 @@ +//@run-rustfix +//@aux-build:proc_macros.rs +#![feature(custom_inner_attributes)] +#![allow(clippy::needless_pub_self, unused)] +#![warn(clippy::pub_with_shorthand)] +#![no_main] +#![rustfmt::skip] // rustfmt will remove `in`, understandable + // but very annoying for our purposes! + +#[macro_use] +extern crate proc_macros; + +pub(self) fn a() {} +pub(in self) fn b() {} + +pub fn c() {} +mod a { + pub(in super) fn d() {} + pub(super) fn e() {} + pub(self) fn f() {} + pub(crate) fn k() {} + pub(in crate) fn m() {} + mod b { + pub(in crate::a) fn l() {} + } +} + +external! { + pub(self) fn g() {} + pub(in self) fn h() {} +} +with_span! { + span + pub(self) fn i() {} + pub(in self) fn j() {} +} + +// not really anything more to test. just a really simple lint overall diff --git a/tests/ui/pub_with_shorthand.stderr b/tests/ui/pub_with_shorthand.stderr new file mode 100644 index 00000000000..323b5a23b24 --- /dev/null +++ b/tests/ui/pub_with_shorthand.stderr @@ -0,0 +1,28 @@ +error: usage of `pub` without `in` + --> $DIR/pub_with_shorthand.rs:13:1 + | +LL | pub(self) fn a() {} + | ^^^^^^^^^ help: add it: `pub(in self)` + | + = note: `-D clippy::pub-with-shorthand` implied by `-D warnings` + +error: usage of `pub` without `in` + --> $DIR/pub_with_shorthand.rs:19:5 + | +LL | pub(super) fn e() {} + | ^^^^^^^^^^ help: add it: `pub(in super)` + +error: usage of `pub` without `in` + --> $DIR/pub_with_shorthand.rs:20:5 + | +LL | pub(self) fn f() {} + | ^^^^^^^^^ help: add it: `pub(in self)` + +error: usage of `pub` without `in` + --> $DIR/pub_with_shorthand.rs:21:5 + | +LL | pub(crate) fn k() {} + | ^^^^^^^^^^ help: add it: `pub(in crate)` + +error: aborting due to 4 previous errors + diff --git a/tests/ui/pub_without_shorthand.fixed b/tests/ui/pub_without_shorthand.fixed new file mode 100644 index 00000000000..55159efb5bf --- /dev/null +++ b/tests/ui/pub_without_shorthand.fixed @@ -0,0 +1,38 @@ +//@run-rustfix +//@aux-build:proc_macros.rs +#![feature(custom_inner_attributes)] +#![allow(clippy::needless_pub_self, unused)] +#![warn(clippy::pub_without_shorthand)] +#![no_main] +#![rustfmt::skip] // rustfmt will remove `in`, understandable + // but very annoying for our purposes! + +#[macro_use] +extern crate proc_macros; + +pub(self) fn a() {} +pub(self) fn b() {} + +pub fn c() {} +mod a { + pub(super) fn d() {} + pub(super) fn e() {} + pub(self) fn f() {} + pub(crate) fn k() {} + pub(crate) fn m() {} + mod b { + pub(in crate::a) fn l() {} + } +} + +external! { + pub(self) fn g() {} + pub(in self) fn h() {} +} +with_span! { + span + pub(self) fn i() {} + pub(in self) fn j() {} +} + +// not really anything more to test. just a really simple lint overall diff --git a/tests/ui/pub_without_shorthand.rs b/tests/ui/pub_without_shorthand.rs new file mode 100644 index 00000000000..38f4da85a49 --- /dev/null +++ b/tests/ui/pub_without_shorthand.rs @@ -0,0 +1,38 @@ +//@run-rustfix +//@aux-build:proc_macros.rs +#![feature(custom_inner_attributes)] +#![allow(clippy::needless_pub_self, unused)] +#![warn(clippy::pub_without_shorthand)] +#![no_main] +#![rustfmt::skip] // rustfmt will remove `in`, understandable + // but very annoying for our purposes! + +#[macro_use] +extern crate proc_macros; + +pub(self) fn a() {} +pub(in self) fn b() {} + +pub fn c() {} +mod a { + pub(in super) fn d() {} + pub(super) fn e() {} + pub(self) fn f() {} + pub(crate) fn k() {} + pub(in crate) fn m() {} + mod b { + pub(in crate::a) fn l() {} + } +} + +external! { + pub(self) fn g() {} + pub(in self) fn h() {} +} +with_span! { + span + pub(self) fn i() {} + pub(in self) fn j() {} +} + +// not really anything more to test. just a really simple lint overall diff --git a/tests/ui/pub_without_shorthand.stderr b/tests/ui/pub_without_shorthand.stderr new file mode 100644 index 00000000000..a18c9bf8934 --- /dev/null +++ b/tests/ui/pub_without_shorthand.stderr @@ -0,0 +1,22 @@ +error: usage of `pub` with `in` + --> $DIR/pub_without_shorthand.rs:14:1 + | +LL | pub(in self) fn b() {} + | ^^^^^^^^^^^^ help: remove it: `pub(self)` + | + = note: `-D clippy::pub-without-shorthand` implied by `-D warnings` + +error: usage of `pub` with `in` + --> $DIR/pub_without_shorthand.rs:18:5 + | +LL | pub(in super) fn d() {} + | ^^^^^^^^^^^^^ help: remove it: `pub(super)` + +error: usage of `pub` with `in` + --> $DIR/pub_without_shorthand.rs:22:5 + | +LL | pub(in crate) fn m() {} + | ^^^^^^^^^^^^^ help: remove it: `pub(crate)` + +error: aborting due to 3 previous errors + From 46aa8abf08057618038c60c11b98a3c6cff927de Mon Sep 17 00:00:00 2001 From: Catherine <114838443+Centri3@users.noreply.github.com> Date: Tue, 27 Jun 2023 05:25:54 -0500 Subject: [PATCH 289/310] Change category and update to `ui_test` --- clippy_lints/src/visibility.rs | 14 +++++++++----- tests/ui/needless_pub_self.fixed | 2 +- tests/ui/needless_pub_self.rs | 2 +- tests/ui/pub_with_shorthand.fixed | 2 +- tests/ui/pub_with_shorthand.rs | 2 +- tests/ui/pub_without_shorthand.fixed | 2 +- tests/ui/pub_without_shorthand.rs | 2 +- 7 files changed, 15 insertions(+), 11 deletions(-) diff --git a/clippy_lints/src/visibility.rs b/clippy_lints/src/visibility.rs index 635d0ab9652..43248bccc13 100644 --- a/clippy_lints/src/visibility.rs +++ b/clippy_lints/src/visibility.rs @@ -23,16 +23,18 @@ declare_clippy_lint! { /// ``` #[clippy::version = "1.72.0"] pub NEEDLESS_PUB_SELF, - complexity, + style, "checks for usage of `pub(self)` and `pub(in self)`." } declare_clippy_lint! { /// ### What it does - /// Checks for missing usage of the `pub(in )` shorthand. + /// Checks for usage of `pub()` with `in`. /// /// ### Why is this bad? /// Consistency. Use it or don't, just be consistent about it. /// + /// Also see the `pub_without_shorthand` lint for an alternative. + /// /// ### Example /// ```rust,ignore /// pub(super) type OptBox = Option>; @@ -44,11 +46,11 @@ declare_clippy_lint! { #[clippy::version = "1.72.0"] pub PUB_WITH_SHORTHAND, restriction, - "disallows usage of the `pub()`, suggesting use of the `in` shorthand" + "disallows usage of `pub()`, without `in`" } declare_clippy_lint! { /// ### What it does - /// Checks for usage of the `pub(in )` shorthand. + /// Checks for usage of `pub()` without `in`. /// /// Note: As you cannot write a module's path in `pub()`, this will only trigger on /// `pub(super)` and the like. @@ -56,6 +58,8 @@ declare_clippy_lint! { /// ### Why is this bad? /// Consistency. Use it or don't, just be consistent about it. /// + /// Also see the `pub_with_shorthand` lint for an alternative. + /// /// ### Example /// ```rust,ignore /// pub(in super) type OptBox = Option>; @@ -67,7 +71,7 @@ declare_clippy_lint! { #[clippy::version = "1.72.0"] pub PUB_WITHOUT_SHORTHAND, restriction, - "disallows usage of the `pub(in )` shorthand wherever possible" + "disallows usage of `pub(in )` with `in`" } declare_lint_pass!(Visibility => [NEEDLESS_PUB_SELF, PUB_WITH_SHORTHAND, PUB_WITHOUT_SHORTHAND]); diff --git a/tests/ui/needless_pub_self.fixed b/tests/ui/needless_pub_self.fixed index bf5e70d9a05..672b4c318a8 100644 --- a/tests/ui/needless_pub_self.fixed +++ b/tests/ui/needless_pub_self.fixed @@ -1,5 +1,5 @@ //@run-rustfix -//@aux-build:proc_macros.rs +//@aux-build:proc_macros.rs:proc-macro #![feature(custom_inner_attributes)] #![allow(unused)] #![warn(clippy::needless_pub_self)] diff --git a/tests/ui/needless_pub_self.rs b/tests/ui/needless_pub_self.rs index a49a6658f8b..5ac1edf8e99 100644 --- a/tests/ui/needless_pub_self.rs +++ b/tests/ui/needless_pub_self.rs @@ -1,5 +1,5 @@ //@run-rustfix -//@aux-build:proc_macros.rs +//@aux-build:proc_macros.rs:proc-macro #![feature(custom_inner_attributes)] #![allow(unused)] #![warn(clippy::needless_pub_self)] diff --git a/tests/ui/pub_with_shorthand.fixed b/tests/ui/pub_with_shorthand.fixed index c9487ed7fc3..a774faa0a67 100644 --- a/tests/ui/pub_with_shorthand.fixed +++ b/tests/ui/pub_with_shorthand.fixed @@ -1,5 +1,5 @@ //@run-rustfix -//@aux-build:proc_macros.rs +//@aux-build:proc_macros.rs:proc-macro #![feature(custom_inner_attributes)] #![allow(clippy::needless_pub_self, unused)] #![warn(clippy::pub_with_shorthand)] diff --git a/tests/ui/pub_with_shorthand.rs b/tests/ui/pub_with_shorthand.rs index e47c926520b..4a4bbc18728 100644 --- a/tests/ui/pub_with_shorthand.rs +++ b/tests/ui/pub_with_shorthand.rs @@ -1,5 +1,5 @@ //@run-rustfix -//@aux-build:proc_macros.rs +//@aux-build:proc_macros.rs:proc-macro #![feature(custom_inner_attributes)] #![allow(clippy::needless_pub_self, unused)] #![warn(clippy::pub_with_shorthand)] diff --git a/tests/ui/pub_without_shorthand.fixed b/tests/ui/pub_without_shorthand.fixed index 55159efb5bf..fdb49ac4d90 100644 --- a/tests/ui/pub_without_shorthand.fixed +++ b/tests/ui/pub_without_shorthand.fixed @@ -1,5 +1,5 @@ //@run-rustfix -//@aux-build:proc_macros.rs +//@aux-build:proc_macros.rs:proc-macro #![feature(custom_inner_attributes)] #![allow(clippy::needless_pub_self, unused)] #![warn(clippy::pub_without_shorthand)] diff --git a/tests/ui/pub_without_shorthand.rs b/tests/ui/pub_without_shorthand.rs index 38f4da85a49..1f2ef7ece39 100644 --- a/tests/ui/pub_without_shorthand.rs +++ b/tests/ui/pub_without_shorthand.rs @@ -1,5 +1,5 @@ //@run-rustfix -//@aux-build:proc_macros.rs +//@aux-build:proc_macros.rs:proc-macro #![feature(custom_inner_attributes)] #![allow(clippy::needless_pub_self, unused)] #![warn(clippy::pub_without_shorthand)] From b713cd5945501c07990e9845eed7a5e612d1c135 Mon Sep 17 00:00:00 2001 From: y21 <30553356+y21@users.noreply.github.com> Date: Wed, 28 Jun 2023 11:35:10 +0200 Subject: [PATCH 290/310] move `is_in_trait_method` to utils and rename --- clippy_lints/src/unused_async.rs | 19 +++---------------- clippy_utils/src/lib.rs | 12 ++++++++++++ 2 files changed, 15 insertions(+), 16 deletions(-) diff --git a/clippy_lints/src/unused_async.rs b/clippy_lints/src/unused_async.rs index 21153973dff..5e42cf7e4f3 100644 --- a/clippy_lints/src/unused_async.rs +++ b/clippy_lints/src/unused_async.rs @@ -1,6 +1,7 @@ use clippy_utils::diagnostics::span_lint_and_then; +use clippy_utils::is_def_id_trait_method; use rustc_hir::intravisit::{walk_body, walk_expr, walk_fn, FnKind, Visitor}; -use rustc_hir::{Body, Expr, ExprKind, FnDecl, ItemKind, Node, YieldSource}; +use rustc_hir::{Body, Expr, ExprKind, FnDecl, YieldSource}; use rustc_lint::{LateContext, LateLintPass}; use rustc_middle::hir::nested_filter; use rustc_session::{declare_lint_pass, declare_tool_lint}; @@ -81,20 +82,6 @@ impl<'a, 'tcx> Visitor<'tcx> for AsyncFnVisitor<'a, 'tcx> { } } -/// Checks if the `def_id` belongs to a function and that function is part of a trait impl, -/// in which case we shouldn't lint because `async` is part of the trait definition and therefore -/// can't be removed. -fn is_in_trait_impl(cx: &LateContext<'_>, def_id: LocalDefId) -> bool { - if let Some(hir_id) = cx.tcx.opt_local_def_id_to_hir_id(def_id) - && let Node::Item(item) = cx.tcx.hir().get_parent(hir_id) - && let ItemKind::Impl(imp) = item.kind - { - imp.of_trait.is_some() - } else { - false - } -} - impl<'tcx> LateLintPass<'tcx> for UnusedAsync { fn check_fn( &mut self, @@ -105,7 +92,7 @@ impl<'tcx> LateLintPass<'tcx> for UnusedAsync { span: Span, def_id: LocalDefId, ) { - if !span.from_expansion() && fn_kind.asyncness().is_async() && !is_in_trait_impl(cx, def_id) { + if !span.from_expansion() && fn_kind.asyncness().is_async() && !is_def_id_trait_method(cx, def_id) { let mut visitor = AsyncFnVisitor { cx, found_await: false, diff --git a/clippy_utils/src/lib.rs b/clippy_utils/src/lib.rs index 078dcef1927..727b59f1f43 100644 --- a/clippy_utils/src/lib.rs +++ b/clippy_utils/src/lib.rs @@ -327,6 +327,18 @@ pub fn is_trait_method(cx: &LateContext<'_>, expr: &Expr<'_>, diag_item: Symbol) .map_or(false, |did| is_diag_trait_item(cx, did, diag_item)) } +/// Checks if the `def_id` belongs to a function that is part of a trait impl. +pub fn is_def_id_trait_method(cx: &LateContext<'_>, def_id: LocalDefId) -> bool { + if let Some(hir_id) = cx.tcx.opt_local_def_id_to_hir_id(def_id) + && let Node::Item(item) = cx.tcx.hir().get_parent(hir_id) + && let ItemKind::Impl(imp) = item.kind + { + imp.of_trait.is_some() + } else { + false + } +} + /// Checks if the given expression is a path referring an item on the trait /// that is marked with the given diagnostic item. /// From 70610c00186cd9fd33f357fe2243822a3008049a Mon Sep 17 00:00:00 2001 From: y21 <30553356+y21@users.noreply.github.com> Date: Wed, 28 Jun 2023 12:41:18 +0200 Subject: [PATCH 291/310] lint in nested bodies if `try` is in outer body --- clippy_lints/src/question_mark.rs | 22 ++++++++++++++++++---- tests/ui/question_mark.fixed | 10 ++++++++++ tests/ui/question_mark.rs | 14 ++++++++++++++ tests/ui/question_mark.stderr | 12 +++++++++++- 4 files changed, 53 insertions(+), 5 deletions(-) diff --git a/clippy_lints/src/question_mark.rs b/clippy_lints/src/question_mark.rs index 036ad3e0d15..e3d940ad2a4 100644 --- a/clippy_lints/src/question_mark.rs +++ b/clippy_lints/src/question_mark.rs @@ -49,7 +49,7 @@ pub struct QuestionMark { /// very quickly, without having to walk up the parent chain, by simply checking /// if it is greater than zero. /// As for why we need this in the first place: - try_block_depth: u32, + try_block_depth_stack: Vec, } impl_lint_pass!(QuestionMark => [QUESTION_MARK]); @@ -150,7 +150,7 @@ fn expr_return_none_or_err( impl QuestionMark { fn inside_try_block(&self) -> bool { - self.try_block_depth > 0 + self.try_block_depth_stack.last() > Some(&0) } /// Checks if the given expression on the given context matches the following structure: @@ -268,13 +268,27 @@ impl<'tcx> LateLintPass<'tcx> for QuestionMark { fn check_block(&mut self, cx: &LateContext<'tcx>, block: &'tcx rustc_hir::Block<'tcx>) { if is_try_block(cx, block) { - self.try_block_depth += 1; + *self + .try_block_depth_stack + .last_mut() + .expect("blocks are always part of bodies and must have a depth") += 1; } } + fn check_body(&mut self, _: &LateContext<'tcx>, _: &'tcx rustc_hir::Body<'tcx>) { + self.try_block_depth_stack.push(0); + } + + fn check_body_post(&mut self, _: &LateContext<'tcx>, _: &'tcx rustc_hir::Body<'tcx>) { + self.try_block_depth_stack.pop(); + } + fn check_block_post(&mut self, cx: &LateContext<'tcx>, block: &'tcx rustc_hir::Block<'tcx>) { if is_try_block(cx, block) { - self.try_block_depth -= 1; + *self + .try_block_depth_stack + .last_mut() + .expect("blocks are always part of bodies and must have a depth") -= 1; } } } diff --git a/tests/ui/question_mark.fixed b/tests/ui/question_mark.fixed index f257378842b..2d8920ccc42 100644 --- a/tests/ui/question_mark.fixed +++ b/tests/ui/question_mark.fixed @@ -239,6 +239,16 @@ fn issue8628(a: Option) -> Option { b.or(Some(128)) } +fn issue6828_nested_body() -> Option { + try { + fn f2(a: Option) -> Option { + a?; + Some(32) + } + 123 + } +} + // should not lint, `?` operator not available in const context const fn issue9175(option: Option<()>) -> Option<()> { if option.is_none() { diff --git a/tests/ui/question_mark.rs b/tests/ui/question_mark.rs index 29d79b078ac..69451c17ee7 100644 --- a/tests/ui/question_mark.rs +++ b/tests/ui/question_mark.rs @@ -275,6 +275,20 @@ fn issue8628(a: Option) -> Option { b.or(Some(128)) } +fn issue6828_nested_body() -> Option { + try { + fn f2(a: Option) -> Option { + if a.is_none() { + return None; + // do lint here, the outer `try` is not relevant here + // https://github.com/rust-lang/rust-clippy/pull/11001#issuecomment-1610636867 + } + Some(32) + } + 123 + } +} + // should not lint, `?` operator not available in const context const fn issue9175(option: Option<()>) -> Option<()> { if option.is_none() { diff --git a/tests/ui/question_mark.stderr b/tests/ui/question_mark.stderr index 86d89942cc0..2cfd7586308 100644 --- a/tests/ui/question_mark.stderr +++ b/tests/ui/question_mark.stderr @@ -130,5 +130,15 @@ LL | | return Err(err); LL | | } | |_____^ help: replace it with: `func_returning_result()?;` -error: aborting due to 15 previous errors +error: this block may be rewritten with the `?` operator + --> $DIR/question_mark.rs:281:13 + | +LL | / if a.is_none() { +LL | | return None; +LL | | // do lint here, the outer `try` is not relevant here +LL | | // https://github.com/rust-lang/rust-clippy/pull/11001#issuecomment-1610636867 +LL | | } + | |_____________^ help: replace it with: `a?;` + +error: aborting due to 16 previous errors From cee4c4169c0f98bafe2e2c6cd6d3d2d401e5ce18 Mon Sep 17 00:00:00 2001 From: y21 <30553356+y21@users.noreply.github.com> Date: Wed, 28 Jun 2023 17:00:54 +0200 Subject: [PATCH 292/310] allow dead code in the test --- tests/ui/option_if_let_else.fixed | 4 +--- tests/ui/option_if_let_else.rs | 4 +--- tests/ui/option_if_let_else.stderr | 4 ++-- 3 files changed, 4 insertions(+), 8 deletions(-) diff --git a/tests/ui/option_if_let_else.fixed b/tests/ui/option_if_let_else.fixed index 44ab8ebb50a..8e59e4375d2 100644 --- a/tests/ui/option_if_let_else.fixed +++ b/tests/ui/option_if_let_else.fixed @@ -198,8 +198,6 @@ fn main() { let _ = res.map_or(1, |a| a + 1); let _ = res.map_or(1, |a| a + 1); let _ = res.map_or(5, |a| a + 1); - issue10729::reproduce(&None); - issue10729::reproduce2(&mut None); } #[allow(dead_code)] @@ -212,7 +210,7 @@ fn issue9742() -> Option<&'static str> { } mod issue10729 { - #![allow(clippy::unit_arg)] + #![allow(clippy::unit_arg, dead_code)] pub fn reproduce(initial: &Option) { // 👇 needs `.as_ref()` because initial is an `&Option<_>` diff --git a/tests/ui/option_if_let_else.rs b/tests/ui/option_if_let_else.rs index 9358c20ab95..e72edf2a8e3 100644 --- a/tests/ui/option_if_let_else.rs +++ b/tests/ui/option_if_let_else.rs @@ -239,8 +239,6 @@ fn main() { Ok(a) => a + 1, }; let _ = if let Ok(a) = res { a + 1 } else { 5 }; - issue10729::reproduce(&None); - issue10729::reproduce2(&mut None); } #[allow(dead_code)] @@ -253,7 +251,7 @@ fn issue9742() -> Option<&'static str> { } mod issue10729 { - #![allow(clippy::unit_arg)] + #![allow(clippy::unit_arg, dead_code)] pub fn reproduce(initial: &Option) { // 👇 needs `.as_ref()` because initial is an `&Option<_>` diff --git a/tests/ui/option_if_let_else.stderr b/tests/ui/option_if_let_else.stderr index fde27f21690..aa2da217400 100644 --- a/tests/ui/option_if_let_else.stderr +++ b/tests/ui/option_if_let_else.stderr @@ -272,7 +272,7 @@ LL | let _ = if let Ok(a) = res { a + 1 } else { 5 }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `res.map_or(5, |a| a + 1)` error: use Option::map_or instead of an if let/else - --> $DIR/option_if_let_else.rs:260:9 + --> $DIR/option_if_let_else.rs:258:9 | LL | / match initial { LL | | Some(value) => do_something(value), @@ -281,7 +281,7 @@ LL | | } | |_________^ help: try: `initial.as_ref().map_or({}, |value| do_something(value))` error: use Option::map_or instead of an if let/else - --> $DIR/option_if_let_else.rs:267:9 + --> $DIR/option_if_let_else.rs:265:9 | LL | / match initial { LL | | Some(value) => do_something2(value), From 211278bc862f245c11c586f1b2e6ac746ace7399 Mon Sep 17 00:00:00 2001 From: darklyspaced Date: Thu, 29 Jun 2023 10:18:38 +0800 Subject: [PATCH 293/310] updated list of lints that use msrv --- clippy_lints/src/utils/conf.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clippy_lints/src/utils/conf.rs b/clippy_lints/src/utils/conf.rs index 12197666b30..5c17b243d7c 100644 --- a/clippy_lints/src/utils/conf.rs +++ b/clippy_lints/src/utils/conf.rs @@ -294,7 +294,7 @@ define_Conf! { /// /// Suppress lints whenever the suggested change would cause breakage for other crates. (avoid_breaking_exported_api: bool = true), - /// Lint: MANUAL_SPLIT_ONCE, MANUAL_STR_REPEAT, CLONED_INSTEAD_OF_COPIED, REDUNDANT_FIELD_NAMES, REDUNDANT_STATIC_LIFETIMES, FILTER_MAP_NEXT, CHECKED_CONVERSIONS, MANUAL_RANGE_CONTAINS, USE_SELF, MEM_REPLACE_WITH_DEFAULT, MANUAL_NON_EXHAUSTIVE, OPTION_AS_REF_DEREF, MAP_UNWRAP_OR, MATCH_LIKE_MATCHES_MACRO, MANUAL_STRIP, MISSING_CONST_FOR_FN, UNNESTED_OR_PATTERNS, FROM_OVER_INTO, PTR_AS_PTR, IF_THEN_SOME_ELSE_NONE, APPROX_CONSTANT, DEPRECATED_CFG_ATTR, INDEX_REFUTABLE_SLICE, MAP_CLONE, BORROW_AS_PTR, MANUAL_BITS, ERR_EXPECT, CAST_ABS_TO_UNSIGNED, UNINLINED_FORMAT_ARGS, MANUAL_CLAMP, MANUAL_LET_ELSE, UNCHECKED_DURATION_SUBTRACTION, COLLAPSIBLE_STR_REPLACE, SEEK_FROM_CURRENT, SEEK_REWIND, UNNECESSARY_LAZY_EVALUATIONS, TRANSMUTE_PTR_TO_REF, ALMOST_COMPLETE_RANGE, NEEDLESS_BORROW, DERIVABLE_IMPLS, MANUAL_IS_ASCII_CHECK, MANUAL_REM_EUCLID, MANUAL_RETAIN, TYPE_REPETITION_IN_BOUNDS. + /// Lint: MANUAL_SPLIT_ONCE, MANUAL_STR_REPEAT, CLONED_INSTEAD_OF_COPIED, REDUNDANT_FIELD_NAMES, OPTION_MAP_UNWRAP_OR, REDUNDANT_STATIC_LIFETIMES, FILTER_MAP_NEXT, CHECKED_CONVERSIONS, MANUAL_RANGE_CONTAINS, USE_SELF, MEM_REPLACE_WITH_DEFAULT, MANUAL_NON_EXHAUSTIVE, OPTION_AS_REF_DEREF, MAP_UNWRAP_OR, MATCH_LIKE_MATCHES_MACRO, MANUAL_STRIP, MISSING_CONST_FOR_FN, UNNESTED_OR_PATTERNS, FROM_OVER_INTO, PTR_AS_PTR, IF_THEN_SOME_ELSE_NONE, APPROX_CONSTANT, DEPRECATED_CFG_ATTR, INDEX_REFUTABLE_SLICE, MAP_CLONE, BORROW_AS_PTR, MANUAL_BITS, ERR_EXPECT, CAST_ABS_TO_UNSIGNED, UNINLINED_FORMAT_ARGS, MANUAL_CLAMP, MANUAL_LET_ELSE, UNCHECKED_DURATION_SUBTRACTION, COLLAPSIBLE_STR_REPLACE, SEEK_FROM_CURRENT, SEEK_REWIND, UNNECESSARY_LAZY_EVALUATIONS, TRANSMUTE_PTR_TO_REF, ALMOST_COMPLETE_RANGE, NEEDLESS_BORROW, DERIVABLE_IMPLS, MANUAL_IS_ASCII_CHECK, MANUAL_REM_EUCLID, MANUAL_RETAIN, TYPE_REPETITION_IN_BOUNDS. /// /// The minimum rust version that the project supports (msrv: Option = None), From bb42b1808156194c9293621a8a1647ac957133ea Mon Sep 17 00:00:00 2001 From: darklyspaced Date: Thu, 29 Jun 2023 17:30:39 +0800 Subject: [PATCH 294/310] ran `cargo collect-metadata` --- book/src/lint_configuration.md | 1 + 1 file changed, 1 insertion(+) diff --git a/book/src/lint_configuration.md b/book/src/lint_configuration.md index 9bf7b1949c4..86b5d472a52 100644 --- a/book/src/lint_configuration.md +++ b/book/src/lint_configuration.md @@ -108,6 +108,7 @@ The minimum rust version that the project supports * [`manual_str_repeat`](https://rust-lang.github.io/rust-clippy/master/index.html#manual_str_repeat) * [`cloned_instead_of_copied`](https://rust-lang.github.io/rust-clippy/master/index.html#cloned_instead_of_copied) * [`redundant_field_names`](https://rust-lang.github.io/rust-clippy/master/index.html#redundant_field_names) +* [`option_map_unwrap_or`](https://rust-lang.github.io/rust-clippy/master/index.html#option_map_unwrap_or) * [`redundant_static_lifetimes`](https://rust-lang.github.io/rust-clippy/master/index.html#redundant_static_lifetimes) * [`filter_map_next`](https://rust-lang.github.io/rust-clippy/master/index.html#filter_map_next) * [`checked_conversions`](https://rust-lang.github.io/rust-clippy/master/index.html#checked_conversions) From bfcc8ba444180dfc12bb113d1d500b81c9e87956 Mon Sep 17 00:00:00 2001 From: Catherine <114838443+Centri3@users.noreply.github.com> Date: Sat, 24 Jun 2023 07:40:09 -0500 Subject: [PATCH 295/310] New lint `tuple_array_conversions` --- CHANGELOG.md | 1 + clippy_lints/src/declared_lints.rs | 1 + clippy_lints/src/lib.rs | 2 + clippy_lints/src/tuple_array_conversions.rs | 187 ++++++++++++++++++++ tests/ui/tuple_array_conversions.rs | 43 +++++ tests/ui/tuple_array_conversions.stderr | 59 ++++++ 6 files changed, 293 insertions(+) create mode 100644 clippy_lints/src/tuple_array_conversions.rs create mode 100644 tests/ui/tuple_array_conversions.rs create mode 100644 tests/ui/tuple_array_conversions.stderr diff --git a/CHANGELOG.md b/CHANGELOG.md index 4debe304857..04917871c40 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5262,6 +5262,7 @@ Released 2018-09-13 [`trivial_regex`]: https://rust-lang.github.io/rust-clippy/master/index.html#trivial_regex [`trivially_copy_pass_by_ref`]: https://rust-lang.github.io/rust-clippy/master/index.html#trivially_copy_pass_by_ref [`try_err`]: https://rust-lang.github.io/rust-clippy/master/index.html#try_err +[`tuple_array_conversions`]: https://rust-lang.github.io/rust-clippy/master/index.html#tuple_array_conversions [`type_complexity`]: https://rust-lang.github.io/rust-clippy/master/index.html#type_complexity [`type_repetition_in_bounds`]: https://rust-lang.github.io/rust-clippy/master/index.html#type_repetition_in_bounds [`unchecked_duration_subtraction`]: https://rust-lang.github.io/rust-clippy/master/index.html#unchecked_duration_subtraction diff --git a/clippy_lints/src/declared_lints.rs b/clippy_lints/src/declared_lints.rs index 46f4082f0c7..316645e4066 100644 --- a/clippy_lints/src/declared_lints.rs +++ b/clippy_lints/src/declared_lints.rs @@ -624,6 +624,7 @@ pub(crate) static LINTS: &[&crate::LintInfo] = &[ crate::transmute::UNSOUND_COLLECTION_TRANSMUTE_INFO, crate::transmute::USELESS_TRANSMUTE_INFO, crate::transmute::WRONG_TRANSMUTE_INFO, + crate::tuple_array_conversions::TUPLE_ARRAY_CONVERSIONS_INFO, crate::types::BORROWED_BOX_INFO, crate::types::BOX_COLLECTION_INFO, crate::types::LINKEDLIST_INFO, diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index 5ab28b5c70c..39301b5344a 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -311,6 +311,7 @@ mod to_digit_is_some; mod trailing_empty_array; mod trait_bounds; mod transmute; +mod tuple_array_conversions; mod types; mod undocumented_unsafe_blocks; mod unicode; @@ -1072,6 +1073,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: }); store.register_late_pass(|_| Box::new(manual_range_patterns::ManualRangePatterns)); store.register_early_pass(|| Box::new(visibility::Visibility)); + store.register_late_pass(|_| Box::new(tuple_array_conversions::TupleArrayConversions)); // add lints here, do not remove this comment, it's used in `new_lint` } diff --git a/clippy_lints/src/tuple_array_conversions.rs b/clippy_lints/src/tuple_array_conversions.rs new file mode 100644 index 00000000000..9640083f764 --- /dev/null +++ b/clippy_lints/src/tuple_array_conversions.rs @@ -0,0 +1,187 @@ +use clippy_utils::{diagnostics::span_lint_and_help, is_from_proc_macro, path_to_local}; +use rustc_hir::*; +use rustc_lint::{LateContext, LateLintPass, LintContext}; +use rustc_middle::{lint::in_external_macro, ty}; +use rustc_session::{declare_lint_pass, declare_tool_lint}; + +declare_clippy_lint! { + /// ### What it does + /// + /// ### Why is this bad? + /// + /// ### Example + /// ```rust,ignore + /// let t1 = &[(1, 2), (3, 4)]; + /// let v1: Vec<[u32; 2]> = t1.iter().map(|&(a, b)| [a, b]).collect(); + /// ``` + /// Use instead: + /// ```rust,ignore + /// let t1 = &[(1, 2), (3, 4)]; + /// let v1: Vec<[u32; 2]> = t1.iter().map(|&t| t.into()).collect(); + /// ``` + #[clippy::version = "1.72.0"] + pub TUPLE_ARRAY_CONVERSIONS, + complexity, + "default lint description" +} +declare_lint_pass!(TupleArrayConversions => [TUPLE_ARRAY_CONVERSIONS]); + +impl LateLintPass<'_> for TupleArrayConversions { + fn check_expr<'tcx>(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>) { + if !in_external_macro(cx.sess(), expr.span) { + _ = check_array(cx, expr) || check_tuple(cx, expr); + } + } +} + +fn check_array<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>) -> bool { + let ExprKind::Array(elements) = expr.kind else { + return false; + }; + if !(1..=12).contains(&elements.len()) { + return false; + } + + if let Some(locals) = path_to_locals(cx, elements) + && locals.iter().all(|local| { + matches!( + local, + Node::Pat(pat) if matches!( + cx.typeck_results().pat_ty(backtrack_pat(cx, pat)).peel_refs().kind(), + ty::Tuple(_), + ), + ) + }) + { + return emit_lint(cx, expr, ToType::Array); + } + + if let Some(elements) = elements + .iter() + .map(|expr| { + if let ExprKind::Field(path, _) = expr.kind { + return Some(path); + }; + + None + }) + .collect::>>>() + && let Some(locals) = path_to_locals(cx, elements) + && locals.iter().all(|local| { + matches!( + local, + Node::Pat(pat) if matches!( + cx.typeck_results().pat_ty(backtrack_pat(cx, pat)).peel_refs().kind(), + ty::Tuple(_), + ), + ) + }) + { + return emit_lint(cx, expr, ToType::Array); + } + + false +} + +fn check_tuple<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>) -> bool { + let ExprKind::Tup(elements) = expr.kind else { + return false; + }; + if !(1..=12).contains(&elements.len()) { + return false; + }; + if let Some(locals) = path_to_locals(cx, elements) + && locals.iter().all(|local| { + matches!( + local, + Node::Pat(pat) if matches!( + cx.typeck_results().pat_ty(backtrack_pat(cx, pat)).peel_refs().kind(), + ty::Array(_, _), + ), + ) + }) + { + return emit_lint(cx, expr, ToType::Tuple); + } + + if let Some(elements) = elements + .iter() + .map(|expr| { + if let ExprKind::Index(path, _) = expr.kind { + return Some(path); + }; + + None + }) + .collect::>>>() + && let Some(locals) = path_to_locals(cx, elements.clone()) + && locals.iter().all(|local| { + matches!( + local, + Node::Pat(pat) if cx.typeck_results() + .pat_ty(backtrack_pat(cx, pat)) + .peel_refs() + .is_array() + ) + }) + { + return emit_lint(cx, expr, ToType::Tuple); + } + + false +} + +/// Walks up the `Pat` until it's reached the final containing `Pat`. +fn backtrack_pat<'tcx>(cx: &LateContext<'tcx>, start: &'tcx Pat<'tcx>) -> &'tcx Pat<'tcx> { + let mut end = start; + for (_, node) in cx.tcx.hir().parent_iter(start.hir_id) { + if let Node::Pat(pat) = node { + end = pat; + } else { + break; + } + } + end +} + +fn path_to_locals<'tcx>( + cx: &LateContext<'tcx>, + exprs: impl IntoIterator>, +) -> Option>> { + exprs + .into_iter() + .map(|element| path_to_local(element).and_then(|local| cx.tcx.hir().find(local))) + .collect() +} + +#[derive(Clone, Copy)] +enum ToType { + Array, + Tuple, +} + +impl ToType { + fn help(self) -> &'static str { + match self { + ToType::Array => "it looks like you're trying to convert a tuple to an array", + ToType::Tuple => "it looks like you're trying to convert an array to a tuple", + } + } +} + +fn emit_lint<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>, to_type: ToType) -> bool { + if !is_from_proc_macro(cx, expr) { + span_lint_and_help( + cx, + TUPLE_ARRAY_CONVERSIONS, + expr.span, + to_type.help(), + None, + "use `.into()` instead", + ); + + return true; + } + + false +} diff --git a/tests/ui/tuple_array_conversions.rs b/tests/ui/tuple_array_conversions.rs new file mode 100644 index 00000000000..061c05e98d0 --- /dev/null +++ b/tests/ui/tuple_array_conversions.rs @@ -0,0 +1,43 @@ +//@aux-build:proc_macros.rs:proc-macro +#![allow(clippy::useless_vec, unused)] +#![warn(clippy::tuple_array_conversions)] + +#[macro_use] +extern crate proc_macros; + +fn main() { + let x = [1, 2]; + let x = (x[0], x[1]); + let x = [x.0, x.1]; + let x = &[1, 2]; + let x = (x[0], x[1]); + + let t1: &[(u32, u32)] = &[(1, 2), (3, 4)]; + let v1: Vec<[u32; 2]> = t1.iter().map(|&(a, b)| [a, b]).collect(); + t1.iter().for_each(|&(a, b)| _ = [a, b]); + let t2: Vec<(u32, u32)> = v1.iter().map(|&[a, b]| (a, b)).collect(); + t1.iter().for_each(|&(a, b)| _ = [a, b]); + // Do not lint + let v2: Vec<[u32; 2]> = t1.iter().map(|&t| t.into()).collect(); + let t3: Vec<(u32, u32)> = v2.iter().map(|&v| v.into()).collect(); + let x = [1; 13]; + let x = (x[0], x[1], x[2], x[3], x[4], x[5], x[6], x[7], x[8], x[9], x[10], x[11], x[12]); + let x = [x.0, x.1, x.2, x.3, x.4, x.5, x.6, x.7, x.8, x.9, x.10, x.11, x.12]; + let x = (1, 2); + let x = (x.0, x.1); + let x = [1, 2]; + let x = [x[0], x[1]]; + let x = vec![1, 2]; + let x = (x[0], x[1]); + external! { + let t1: &[(u32, u32)] = &[(1, 2), (3, 4)]; + let v1: Vec<[u32; 2]> = t1.iter().map(|&(a, b)| [a, b]).collect(); + let t2: Vec<(u32, u32)> = v1.iter().map(|&[a, b]| (a, b)).collect(); + } + with_span! { + span + let t1: &[(u32, u32)] = &[(1, 2), (3, 4)]; + let v1: Vec<[u32; 2]> = t1.iter().map(|&(a, b)| [a, b]).collect(); + let t2: Vec<(u32, u32)> = v1.iter().map(|&[a, b]| (a, b)).collect(); + } +} diff --git a/tests/ui/tuple_array_conversions.stderr b/tests/ui/tuple_array_conversions.stderr new file mode 100644 index 00000000000..aba461e51f7 --- /dev/null +++ b/tests/ui/tuple_array_conversions.stderr @@ -0,0 +1,59 @@ +error: it looks like you're trying to convert an array to a tuple + --> $DIR/tuple_array_conversions.rs:10:13 + | +LL | let x = (x[0], x[1]); + | ^^^^^^^^^^^^ + | + = help: use `.into()` instead + = note: `-D clippy::tuple-array-conversions` implied by `-D warnings` + +error: it looks like you're trying to convert a tuple to an array + --> $DIR/tuple_array_conversions.rs:11:13 + | +LL | let x = [x.0, x.1]; + | ^^^^^^^^^^ + | + = help: use `.into()` instead + +error: it looks like you're trying to convert an array to a tuple + --> $DIR/tuple_array_conversions.rs:13:13 + | +LL | let x = (x[0], x[1]); + | ^^^^^^^^^^^^ + | + = help: use `.into()` instead + +error: it looks like you're trying to convert a tuple to an array + --> $DIR/tuple_array_conversions.rs:16:53 + | +LL | let v1: Vec<[u32; 2]> = t1.iter().map(|&(a, b)| [a, b]).collect(); + | ^^^^^^ + | + = help: use `.into()` instead + +error: it looks like you're trying to convert a tuple to an array + --> $DIR/tuple_array_conversions.rs:17:38 + | +LL | t1.iter().for_each(|&(a, b)| _ = [a, b]); + | ^^^^^^ + | + = help: use `.into()` instead + +error: it looks like you're trying to convert an array to a tuple + --> $DIR/tuple_array_conversions.rs:18:55 + | +LL | let t2: Vec<(u32, u32)> = v1.iter().map(|&[a, b]| (a, b)).collect(); + | ^^^^^^ + | + = help: use `.into()` instead + +error: it looks like you're trying to convert a tuple to an array + --> $DIR/tuple_array_conversions.rs:19:38 + | +LL | t1.iter().for_each(|&(a, b)| _ = [a, b]); + | ^^^^^^ + | + = help: use `.into()` instead + +error: aborting due to 7 previous errors + From b1acbde618084db21339030db44120d84efc93ed Mon Sep 17 00:00:00 2001 From: Catherine <114838443+Centri3@users.noreply.github.com> Date: Sat, 24 Jun 2023 08:24:13 -0500 Subject: [PATCH 296/310] Add msrv check and make test pass --- clippy_lints/src/lib.rs | 2 +- clippy_lints/src/tuple_array_conversions.rs | 153 +++++++++++++------- clippy_lints/src/upper_case_acronyms.rs | 2 +- clippy_lints/src/utils/conf.rs | 2 +- clippy_utils/src/msrvs.rs | 1 + tests/ui/tuple_array_conversions.rs | 36 ++++- tests/ui/tuple_array_conversions.stderr | 56 ++++++- 7 files changed, 188 insertions(+), 64 deletions(-) diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index 39301b5344a..87329ee5e14 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -1073,7 +1073,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: }); store.register_late_pass(|_| Box::new(manual_range_patterns::ManualRangePatterns)); store.register_early_pass(|| Box::new(visibility::Visibility)); - store.register_late_pass(|_| Box::new(tuple_array_conversions::TupleArrayConversions)); + store.register_late_pass(move |_| Box::new(tuple_array_conversions::TupleArrayConversions { msrv: msrv() })); // add lints here, do not remove this comment, it's used in `new_lint` } diff --git a/clippy_lints/src/tuple_array_conversions.rs b/clippy_lints/src/tuple_array_conversions.rs index 9640083f764..9d5e872bd78 100644 --- a/clippy_lints/src/tuple_array_conversions.rs +++ b/clippy_lints/src/tuple_array_conversions.rs @@ -1,13 +1,23 @@ -use clippy_utils::{diagnostics::span_lint_and_help, is_from_proc_macro, path_to_local}; -use rustc_hir::*; +use clippy_utils::{ + diagnostics::span_lint_and_help, + is_from_proc_macro, + msrvs::{self, Msrv}, + path_to_local, +}; +use itertools::Itertools; +use rustc_hir::{Expr, ExprKind, Node, Pat}; use rustc_lint::{LateContext, LateLintPass, LintContext}; use rustc_middle::{lint::in_external_macro, ty}; -use rustc_session::{declare_lint_pass, declare_tool_lint}; +use rustc_session::{declare_tool_lint, impl_lint_pass}; +use std::iter::once; declare_clippy_lint! { /// ### What it does + /// Checks for tuple<=>array conversions that are not done with `.into()`. /// /// ### Why is this bad? + /// It's overly complex. `.into()` works for tuples<=>arrays with less than 13 elements and + /// conveys the intent a lot better, while also leaving less room for bugs! /// /// ### Example /// ```rust,ignore @@ -22,16 +32,23 @@ declare_clippy_lint! { #[clippy::version = "1.72.0"] pub TUPLE_ARRAY_CONVERSIONS, complexity, - "default lint description" + "checks for tuple<=>array conversions that are not done with `.into()`" +} +impl_lint_pass!(TupleArrayConversions => [TUPLE_ARRAY_CONVERSIONS]); + +#[derive(Clone)] +pub struct TupleArrayConversions { + pub msrv: Msrv, } -declare_lint_pass!(TupleArrayConversions => [TUPLE_ARRAY_CONVERSIONS]); impl LateLintPass<'_> for TupleArrayConversions { fn check_expr<'tcx>(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>) { - if !in_external_macro(cx.sess(), expr.span) { + if !in_external_macro(cx.sess(), expr.span) && self.msrv.meets(msrvs::TUPLE_ARRAY_CONVERSIONS) { _ = check_array(cx, expr) || check_tuple(cx, expr); } } + + extract_msrv_attr!(LateContext); } fn check_array<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>) -> bool { @@ -42,15 +59,22 @@ fn check_array<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>) -> bool { return false; } - if let Some(locals) = path_to_locals(cx, elements) - && locals.iter().all(|local| { - matches!( - local, - Node::Pat(pat) if matches!( - cx.typeck_results().pat_ty(backtrack_pat(cx, pat)).peel_refs().kind(), - ty::Tuple(_), - ), - ) + if let Some(locals) = path_to_locals(cx, &elements.iter().collect_vec()) + && let [first, rest @ ..] = &*locals + && let Node::Pat(first_pat) = first + && let first_id = parent_pat(cx, first_pat).hir_id + && rest.iter().chain(once(first)).all(|local| { + if let Node::Pat(pat) = local + && let parent = parent_pat(cx, pat) + && parent.hir_id == first_id + { + return matches!( + cx.typeck_results().pat_ty(parent).peel_refs().kind(), + ty::Tuple(len) if len.len() == elements.len() + ); + } + + false }) { return emit_lint(cx, expr, ToType::Array); @@ -66,15 +90,22 @@ fn check_array<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>) -> bool { None }) .collect::>>>() - && let Some(locals) = path_to_locals(cx, elements) - && locals.iter().all(|local| { - matches!( - local, - Node::Pat(pat) if matches!( - cx.typeck_results().pat_ty(backtrack_pat(cx, pat)).peel_refs().kind(), - ty::Tuple(_), - ), - ) + && let Some(locals) = path_to_locals(cx, &elements) + && let [first, rest @ ..] = &*locals + && let Node::Pat(first_pat) = first + && let first_id = parent_pat(cx, first_pat).hir_id + && rest.iter().chain(once(first)).all(|local| { + if let Node::Pat(pat) = local + && let parent = parent_pat(cx, pat) + && parent.hir_id == first_id + { + return matches!( + cx.typeck_results().pat_ty(parent).peel_refs().kind(), + ty::Tuple(len) if len.len() == elements.len() + ); + } + + false }) { return emit_lint(cx, expr, ToType::Array); @@ -83,6 +114,7 @@ fn check_array<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>) -> bool { false } +#[expect(clippy::cast_possible_truncation)] fn check_tuple<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>) -> bool { let ExprKind::Tup(elements) = expr.kind else { return false; @@ -90,15 +122,23 @@ fn check_tuple<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>) -> bool { if !(1..=12).contains(&elements.len()) { return false; }; - if let Some(locals) = path_to_locals(cx, elements) - && locals.iter().all(|local| { - matches!( - local, - Node::Pat(pat) if matches!( - cx.typeck_results().pat_ty(backtrack_pat(cx, pat)).peel_refs().kind(), - ty::Array(_, _), - ), - ) + + if let Some(locals) = path_to_locals(cx, &elements.iter().collect_vec()) + && let [first, rest @ ..] = &*locals + && let Node::Pat(first_pat) = first + && let first_id = parent_pat(cx, first_pat).hir_id + && rest.iter().chain(once(first)).all(|local| { + if let Node::Pat(pat) = local + && let parent = parent_pat(cx, pat) + && parent.hir_id == first_id + { + return matches!( + cx.typeck_results().pat_ty(parent).peel_refs().kind(), + ty::Array(_, len) if len.eval_target_usize(cx.tcx, cx.param_env) as usize == elements.len() + ); + } + + false }) { return emit_lint(cx, expr, ToType::Tuple); @@ -114,15 +154,22 @@ fn check_tuple<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>) -> bool { None }) .collect::>>>() - && let Some(locals) = path_to_locals(cx, elements.clone()) - && locals.iter().all(|local| { - matches!( - local, - Node::Pat(pat) if cx.typeck_results() - .pat_ty(backtrack_pat(cx, pat)) - .peel_refs() - .is_array() - ) + && let Some(locals) = path_to_locals(cx, &elements) + && let [first, rest @ ..] = &*locals + && let Node::Pat(first_pat) = first + && let first_id = parent_pat(cx, first_pat).hir_id + && rest.iter().chain(once(first)).all(|local| { + if let Node::Pat(pat) = local + && let parent = parent_pat(cx, pat) + && parent.hir_id == first_id + { + return matches!( + cx.typeck_results().pat_ty(parent).peel_refs().kind(), + ty::Array(_, len) if len.eval_target_usize(cx.tcx, cx.param_env) as usize == elements.len() + ); + } + + false }) { return emit_lint(cx, expr, ToType::Tuple); @@ -132,7 +179,7 @@ fn check_tuple<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>) -> bool { } /// Walks up the `Pat` until it's reached the final containing `Pat`. -fn backtrack_pat<'tcx>(cx: &LateContext<'tcx>, start: &'tcx Pat<'tcx>) -> &'tcx Pat<'tcx> { +fn parent_pat<'tcx>(cx: &LateContext<'tcx>, start: &'tcx Pat<'tcx>) -> &'tcx Pat<'tcx> { let mut end = start; for (_, node) in cx.tcx.hir().parent_iter(start.hir_id) { if let Node::Pat(pat) = node { @@ -144,12 +191,9 @@ fn backtrack_pat<'tcx>(cx: &LateContext<'tcx>, start: &'tcx Pat<'tcx>) -> &'tcx end } -fn path_to_locals<'tcx>( - cx: &LateContext<'tcx>, - exprs: impl IntoIterator>, -) -> Option>> { +fn path_to_locals<'tcx>(cx: &LateContext<'tcx>, exprs: &[&'tcx Expr<'tcx>]) -> Option>> { exprs - .into_iter() + .iter() .map(|element| path_to_local(element).and_then(|local| cx.tcx.hir().find(local))) .collect() } @@ -161,12 +205,19 @@ enum ToType { } impl ToType { - fn help(self) -> &'static str { + fn msg(self) -> &'static str { match self { ToType::Array => "it looks like you're trying to convert a tuple to an array", ToType::Tuple => "it looks like you're trying to convert an array to a tuple", } } + + fn help(self) -> &'static str { + match self { + ToType::Array => "use `.into()` instead, or `<[T; N]>::from` if type annotations are needed", + ToType::Tuple => "use `.into()` instead, or `<(T0, T1, ..., Tn)>::from` if type annotations are needed", + } + } } fn emit_lint<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>, to_type: ToType) -> bool { @@ -175,9 +226,9 @@ fn emit_lint<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>, to_type: ToTy cx, TUPLE_ARRAY_CONVERSIONS, expr.span, - to_type.help(), + to_type.msg(), None, - "use `.into()` instead", + to_type.help(), ); return true; diff --git a/clippy_lints/src/upper_case_acronyms.rs b/clippy_lints/src/upper_case_acronyms.rs index 1d2d3eb12e1..4df1e3299ed 100644 --- a/clippy_lints/src/upper_case_acronyms.rs +++ b/clippy_lints/src/upper_case_acronyms.rs @@ -65,7 +65,7 @@ fn correct_ident(ident: &str) -> String { let mut ident = fragments.clone().next().unwrap(); for (ref prev, ref curr) in fragments.tuple_windows() { - if [prev, curr] + if <[&String; 2]>::from((prev, curr)) .iter() .all(|s| s.len() == 1 && s.chars().next().unwrap().is_ascii_uppercase()) { diff --git a/clippy_lints/src/utils/conf.rs b/clippy_lints/src/utils/conf.rs index 972e24aac51..89063964622 100644 --- a/clippy_lints/src/utils/conf.rs +++ b/clippy_lints/src/utils/conf.rs @@ -294,7 +294,7 @@ define_Conf! { /// /// Suppress lints whenever the suggested change would cause breakage for other crates. (avoid_breaking_exported_api: bool = true), - /// Lint: MANUAL_SPLIT_ONCE, MANUAL_STR_REPEAT, CLONED_INSTEAD_OF_COPIED, REDUNDANT_FIELD_NAMES, OPTION_MAP_UNWRAP_OR, REDUNDANT_STATIC_LIFETIMES, FILTER_MAP_NEXT, CHECKED_CONVERSIONS, MANUAL_RANGE_CONTAINS, USE_SELF, MEM_REPLACE_WITH_DEFAULT, MANUAL_NON_EXHAUSTIVE, OPTION_AS_REF_DEREF, MAP_UNWRAP_OR, MATCH_LIKE_MATCHES_MACRO, MANUAL_STRIP, MISSING_CONST_FOR_FN, UNNESTED_OR_PATTERNS, FROM_OVER_INTO, PTR_AS_PTR, IF_THEN_SOME_ELSE_NONE, APPROX_CONSTANT, DEPRECATED_CFG_ATTR, INDEX_REFUTABLE_SLICE, MAP_CLONE, BORROW_AS_PTR, MANUAL_BITS, ERR_EXPECT, CAST_ABS_TO_UNSIGNED, UNINLINED_FORMAT_ARGS, MANUAL_CLAMP, MANUAL_LET_ELSE, UNCHECKED_DURATION_SUBTRACTION, COLLAPSIBLE_STR_REPLACE, SEEK_FROM_CURRENT, SEEK_REWIND, UNNECESSARY_LAZY_EVALUATIONS, TRANSMUTE_PTR_TO_REF, ALMOST_COMPLETE_RANGE, NEEDLESS_BORROW, DERIVABLE_IMPLS, MANUAL_IS_ASCII_CHECK, MANUAL_REM_EUCLID, MANUAL_RETAIN, TYPE_REPETITION_IN_BOUNDS. + /// Lint: MANUAL_SPLIT_ONCE, MANUAL_STR_REPEAT, CLONED_INSTEAD_OF_COPIED, REDUNDANT_FIELD_NAMES, OPTION_MAP_UNWRAP_OR, REDUNDANT_STATIC_LIFETIMES, FILTER_MAP_NEXT, CHECKED_CONVERSIONS, MANUAL_RANGE_CONTAINS, USE_SELF, MEM_REPLACE_WITH_DEFAULT, MANUAL_NON_EXHAUSTIVE, OPTION_AS_REF_DEREF, MAP_UNWRAP_OR, MATCH_LIKE_MATCHES_MACRO, MANUAL_STRIP, MISSING_CONST_FOR_FN, UNNESTED_OR_PATTERNS, FROM_OVER_INTO, PTR_AS_PTR, IF_THEN_SOME_ELSE_NONE, APPROX_CONSTANT, DEPRECATED_CFG_ATTR, INDEX_REFUTABLE_SLICE, MAP_CLONE, BORROW_AS_PTR, MANUAL_BITS, ERR_EXPECT, CAST_ABS_TO_UNSIGNED, UNINLINED_FORMAT_ARGS, MANUAL_CLAMP, MANUAL_LET_ELSE, UNCHECKED_DURATION_SUBTRACTION, COLLAPSIBLE_STR_REPLACE, SEEK_FROM_CURRENT, SEEK_REWIND, UNNECESSARY_LAZY_EVALUATIONS, TRANSMUTE_PTR_TO_REF, ALMOST_COMPLETE_RANGE, NEEDLESS_BORROW, DERIVABLE_IMPLS, MANUAL_IS_ASCII_CHECK, MANUAL_REM_EUCLID, MANUAL_RETAIN, TYPE_REPETITION_IN_BOUNDS, TUPLE_ARRAY_CONVERSIONS. /// /// The minimum rust version that the project supports (msrv: Option = None), diff --git a/clippy_utils/src/msrvs.rs b/clippy_utils/src/msrvs.rs index 5aacca45146..1f70f11bd67 100644 --- a/clippy_utils/src/msrvs.rs +++ b/clippy_utils/src/msrvs.rs @@ -19,6 +19,7 @@ macro_rules! msrv_aliases { // names may refer to stabilized feature flags or library items msrv_aliases! { + 1,71,0 { TUPLE_ARRAY_CONVERSIONS } 1,70,0 { OPTION_IS_SOME_AND } 1,68,0 { PATH_MAIN_SEPARATOR_STR } 1,65,0 { LET_ELSE, POINTER_CAST_CONSTNESS } diff --git a/tests/ui/tuple_array_conversions.rs b/tests/ui/tuple_array_conversions.rs index 061c05e98d0..64aaa53be5c 100644 --- a/tests/ui/tuple_array_conversions.rs +++ b/tests/ui/tuple_array_conversions.rs @@ -1,5 +1,5 @@ //@aux-build:proc_macros.rs:proc-macro -#![allow(clippy::useless_vec, unused)] +#![allow(clippy::no_effect, clippy::useless_vec, unused)] #![warn(clippy::tuple_array_conversions)] #[macro_use] @@ -21,7 +21,9 @@ fn main() { let v2: Vec<[u32; 2]> = t1.iter().map(|&t| t.into()).collect(); let t3: Vec<(u32, u32)> = v2.iter().map(|&v| v.into()).collect(); let x = [1; 13]; - let x = (x[0], x[1], x[2], x[3], x[4], x[5], x[6], x[7], x[8], x[9], x[10], x[11], x[12]); + let x = ( + x[0], x[1], x[2], x[3], x[4], x[5], x[6], x[7], x[8], x[9], x[10], x[11], x[12], + ); let x = [x.0, x.1, x.2, x.3, x.4, x.5, x.6, x.7, x.8, x.9, x.10, x.11, x.12]; let x = (1, 2); let x = (x.0, x.1); @@ -29,6 +31,18 @@ fn main() { let x = [x[0], x[1]]; let x = vec![1, 2]; let x = (x[0], x[1]); + let x = [1; 3]; + let x = (x[0],); + let x = (1, 2, 3); + let x = [x.0]; + let x = (1, 2); + let y = (1, 2); + [x.0, y.0]; + [x.0, y.1]; + // FP + let x = [x.0, x.0]; + let x = (x[0], x[0]); + // How can this be fixed? external! { let t1: &[(u32, u32)] = &[(1, 2), (3, 4)]; let v1: Vec<[u32; 2]> = t1.iter().map(|&(a, b)| [a, b]).collect(); @@ -41,3 +55,21 @@ fn main() { let t2: Vec<(u32, u32)> = v1.iter().map(|&[a, b]| (a, b)).collect(); } } + +#[clippy::msrv = "1.70.0"] +fn msrv_too_low() { + let x = [1, 2]; + let x = (x[0], x[1]); + let x = [x.0, x.1]; + let x = &[1, 2]; + let x = (x[0], x[1]); +} + +#[clippy::msrv = "1.71.0"] +fn msrv_juust_right() { + let x = [1, 2]; + let x = (x[0], x[1]); + let x = [x.0, x.1]; + let x = &[1, 2]; + let x = (x[0], x[1]); +} diff --git a/tests/ui/tuple_array_conversions.stderr b/tests/ui/tuple_array_conversions.stderr index aba461e51f7..d9d59a611a0 100644 --- a/tests/ui/tuple_array_conversions.stderr +++ b/tests/ui/tuple_array_conversions.stderr @@ -4,7 +4,7 @@ error: it looks like you're trying to convert an array to a tuple LL | let x = (x[0], x[1]); | ^^^^^^^^^^^^ | - = help: use `.into()` instead + = help: use `.into()` instead, or `<(T0, T1, ..., Tn)>::from` if type annotations are needed = note: `-D clippy::tuple-array-conversions` implied by `-D warnings` error: it looks like you're trying to convert a tuple to an array @@ -13,7 +13,7 @@ error: it looks like you're trying to convert a tuple to an array LL | let x = [x.0, x.1]; | ^^^^^^^^^^ | - = help: use `.into()` instead + = help: use `.into()` instead, or `<[T; N]>::from` if type annotations are needed error: it looks like you're trying to convert an array to a tuple --> $DIR/tuple_array_conversions.rs:13:13 @@ -21,7 +21,7 @@ error: it looks like you're trying to convert an array to a tuple LL | let x = (x[0], x[1]); | ^^^^^^^^^^^^ | - = help: use `.into()` instead + = help: use `.into()` instead, or `<(T0, T1, ..., Tn)>::from` if type annotations are needed error: it looks like you're trying to convert a tuple to an array --> $DIR/tuple_array_conversions.rs:16:53 @@ -29,7 +29,7 @@ error: it looks like you're trying to convert a tuple to an array LL | let v1: Vec<[u32; 2]> = t1.iter().map(|&(a, b)| [a, b]).collect(); | ^^^^^^ | - = help: use `.into()` instead + = help: use `.into()` instead, or `<[T; N]>::from` if type annotations are needed error: it looks like you're trying to convert a tuple to an array --> $DIR/tuple_array_conversions.rs:17:38 @@ -37,7 +37,7 @@ error: it looks like you're trying to convert a tuple to an array LL | t1.iter().for_each(|&(a, b)| _ = [a, b]); | ^^^^^^ | - = help: use `.into()` instead + = help: use `.into()` instead, or `<[T; N]>::from` if type annotations are needed error: it looks like you're trying to convert an array to a tuple --> $DIR/tuple_array_conversions.rs:18:55 @@ -45,7 +45,7 @@ error: it looks like you're trying to convert an array to a tuple LL | let t2: Vec<(u32, u32)> = v1.iter().map(|&[a, b]| (a, b)).collect(); | ^^^^^^ | - = help: use `.into()` instead + = help: use `.into()` instead, or `<(T0, T1, ..., Tn)>::from` if type annotations are needed error: it looks like you're trying to convert a tuple to an array --> $DIR/tuple_array_conversions.rs:19:38 @@ -53,7 +53,47 @@ error: it looks like you're trying to convert a tuple to an array LL | t1.iter().for_each(|&(a, b)| _ = [a, b]); | ^^^^^^ | - = help: use `.into()` instead + = help: use `.into()` instead, or `<[T; N]>::from` if type annotations are needed -error: aborting due to 7 previous errors +error: it looks like you're trying to convert a tuple to an array + --> $DIR/tuple_array_conversions.rs:43:13 + | +LL | let x = [x.0, x.0]; + | ^^^^^^^^^^ + | + = help: use `.into()` instead, or `<[T; N]>::from` if type annotations are needed + +error: it looks like you're trying to convert an array to a tuple + --> $DIR/tuple_array_conversions.rs:44:13 + | +LL | let x = (x[0], x[0]); + | ^^^^^^^^^^^^ + | + = help: use `.into()` instead, or `<(T0, T1, ..., Tn)>::from` if type annotations are needed + +error: it looks like you're trying to convert an array to a tuple + --> $DIR/tuple_array_conversions.rs:71:13 + | +LL | let x = (x[0], x[1]); + | ^^^^^^^^^^^^ + | + = help: use `.into()` instead, or `<(T0, T1, ..., Tn)>::from` if type annotations are needed + +error: it looks like you're trying to convert a tuple to an array + --> $DIR/tuple_array_conversions.rs:72:13 + | +LL | let x = [x.0, x.1]; + | ^^^^^^^^^^ + | + = help: use `.into()` instead, or `<[T; N]>::from` if type annotations are needed + +error: it looks like you're trying to convert an array to a tuple + --> $DIR/tuple_array_conversions.rs:74:13 + | +LL | let x = (x[0], x[1]); + | ^^^^^^^^^^^^ + | + = help: use `.into()` instead, or `<(T0, T1, ..., Tn)>::from` if type annotations are needed + +error: aborting due to 12 previous errors From 95b24d44a68e3f84c10e392cb19e2db921cbedf8 Mon Sep 17 00:00:00 2001 From: Catherine <114838443+Centri3@users.noreply.github.com> Date: Sat, 24 Jun 2023 09:40:58 -0500 Subject: [PATCH 297/310] Fix FP --- clippy_lints/src/tuple_array_conversions.rs | 15 +++++++++++---- tests/ui/tuple_array_conversions.rs | 2 -- tests/ui/tuple_array_conversions.stderr | 18 +----------------- 3 files changed, 12 insertions(+), 23 deletions(-) diff --git a/clippy_lints/src/tuple_array_conversions.rs b/clippy_lints/src/tuple_array_conversions.rs index 9d5e872bd78..6564666d186 100644 --- a/clippy_lints/src/tuple_array_conversions.rs +++ b/clippy_lints/src/tuple_array_conversions.rs @@ -5,6 +5,7 @@ use clippy_utils::{ path_to_local, }; use itertools::Itertools; +use rustc_ast::LitKind; use rustc_hir::{Expr, ExprKind, Node, Pat}; use rustc_lint::{LateContext, LateLintPass, LintContext}; use rustc_middle::{lint::in_external_macro, ty}; @@ -82,8 +83,9 @@ fn check_array<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>) -> bool { if let Some(elements) = elements .iter() - .map(|expr| { - if let ExprKind::Field(path, _) = expr.kind { + .enumerate() + .map(|(i, expr)| { + if let ExprKind::Field(path, field) = expr.kind && field.as_str() == i.to_string() { return Some(path); }; @@ -146,8 +148,13 @@ fn check_tuple<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>) -> bool { if let Some(elements) = elements .iter() - .map(|expr| { - if let ExprKind::Index(path, _) = expr.kind { + .enumerate() + .map(|(i, expr)| { + if let ExprKind::Index(path, index) = expr.kind + && let ExprKind::Lit(lit) = index.kind + && let LitKind::Int(val, _) = lit.node + && val as usize == i + { return Some(path); }; diff --git a/tests/ui/tuple_array_conversions.rs b/tests/ui/tuple_array_conversions.rs index 64aaa53be5c..f96a7c97f1a 100644 --- a/tests/ui/tuple_array_conversions.rs +++ b/tests/ui/tuple_array_conversions.rs @@ -39,10 +39,8 @@ fn main() { let y = (1, 2); [x.0, y.0]; [x.0, y.1]; - // FP let x = [x.0, x.0]; let x = (x[0], x[0]); - // How can this be fixed? external! { let t1: &[(u32, u32)] = &[(1, 2), (3, 4)]; let v1: Vec<[u32; 2]> = t1.iter().map(|&(a, b)| [a, b]).collect(); diff --git a/tests/ui/tuple_array_conversions.stderr b/tests/ui/tuple_array_conversions.stderr index d9d59a611a0..7352b089d6b 100644 --- a/tests/ui/tuple_array_conversions.stderr +++ b/tests/ui/tuple_array_conversions.stderr @@ -55,22 +55,6 @@ LL | t1.iter().for_each(|&(a, b)| _ = [a, b]); | = help: use `.into()` instead, or `<[T; N]>::from` if type annotations are needed -error: it looks like you're trying to convert a tuple to an array - --> $DIR/tuple_array_conversions.rs:43:13 - | -LL | let x = [x.0, x.0]; - | ^^^^^^^^^^ - | - = help: use `.into()` instead, or `<[T; N]>::from` if type annotations are needed - -error: it looks like you're trying to convert an array to a tuple - --> $DIR/tuple_array_conversions.rs:44:13 - | -LL | let x = (x[0], x[0]); - | ^^^^^^^^^^^^ - | - = help: use `.into()` instead, or `<(T0, T1, ..., Tn)>::from` if type annotations are needed - error: it looks like you're trying to convert an array to a tuple --> $DIR/tuple_array_conversions.rs:71:13 | @@ -95,5 +79,5 @@ LL | let x = (x[0], x[1]); | = help: use `.into()` instead, or `<(T0, T1, ..., Tn)>::from` if type annotations are needed -error: aborting due to 12 previous errors +error: aborting due to 10 previous errors From 826edd75ef9bfa1053a39461602611985680f8e7 Mon Sep 17 00:00:00 2001 From: Catherine <114838443+Centri3@users.noreply.github.com> Date: Sat, 24 Jun 2023 10:08:26 -0500 Subject: [PATCH 298/310] heavily refactor --- book/src/lint_configuration.md | 1 + clippy_lints/src/tuple_array_conversions.rs | 196 ++++++++++---------- tests/ui/tuple_array_conversions.stderr | 6 +- 3 files changed, 97 insertions(+), 106 deletions(-) diff --git a/book/src/lint_configuration.md b/book/src/lint_configuration.md index 8bb3a57ba9a..ae0b5140316 100644 --- a/book/src/lint_configuration.md +++ b/book/src/lint_configuration.md @@ -149,6 +149,7 @@ The minimum rust version that the project supports * [`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) * [`type_repetition_in_bounds`](https://rust-lang.github.io/rust-clippy/master/index.html#type_repetition_in_bounds) +* [`tuple_array_conversions`](https://rust-lang.github.io/rust-clippy/master/index.html#tuple_array_conversions) ## `cognitive-complexity-threshold` diff --git a/clippy_lints/src/tuple_array_conversions.rs b/clippy_lints/src/tuple_array_conversions.rs index 6564666d186..bd983306508 100644 --- a/clippy_lints/src/tuple_array_conversions.rs +++ b/clippy_lints/src/tuple_array_conversions.rs @@ -4,9 +4,8 @@ use clippy_utils::{ msrvs::{self, Msrv}, path_to_local, }; -use itertools::Itertools; use rustc_ast::LitKind; -use rustc_hir::{Expr, ExprKind, Node, Pat}; +use rustc_hir::{Expr, ExprKind, HirId, Node, Pat}; use rustc_lint::{LateContext, LateLintPass, LintContext}; use rustc_middle::{lint::in_external_macro, ty}; use rustc_session::{declare_tool_lint, impl_lint_pass}; @@ -17,8 +16,8 @@ declare_clippy_lint! { /// Checks for tuple<=>array conversions that are not done with `.into()`. /// /// ### Why is this bad? - /// It's overly complex. `.into()` works for tuples<=>arrays with less than 13 elements and - /// conveys the intent a lot better, while also leaving less room for bugs! + /// It's unnecessary complexity. `.into()` works for tuples<=>arrays at or below 12 elements and + /// conveys the intent a lot better, while also leaving less room for hard to spot bugs! /// /// ### Example /// ```rust,ignore @@ -45,26 +44,28 @@ pub struct TupleArrayConversions { impl LateLintPass<'_> for TupleArrayConversions { fn check_expr<'tcx>(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>) { if !in_external_macro(cx.sess(), expr.span) && self.msrv.meets(msrvs::TUPLE_ARRAY_CONVERSIONS) { - _ = check_array(cx, expr) || check_tuple(cx, expr); + match expr.kind { + ExprKind::Array(elements) if (1..=12).contains(&elements.len()) => check_array(cx, expr, elements), + ExprKind::Tup(elements) if (1..=12).contains(&elements.len()) => check_tuple(cx, expr, elements), + _ => {}, + } } } extract_msrv_attr!(LateContext); } -fn check_array<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>) -> bool { - let ExprKind::Array(elements) = expr.kind else { - return false; - }; - if !(1..=12).contains(&elements.len()) { - return false; - } - - if let Some(locals) = path_to_locals(cx, &elements.iter().collect_vec()) - && let [first, rest @ ..] = &*locals - && let Node::Pat(first_pat) = first - && let first_id = parent_pat(cx, first_pat).hir_id - && rest.iter().chain(once(first)).all(|local| { +#[expect( + clippy::blocks_in_if_conditions, + reason = "not a FP, but this is much easier to understand" +)] +fn check_array<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>, elements: &'tcx [Expr<'tcx>]) { + if should_lint( + cx, + elements, + // This is cursed. + Some, + |(first_id, local)| { if let Node::Pat(pat) = local && let parent = parent_pat(cx, pat) && parent.hir_id == first_id @@ -76,27 +77,18 @@ fn check_array<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>) -> bool { } false - }) - { - return emit_lint(cx, expr, ToType::Array); - } + }, + ) || should_lint( + cx, + elements, + |(i, expr)| { + if let ExprKind::Field(path, field) = expr.kind && field.as_str() == i.to_string() { + return Some((i, path)); + }; - if let Some(elements) = elements - .iter() - .enumerate() - .map(|(i, expr)| { - if let ExprKind::Field(path, field) = expr.kind && field.as_str() == i.to_string() { - return Some(path); - }; - - None - }) - .collect::>>>() - && let Some(locals) = path_to_locals(cx, &elements) - && let [first, rest @ ..] = &*locals - && let Node::Pat(first_pat) = first - && let first_id = parent_pat(cx, first_pat).hir_id - && rest.iter().chain(once(first)).all(|local| { + None + }, + |(first_id, local)| { if let Node::Pat(pat) = local && let parent = parent_pat(cx, pat) && parent.hir_id == first_id @@ -108,28 +100,45 @@ fn check_array<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>) -> bool { } false - }) - { - return emit_lint(cx, expr, ToType::Array); + }, + ) { + emit_lint(cx, expr, ToType::Array); } - - false } +#[expect( + clippy::blocks_in_if_conditions, + reason = "not a FP, but this is much easier to understand" +)] #[expect(clippy::cast_possible_truncation)] -fn check_tuple<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>) -> bool { - let ExprKind::Tup(elements) = expr.kind else { - return false; - }; - if !(1..=12).contains(&elements.len()) { - return false; - }; +fn check_tuple<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>, elements: &'tcx [Expr<'tcx>]) { + if should_lint(cx, elements, Some, |(first_id, local)| { + if let Node::Pat(pat) = local + && let parent = parent_pat(cx, pat) + && parent.hir_id == first_id + { + return matches!( + cx.typeck_results().pat_ty(parent).peel_refs().kind(), + ty::Array(_, len) if len.eval_target_usize(cx.tcx, cx.param_env) as usize == elements.len() + ); + } - if let Some(locals) = path_to_locals(cx, &elements.iter().collect_vec()) - && let [first, rest @ ..] = &*locals - && let Node::Pat(first_pat) = first - && let first_id = parent_pat(cx, first_pat).hir_id - && rest.iter().chain(once(first)).all(|local| { + false + }) || should_lint( + cx, + elements, + |(i, expr)| { + if let ExprKind::Index(path, index) = expr.kind + && let ExprKind::Lit(lit) = index.kind + && let LitKind::Int(val, _) = lit.node + && val as usize == i + { + return Some((i, path)); + }; + + None + }, + |(first_id, local)| { if let Node::Pat(pat) = local && let parent = parent_pat(cx, pat) && parent.hir_id == first_id @@ -141,48 +150,10 @@ fn check_tuple<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>) -> bool { } false - }) - { - return emit_lint(cx, expr, ToType::Tuple); + }, + ) { + emit_lint(cx, expr, ToType::Tuple); } - - if let Some(elements) = elements - .iter() - .enumerate() - .map(|(i, expr)| { - if let ExprKind::Index(path, index) = expr.kind - && let ExprKind::Lit(lit) = index.kind - && let LitKind::Int(val, _) = lit.node - && val as usize == i - { - return Some(path); - }; - - None - }) - .collect::>>>() - && let Some(locals) = path_to_locals(cx, &elements) - && let [first, rest @ ..] = &*locals - && let Node::Pat(first_pat) = first - && let first_id = parent_pat(cx, first_pat).hir_id - && rest.iter().chain(once(first)).all(|local| { - if let Node::Pat(pat) = local - && let parent = parent_pat(cx, pat) - && parent.hir_id == first_id - { - return matches!( - cx.typeck_results().pat_ty(parent).peel_refs().kind(), - ty::Array(_, len) if len.eval_target_usize(cx.tcx, cx.param_env) as usize == elements.len() - ); - } - - false - }) - { - return emit_lint(cx, expr, ToType::Tuple); - } - - false } /// Walks up the `Pat` until it's reached the final containing `Pat`. @@ -198,13 +169,6 @@ fn parent_pat<'tcx>(cx: &LateContext<'tcx>, start: &'tcx Pat<'tcx>) -> &'tcx Pat end } -fn path_to_locals<'tcx>(cx: &LateContext<'tcx>, exprs: &[&'tcx Expr<'tcx>]) -> Option>> { - exprs - .iter() - .map(|element| path_to_local(element).and_then(|local| cx.tcx.hir().find(local))) - .collect() -} - #[derive(Clone, Copy)] enum ToType { Array, @@ -243,3 +207,29 @@ fn emit_lint<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>, to_type: ToTy false } + +fn should_lint<'tcx>( + cx: &LateContext<'tcx>, + elements: &'tcx [Expr<'tcx>], + map: impl FnMut((usize, &'tcx Expr<'tcx>)) -> Option<(usize, &Expr<'_>)>, + predicate: impl FnMut((HirId, &Node<'tcx>)) -> bool, +) -> bool { + if let Some(elements) = elements + .iter() + .enumerate() + .map(map) + .collect::>>() + && let Some(locals) = elements + .iter() + .map(|(_, element)| path_to_local(element).and_then(|local| cx.tcx.hir().find(local))) + .collect::>>() + && let [first, rest @ ..] = &*locals + && let Node::Pat(first_pat) = first + && let parent = parent_pat(cx, first_pat).hir_id + && rest.iter().chain(once(first)).map(|i| (parent, i)).all(predicate) + { + return true; + } + + false +} diff --git a/tests/ui/tuple_array_conversions.stderr b/tests/ui/tuple_array_conversions.stderr index 7352b089d6b..be653e8efb7 100644 --- a/tests/ui/tuple_array_conversions.stderr +++ b/tests/ui/tuple_array_conversions.stderr @@ -56,7 +56,7 @@ LL | t1.iter().for_each(|&(a, b)| _ = [a, b]); = help: use `.into()` instead, or `<[T; N]>::from` if type annotations are needed error: it looks like you're trying to convert an array to a tuple - --> $DIR/tuple_array_conversions.rs:71:13 + --> $DIR/tuple_array_conversions.rs:69:13 | LL | let x = (x[0], x[1]); | ^^^^^^^^^^^^ @@ -64,7 +64,7 @@ LL | let x = (x[0], x[1]); = help: use `.into()` instead, or `<(T0, T1, ..., Tn)>::from` if type annotations are needed error: it looks like you're trying to convert a tuple to an array - --> $DIR/tuple_array_conversions.rs:72:13 + --> $DIR/tuple_array_conversions.rs:70:13 | LL | let x = [x.0, x.1]; | ^^^^^^^^^^ @@ -72,7 +72,7 @@ LL | let x = [x.0, x.1]; = help: use `.into()` instead, or `<[T; N]>::from` if type annotations are needed error: it looks like you're trying to convert an array to a tuple - --> $DIR/tuple_array_conversions.rs:74:13 + --> $DIR/tuple_array_conversions.rs:72:13 | LL | let x = (x[0], x[1]); | ^^^^^^^^^^^^ From f0619024b876c7a57c83455aa153b3a82fb467b6 Mon Sep 17 00:00:00 2001 From: Caio Date: Sat, 13 May 2023 21:45:03 -0300 Subject: [PATCH 299/310] Fix #10413 --- .../src/significant_drop_tightening.rs | 587 +++++++++--------- tests/ui/significant_drop_tightening.fixed | 12 + tests/ui/significant_drop_tightening.rs | 12 + tests/ui/significant_drop_tightening.stderr | 6 +- 4 files changed, 336 insertions(+), 281 deletions(-) diff --git a/clippy_lints/src/significant_drop_tightening.rs b/clippy_lints/src/significant_drop_tightening.rs index f4e56489b09..140dc66badb 100644 --- a/clippy_lints/src/significant_drop_tightening.rs +++ b/clippy_lints/src/significant_drop_tightening.rs @@ -1,10 +1,10 @@ use clippy_utils::{ diagnostics::span_lint_and_then, - get_attr, + expr_or_init, get_attr, path_to_local, source::{indent_of, snippet}, }; -use rustc_data_structures::fx::{FxHashMap, FxHashSet}; -use rustc_errors::{Applicability, Diagnostic}; +use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexMap}; +use rustc_errors::Applicability; use rustc_hir::{ self as hir, intravisit::{walk_expr, Visitor}, @@ -13,6 +13,7 @@ use rustc_lint::{LateContext, LateLintPass, LintContext}; use rustc_middle::ty::{subst::GenericArgKind, Ty, TypeAndMut}; use rustc_session::{declare_tool_lint, impl_lint_pass}; use rustc_span::{symbol::Ident, Span, DUMMY_SP}; +use std::borrow::Cow; declare_clippy_lint! { /// ### What it does @@ -56,255 +57,102 @@ impl_lint_pass!(SignificantDropTightening<'_> => [SIGNIFICANT_DROP_TIGHTENING]); #[derive(Default)] pub struct SignificantDropTightening<'tcx> { + apas: FxIndexMap, /// Auxiliary structure used to avoid having to verify the same type multiple times. seen_types: FxHashSet>, type_cache: FxHashMap, bool>, } -impl<'tcx> SignificantDropTightening<'tcx> { - /// Unifies the statements of a block with its return expression. - fn all_block_stmts<'ret, 'rslt, 'stmts>( - block_stmts: &'stmts [hir::Stmt<'tcx>], - dummy_ret_stmt: Option<&'ret hir::Stmt<'tcx>>, - ) -> impl Iterator> - where - 'ret: 'rslt, - 'stmts: 'rslt, - { - block_stmts.iter().chain(dummy_ret_stmt) - } - - /// Searches for at least one statement that could slow down the release of a significant drop. - fn at_least_one_stmt_is_expensive<'stmt>(stmts: impl Iterator>) -> bool - where - 'tcx: 'stmt, - { - for stmt in stmts { - match stmt.kind { - hir::StmtKind::Expr(expr) if let hir::ExprKind::Path(_) = expr.kind => {} - hir::StmtKind::Local(local) if let Some(expr) = local.init - && let hir::ExprKind::Path(_) = expr.kind => {}, - _ => return true - }; - } - false - } - - /// Verifies if the expression is of type `drop(some_lock_path)` to assert that the temporary - /// is already being dropped before the end of its scope. - fn has_drop(expr: &'tcx hir::Expr<'_>, init_bind_ident: Ident) -> bool { - if let hir::ExprKind::Call(fun, args) = expr.kind - && let hir::ExprKind::Path(hir::QPath::Resolved(_, fun_path)) = &fun.kind - && let [fun_ident, ..] = fun_path.segments - && fun_ident.ident.name == rustc_span::sym::drop - && let [first_arg, ..] = args - && let hir::ExprKind::Path(hir::QPath::Resolved(_, arg_path)) = &first_arg.kind - && let [first_arg_ps, .. ] = arg_path.segments - { - first_arg_ps.ident == init_bind_ident - } - else { - false - } - } - - /// Tries to find types marked with `#[has_significant_drop]` of an expression `expr` that is - /// originated from `stmt` and then performs common logic on `sdap`. - fn modify_sdap_if_sig_drop_exists( +impl<'tcx> LateLintPass<'tcx> for SignificantDropTightening<'tcx> { + fn check_fn( &mut self, cx: &LateContext<'tcx>, - expr: &'tcx hir::Expr<'_>, - idx: usize, - sdap: &mut SigDropAuxParams, - stmt: &hir::Stmt<'_>, - cb: impl Fn(&mut SigDropAuxParams), + _: hir::intravisit::FnKind<'_>, + _: &hir::FnDecl<'_>, + body: &'tcx hir::Body<'_>, + _: Span, + _: hir::def_id::LocalDefId, ) { - let mut sig_drop_finder = SigDropFinder::new(cx, &mut self.seen_types, &mut self.type_cache); - sig_drop_finder.visit_expr(expr); - if sig_drop_finder.has_sig_drop { - cb(sdap); - if sdap.number_of_stmts > 0 { - sdap.last_use_stmt_idx = idx; - sdap.last_use_stmt_span = stmt.span; - if let hir::ExprKind::MethodCall(_, _, _, span) = expr.kind { - sdap.last_use_method_span = span; - } + self.apas.clear(); + let initial_dummy_stmt = dummy_stmt_expr(&body.value); + let mut ap = AuxParams::new(&mut self.apas, &initial_dummy_stmt); + StmtsChecker::new(&mut ap, cx, &mut self.seen_types, &mut self.type_cache).visit_body(body); + for apa in ap.apas.values() { + if apa.counter <= 1 || !apa.has_expensive_expr_after_last_attr { + continue; } - sdap.number_of_stmts = sdap.number_of_stmts.wrapping_add(1); - } - } - - /// Shows generic overall messages as well as specialized messages depending on the usage. - fn set_suggestions(cx: &LateContext<'tcx>, block_span: Span, diag: &mut Diagnostic, sdap: &SigDropAuxParams) { - match sdap.number_of_stmts { - 0 | 1 => {}, - 2 => { - let indent = " ".repeat(indent_of(cx, sdap.last_use_stmt_span).unwrap_or(0)); - let init_method = snippet(cx, sdap.init_method_span, ".."); - let usage_method = snippet(cx, sdap.last_use_method_span, ".."); - let stmt = if let Some(last_use_bind_span) = sdap.last_use_bind_span { - format!( - "\n{indent}let {} = {init_method}.{usage_method};", - snippet(cx, last_use_bind_span, ".."), - ) - } else { - format!("\n{indent}{init_method}.{usage_method};") - }; - diag.span_suggestion_verbose( - sdap.init_stmt_span, - "merge the temporary construction with its single usage", - stmt, - Applicability::MaybeIncorrect, - ); - diag.span_suggestion( - sdap.last_use_stmt_span, - "remove separated single usage", - "", - Applicability::MaybeIncorrect, - ); - }, - _ => { - diag.span_suggestion( - sdap.last_use_stmt_span.shrink_to_hi(), - "drop the temporary after the end of its last usage", - format!( - "\n{}drop({});", - " ".repeat(indent_of(cx, sdap.last_use_stmt_span).unwrap_or(0)), - sdap.init_bind_ident - ), - Applicability::MaybeIncorrect, - ); - }, - } - diag.note("this might lead to unnecessary resource contention"); - diag.span_label( - block_span, - format!( - "temporary `{}` is currently being dropped at the end of its contained scope", - sdap.init_bind_ident - ), - ); - } -} - -impl<'tcx> LateLintPass<'tcx> for SignificantDropTightening<'tcx> { - fn check_block(&mut self, cx: &LateContext<'tcx>, block: &'tcx hir::Block<'_>) { - let dummy_ret_stmt = block.expr.map(|expr| hir::Stmt { - hir_id: hir::HirId::INVALID, - kind: hir::StmtKind::Expr(expr), - span: DUMMY_SP, - }); - let mut sdap = SigDropAuxParams::default(); - for (idx, stmt) in Self::all_block_stmts(block.stmts, dummy_ret_stmt.as_ref()).enumerate() { - match stmt.kind { - hir::StmtKind::Expr(expr) => self.modify_sdap_if_sig_drop_exists( - cx, - expr, - idx, - &mut sdap, - stmt, - |_| {} - ), - hir::StmtKind::Local(local) if let Some(expr) = local.init => self.modify_sdap_if_sig_drop_exists( - cx, - expr, - idx, - &mut sdap, - stmt, - |local_sdap| { - if local_sdap.number_of_stmts == 0 { - if let hir::PatKind::Binding(_, _, ident, _) = local.pat.kind { - local_sdap.init_bind_ident = ident; - } - if let hir::ExprKind::MethodCall(_, local_expr, _, span) = expr.kind { - local_sdap.init_method_span = local_expr.span.to(span); - } - local_sdap.init_stmt_span = stmt.span; - } - else if let hir::PatKind::Binding(_, _, ident, _) = local.pat.kind { - local_sdap.last_use_bind_span = Some(ident.span); - } - } - ), - hir::StmtKind::Semi(expr) => { - if Self::has_drop(expr, sdap.init_bind_ident) { - return; - } - self.modify_sdap_if_sig_drop_exists(cx, expr, idx, &mut sdap, stmt, |_| {}); - }, - _ => {} - }; - } - - let idx = sdap.last_use_stmt_idx.wrapping_add(1); - let stmts_after_last_use = Self::all_block_stmts(block.stmts, dummy_ret_stmt.as_ref()).skip(idx); - if sdap.number_of_stmts > 1 && Self::at_least_one_stmt_is_expensive(stmts_after_last_use) { span_lint_and_then( cx, SIGNIFICANT_DROP_TIGHTENING, - sdap.init_bind_ident.span, + apa.first_bind_ident.span, "temporary with significant `Drop` can be early dropped", |diag| { - Self::set_suggestions(cx, block.span, diag, &sdap); + match apa.counter { + 0 | 1 => {}, + 2 => { + let indent = " ".repeat(indent_of(cx, apa.last_stmt_span).unwrap_or(0)); + let init_method = snippet(cx, apa.first_method_span, ".."); + let usage_method = snippet(cx, apa.last_method_span, ".."); + let stmt = if apa.last_bind_ident != Ident::empty() { + format!( + "\n{indent}let {} = {init_method}.{usage_method};", + snippet(cx, apa.last_bind_ident.span, ".."), + ) + } else { + format!("\n{indent}{init_method}.{usage_method};") + }; + diag.span_suggestion_verbose( + apa.first_stmt_span, + "merge the temporary construction with its single usage", + stmt, + Applicability::MaybeIncorrect, + ); + diag.span_suggestion( + apa.last_stmt_span, + "remove separated single usage", + "", + Applicability::MaybeIncorrect, + ); + }, + _ => { + diag.span_suggestion( + apa.last_stmt_span.shrink_to_hi(), + "drop the temporary after the end of its last usage", + format!( + "\n{}drop({});", + " ".repeat(indent_of(cx, apa.last_stmt_span).unwrap_or(0)), + apa.first_bind_ident + ), + Applicability::MaybeIncorrect, + ); + }, + } + diag.note("this might lead to unnecessary resource contention"); + diag.span_label( + apa.first_block_span, + format!( + "temporary `{}` is currently being dropped at the end of its contained scope", + apa.first_bind_ident + ), + ); }, ); } } } -/// Auxiliary parameters used on each block check. -struct SigDropAuxParams { - /// The binding or variable that references the initial construction of the type marked with - /// `#[has_significant_drop]`. - init_bind_ident: Ident, - /// Similar to `init_bind_ident` but encompasses the right-hand method call. - init_method_span: Span, - /// Similar to `init_bind_ident` but encompasses the whole contained statement. - init_stmt_span: Span, - - /// The last visited binding or variable span within a block that had any referenced inner type - /// marked with `#[has_significant_drop]`. - last_use_bind_span: Option, - /// Index of the last visited statement within a block that had any referenced inner type - /// marked with `#[has_significant_drop]`. - last_use_stmt_idx: usize, - /// Similar to `last_use_bind_span` but encompasses the whole contained statement. - last_use_stmt_span: Span, - /// Similar to `last_use_bind_span` but encompasses the right-hand method call. - last_use_method_span: Span, - - /// Total number of statements within a block that have any referenced inner type marked with - /// `#[has_significant_drop]`. - number_of_stmts: usize, -} - -impl Default for SigDropAuxParams { - fn default() -> Self { - Self { - init_bind_ident: Ident::empty(), - init_method_span: DUMMY_SP, - init_stmt_span: DUMMY_SP, - last_use_bind_span: None, - last_use_method_span: DUMMY_SP, - last_use_stmt_idx: 0, - last_use_stmt_span: DUMMY_SP, - number_of_stmts: 0, - } - } -} - -/// Checks the existence of the `#[has_significant_drop]` attribute -struct SigDropChecker<'cx, 'sdt, 'tcx> { +/// Checks the existence of the `#[has_significant_drop]` attribute. +struct AttrChecker<'cx, 'others, 'tcx> { cx: &'cx LateContext<'tcx>, - seen_types: &'sdt mut FxHashSet>, - type_cache: &'sdt mut FxHashMap, bool>, + seen_types: &'others mut FxHashSet>, + type_cache: &'others mut FxHashMap, bool>, } -impl<'cx, 'sdt, 'tcx> SigDropChecker<'cx, 'sdt, 'tcx> { +impl<'cx, 'others, 'tcx> AttrChecker<'cx, 'others, 'tcx> { pub(crate) fn new( cx: &'cx LateContext<'tcx>, - seen_types: &'sdt mut FxHashSet>, - type_cache: &'sdt mut FxHashMap, bool>, + seen_types: &'others mut FxHashSet>, + type_cache: &'others mut FxHashMap, bool>, ) -> Self { seen_types.clear(); Self { @@ -314,7 +162,17 @@ impl<'cx, 'sdt, 'tcx> SigDropChecker<'cx, 'sdt, 'tcx> { } } - pub(crate) fn has_sig_drop_attr_uncached(&mut self, ty: Ty<'tcx>) -> bool { + fn has_sig_drop_attr(&mut self, ty: Ty<'tcx>) -> bool { + // The borrow checker prevents us from using something fancier like or_insert_with. + if let Some(ty) = self.type_cache.get(&ty) { + return *ty; + } + let value = self.has_sig_drop_attr_uncached(ty); + self.type_cache.insert(ty, value); + value + } + + fn has_sig_drop_attr_uncached(&mut self, ty: Ty<'tcx>) -> bool { if let Some(adt) = ty.ty_adt_def() { let mut iter = get_attr( self.cx.sess(), @@ -350,73 +208,246 @@ impl<'cx, 'sdt, 'tcx> SigDropChecker<'cx, 'sdt, 'tcx> { } } - pub(crate) fn has_sig_drop_attr(&mut self, ty: Ty<'tcx>) -> bool { - // The borrow checker prevents us from using something fancier like or_insert_with. - if let Some(ty) = self.type_cache.get(&ty) { - return *ty; - } - let value = self.has_sig_drop_attr_uncached(ty); - self.type_cache.insert(ty, value); - value - } - fn has_seen_ty(&mut self, ty: Ty<'tcx>) -> bool { !self.seen_types.insert(ty) } } -/// Performs recursive calls to find any inner type marked with `#[has_significant_drop]`. -struct SigDropFinder<'cx, 'sdt, 'tcx> { - cx: &'cx LateContext<'tcx>, - has_sig_drop: bool, - sig_drop_checker: SigDropChecker<'cx, 'sdt, 'tcx>, +struct StmtsChecker<'ap, 'lc, 'others, 'stmt, 'tcx> { + ap: &'ap mut AuxParams<'others, 'stmt, 'tcx>, + cx: &'lc LateContext<'tcx>, + seen_types: &'others mut FxHashSet>, + type_cache: &'others mut FxHashMap, bool>, } -impl<'cx, 'sdt, 'tcx> SigDropFinder<'cx, 'sdt, 'tcx> { +impl<'ap, 'lc, 'others, 'stmt, 'tcx> StmtsChecker<'ap, 'lc, 'others, 'stmt, 'tcx> { fn new( - cx: &'cx LateContext<'tcx>, - seen_types: &'sdt mut FxHashSet>, - type_cache: &'sdt mut FxHashMap, bool>, + ap: &'ap mut AuxParams<'others, 'stmt, 'tcx>, + cx: &'lc LateContext<'tcx>, + seen_types: &'others mut FxHashSet>, + type_cache: &'others mut FxHashMap, bool>, ) -> Self { Self { + ap, cx, - has_sig_drop: false, - sig_drop_checker: SigDropChecker::new(cx, seen_types, type_cache), + seen_types, + type_cache, + } + } + + fn manage_has_expensive_expr_after_last_attr(&mut self) { + let has_expensive_stmt = match self.ap.curr_stmt.kind { + hir::StmtKind::Expr(expr) if !is_expensive_expr(expr) => false, + hir::StmtKind::Local(local) if let Some(expr) = local.init + && let hir::ExprKind::Path(_) = expr.kind => false, + _ => true + }; + if has_expensive_stmt { + for apa in self.ap.apas.values_mut() { + let last_stmt_is_not_dummy = apa.last_stmt_span != DUMMY_SP; + let last_stmt_is_not_curr = self.ap.curr_stmt.span != apa.last_stmt_span; + let block_equals_curr = self.ap.curr_block_hir_id == apa.first_block_hir_id; + let block_is_ancestor = self + .cx + .tcx + .hir() + .parent_iter(self.ap.curr_block_hir_id) + .any(|(id, _)| id == apa.first_block_hir_id); + if last_stmt_is_not_dummy && last_stmt_is_not_curr && (block_equals_curr || block_is_ancestor) { + apa.has_expensive_expr_after_last_attr = true; + } + } } } } -impl<'cx, 'sdt, 'tcx> Visitor<'tcx> for SigDropFinder<'cx, 'sdt, 'tcx> { - fn visit_expr(&mut self, ex: &'tcx hir::Expr<'_>) { - if self - .sig_drop_checker - .has_sig_drop_attr(self.cx.typeck_results().expr_ty(ex)) - { - self.has_sig_drop = true; - return; +impl<'ap, 'lc, 'others, 'stmt, 'tcx> Visitor<'tcx> for StmtsChecker<'ap, 'lc, 'others, 'stmt, 'tcx> { + fn visit_block(&mut self, block: &'tcx hir::Block<'tcx>) { + self.ap.curr_block_hir_id = block.hir_id; + self.ap.curr_block_span = block.span; + for stmt in block.stmts.iter() { + self.ap.curr_stmt = Cow::Borrowed(stmt); + self.visit_stmt(stmt); + self.ap.curr_block_hir_id = block.hir_id; + self.ap.curr_block_span = block.span; + self.manage_has_expensive_expr_after_last_attr(); } + if let Some(expr) = block.expr { + self.ap.curr_stmt = Cow::Owned(dummy_stmt_expr(expr)); + self.visit_expr(expr); + self.ap.curr_block_hir_id = block.hir_id; + self.ap.curr_block_span = block.span; + self.manage_has_expensive_expr_after_last_attr(); + } + } - match ex.kind { - hir::ExprKind::MethodCall(_, expr, ..) => { - self.visit_expr(expr); - }, - hir::ExprKind::Array(..) - | hir::ExprKind::Assign(..) - | hir::ExprKind::AssignOp(..) - | hir::ExprKind::Binary(..) - | hir::ExprKind::Call(..) - | hir::ExprKind::Field(..) - | hir::ExprKind::If(..) - | hir::ExprKind::Index(..) - | hir::ExprKind::Match(..) - | hir::ExprKind::Repeat(..) - | hir::ExprKind::Ret(..) - | hir::ExprKind::Tup(..) - | hir::ExprKind::Unary(..) - | hir::ExprKind::Yield(..) => { - walk_expr(self, ex); - }, - _ => {}, + fn visit_expr(&mut self, expr: &'tcx hir::Expr<'tcx>) { + let modify_apa_params = |apa: &mut AuxParamsAttr| { + apa.counter = apa.counter.wrapping_add(1); + apa.has_expensive_expr_after_last_attr = false; + }; + let mut ac = AttrChecker::new(self.cx, self.seen_types, self.type_cache); + if ac.has_sig_drop_attr(self.cx.typeck_results().expr_ty(expr)) { + if let hir::StmtKind::Local(local) = self.ap.curr_stmt.kind + && let hir::PatKind::Binding(_, hir_id, ident, _) = local.pat.kind + && !self.ap.apas.contains_key(&hir_id) + && { + if let Some(local_hir_id) = path_to_local(expr) { + local_hir_id == hir_id + } + else { + true + } + } + { + let mut apa = AuxParamsAttr::default(); + apa.first_bind_ident = ident; + apa.first_block_hir_id = self.ap.curr_block_hir_id; + apa.first_block_span = self.ap.curr_block_span; + apa.first_method_span = { + let expr_or_init = expr_or_init(self.cx, expr); + if let hir::ExprKind::MethodCall(_, local_expr, _, span) = expr_or_init.kind { + local_expr.span.to(span) + } + else { + expr_or_init.span + } + }; + apa.first_stmt_span = self.ap.curr_stmt.span; + modify_apa_params(&mut apa); + let _ = self.ap.apas.insert(hir_id, apa); + } else { + let Some(hir_id) = path_to_local(expr) else { return; }; + let Some(apa) = self.ap.apas.get_mut(&hir_id) else { return; }; + match self.ap.curr_stmt.kind { + hir::StmtKind::Local(local) => { + if let hir::PatKind::Binding(_, _, ident, _) = local.pat.kind { + apa.last_bind_ident = ident; + } + if let Some(local_init) = local.init + && let hir::ExprKind::MethodCall(_, _, _, span) = local_init.kind + { + apa.last_method_span = span; + } + }, + hir::StmtKind::Semi(expr) => { + if has_drop(expr, &apa.first_bind_ident) { + apa.has_expensive_expr_after_last_attr = false; + apa.last_stmt_span = DUMMY_SP; + return; + } + if let hir::ExprKind::MethodCall(_, _, _, span) = expr.kind { + apa.last_method_span = span; + } + }, + _ => {}, + } + apa.last_stmt_span = self.ap.curr_stmt.span; + modify_apa_params(apa); + } + } + walk_expr(self, expr); + } +} + +/// Auxiliary parameters used on each block check of an item +struct AuxParams<'others, 'stmt, 'tcx> { + //// See [AuxParamsAttr]. + apas: &'others mut FxIndexMap, + /// The current block identifier that is being visited. + curr_block_hir_id: hir::HirId, + /// The current block span that is being visited. + curr_block_span: Span, + /// The current statement that is being visited. + curr_stmt: Cow<'stmt, hir::Stmt<'tcx>>, +} + +impl<'others, 'stmt, 'tcx> AuxParams<'others, 'stmt, 'tcx> { + fn new(apas: &'others mut FxIndexMap, curr_stmt: &'stmt hir::Stmt<'tcx>) -> Self { + Self { + apas, + curr_block_hir_id: hir::HirId::INVALID, + curr_block_span: DUMMY_SP, + curr_stmt: Cow::Borrowed(curr_stmt), } } } + +/// Auxiliary parameters used on expression created with `#[has_significant_drop]`. +#[derive(Debug)] +struct AuxParamsAttr { + /// The number of times `#[has_significant_drop]` was referenced. + counter: usize, + /// If an expensive expression follows the last use of anything marked with + /// `#[has_significant_drop]`. + has_expensive_expr_after_last_attr: bool, + + /// The identifier of the block that involves the first `#[has_significant_drop]`. + first_block_hir_id: hir::HirId, + /// The span of the block that involves the first `#[has_significant_drop]`. + first_block_span: Span, + /// The binding or variable that references the initial construction of the type marked with + /// `#[has_significant_drop]`. + first_bind_ident: Ident, + /// Similar to `init_bind_ident` but encompasses the right-hand method call. + first_method_span: Span, + /// Similar to `init_bind_ident` but encompasses the whole contained statement. + first_stmt_span: Span, + + /// The last visited binding or variable span within a block that had any referenced inner type + /// marked with `#[has_significant_drop]`. + last_bind_ident: Ident, + /// Similar to `last_bind_span` but encompasses the right-hand method call. + last_method_span: Span, + /// Similar to `last_bind_span` but encompasses the whole contained statement. + last_stmt_span: Span, +} + +impl Default for AuxParamsAttr { + fn default() -> Self { + Self { + counter: 0, + has_expensive_expr_after_last_attr: false, + first_block_hir_id: hir::HirId::INVALID, + first_bind_ident: Ident::empty(), + first_block_span: DUMMY_SP, + first_method_span: DUMMY_SP, + first_stmt_span: DUMMY_SP, + last_bind_ident: Ident::empty(), + last_method_span: DUMMY_SP, + last_stmt_span: DUMMY_SP, + } + } +} + +fn dummy_stmt_expr<'any>(expr: &'any hir::Expr<'any>) -> hir::Stmt<'any> { + hir::Stmt { + hir_id: hir::HirId::INVALID, + kind: hir::StmtKind::Expr(expr), + span: DUMMY_SP, + } +} + +fn has_drop(expr: &hir::Expr<'_>, first_bind_ident: &Ident) -> bool { + if let hir::ExprKind::Call(fun, args) = expr.kind + && let hir::ExprKind::Path(hir::QPath::Resolved(_, fun_path)) = &fun.kind + && let [fun_ident, ..] = fun_path.segments + && fun_ident.ident.name == rustc_span::sym::drop + && let [first_arg, ..] = args + && let hir::ExprKind::Path(hir::QPath::Resolved(_, arg_path)) = &first_arg.kind + && let [first_arg_ps, .. ] = arg_path.segments + { + &first_arg_ps.ident == first_bind_ident + } + else { + false + } +} + +fn is_expensive_expr(expr: &hir::Expr<'_>) -> bool { + if let hir::ExprKind::Path(_) = expr.kind { + false + } else { + true + } +} diff --git a/tests/ui/significant_drop_tightening.fixed b/tests/ui/significant_drop_tightening.fixed index ee7f2b0631a..7b848ead784 100644 --- a/tests/ui/significant_drop_tightening.fixed +++ b/tests/ui/significant_drop_tightening.fixed @@ -16,6 +16,18 @@ pub fn complex_return_triggers_the_lint() -> i32 { foo() } +pub fn issue_10413() { + let mutex = Mutex::new(Some(1)); + let opt = Some(1); + if opt.is_some() { + let lock = mutex.lock().unwrap(); + let _ = *lock; + if opt.is_some() { + let _ = *lock; + } + } +} + pub fn path_return_can_be_ignored() -> i32 { let mutex = Mutex::new(1); let lock = mutex.lock().unwrap(); diff --git a/tests/ui/significant_drop_tightening.rs b/tests/ui/significant_drop_tightening.rs index 9c139deb95f..36f77cf1bdb 100644 --- a/tests/ui/significant_drop_tightening.rs +++ b/tests/ui/significant_drop_tightening.rs @@ -15,6 +15,18 @@ pub fn complex_return_triggers_the_lint() -> i32 { foo() } +pub fn issue_10413() { + let mutex = Mutex::new(Some(1)); + let opt = Some(1); + if opt.is_some() { + let lock = mutex.lock().unwrap(); + let _ = *lock; + if opt.is_some() { + let _ = *lock; + } + } +} + pub fn path_return_can_be_ignored() -> i32 { let mutex = Mutex::new(1); let lock = mutex.lock().unwrap(); diff --git a/tests/ui/significant_drop_tightening.stderr b/tests/ui/significant_drop_tightening.stderr index ab8ce356ec7..3bdac0b0a6b 100644 --- a/tests/ui/significant_drop_tightening.stderr +++ b/tests/ui/significant_drop_tightening.stderr @@ -23,7 +23,7 @@ LL + drop(lock); | error: temporary with significant `Drop` can be early dropped - --> $DIR/significant_drop_tightening.rs:44:13 + --> $DIR/significant_drop_tightening.rs:56:13 | LL | / { LL | | let mutex = Mutex::new(1i32); @@ -43,7 +43,7 @@ LL + drop(lock); | error: temporary with significant `Drop` can be early dropped - --> $DIR/significant_drop_tightening.rs:65:13 + --> $DIR/significant_drop_tightening.rs:77:13 | LL | / { LL | | let mutex = Mutex::new(1i32); @@ -67,7 +67,7 @@ LL + | error: temporary with significant `Drop` can be early dropped - --> $DIR/significant_drop_tightening.rs:71:17 + --> $DIR/significant_drop_tightening.rs:83:17 | LL | / { LL | | let mutex = Mutex::new(vec![1i32]); From fc832f0eb74bb4c4023e359cc90dab941dc2654d Mon Sep 17 00:00:00 2001 From: Caio Date: Thu, 29 Jun 2023 09:30:04 -0300 Subject: [PATCH 300/310] Dogfood --- .../src/significant_drop_tightening.rs | 44 +++++++++---------- 1 file changed, 21 insertions(+), 23 deletions(-) diff --git a/clippy_lints/src/significant_drop_tightening.rs b/clippy_lints/src/significant_drop_tightening.rs index 140dc66badb..fffa8a380c2 100644 --- a/clippy_lints/src/significant_drop_tightening.rs +++ b/clippy_lints/src/significant_drop_tightening.rs @@ -74,7 +74,7 @@ impl<'tcx> LateLintPass<'tcx> for SignificantDropTightening<'tcx> { _: hir::def_id::LocalDefId, ) { self.apas.clear(); - let initial_dummy_stmt = dummy_stmt_expr(&body.value); + let initial_dummy_stmt = dummy_stmt_expr(body.value); let mut ap = AuxParams::new(&mut self.apas, &initial_dummy_stmt); StmtsChecker::new(&mut ap, cx, &mut self.seen_types, &mut self.type_cache).visit_body(body); for apa in ap.apas.values() { @@ -93,13 +93,13 @@ impl<'tcx> LateLintPass<'tcx> for SignificantDropTightening<'tcx> { let indent = " ".repeat(indent_of(cx, apa.last_stmt_span).unwrap_or(0)); let init_method = snippet(cx, apa.first_method_span, ".."); let usage_method = snippet(cx, apa.last_method_span, ".."); - let stmt = if apa.last_bind_ident != Ident::empty() { + let stmt = if apa.last_bind_ident == Ident::empty() { + format!("\n{indent}{init_method}.{usage_method};") + } else { format!( "\n{indent}let {} = {init_method}.{usage_method};", snippet(cx, apa.last_bind_ident.span, ".."), ) - } else { - format!("\n{indent}{init_method}.{usage_method};") }; diag.span_suggestion_verbose( apa.first_stmt_span, @@ -265,7 +265,7 @@ impl<'ap, 'lc, 'others, 'stmt, 'tcx> Visitor<'tcx> for StmtsChecker<'ap, 'lc, 'o fn visit_block(&mut self, block: &'tcx hir::Block<'tcx>) { self.ap.curr_block_hir_id = block.hir_id; self.ap.curr_block_span = block.span; - for stmt in block.stmts.iter() { + for stmt in block.stmts { self.ap.curr_stmt = Cow::Borrowed(stmt); self.visit_stmt(stmt); self.ap.curr_block_hir_id = block.hir_id; @@ -300,20 +300,22 @@ impl<'ap, 'lc, 'others, 'stmt, 'tcx> Visitor<'tcx> for StmtsChecker<'ap, 'lc, 'o } } { - let mut apa = AuxParamsAttr::default(); - apa.first_bind_ident = ident; - apa.first_block_hir_id = self.ap.curr_block_hir_id; - apa.first_block_span = self.ap.curr_block_span; - apa.first_method_span = { - let expr_or_init = expr_or_init(self.cx, expr); - if let hir::ExprKind::MethodCall(_, local_expr, _, span) = expr_or_init.kind { - local_expr.span.to(span) - } - else { - expr_or_init.span - } + let mut apa = AuxParamsAttr { + first_bind_ident: ident, + first_block_hir_id: self.ap.curr_block_hir_id, + first_block_span: self.ap.curr_block_span, + first_method_span: { + let expr_or_init = expr_or_init(self.cx, expr); + if let hir::ExprKind::MethodCall(_, local_expr, _, span) = expr_or_init.kind { + local_expr.span.to(span) + } + else { + expr_or_init.span + } + }, + first_stmt_span: self.ap.curr_stmt.span, + ..Default::default() }; - apa.first_stmt_span = self.ap.curr_stmt.span; modify_apa_params(&mut apa); let _ = self.ap.apas.insert(hir_id, apa); } else { @@ -445,9 +447,5 @@ fn has_drop(expr: &hir::Expr<'_>, first_bind_ident: &Ident) -> bool { } fn is_expensive_expr(expr: &hir::Expr<'_>) -> bool { - if let hir::ExprKind::Path(_) = expr.kind { - false - } else { - true - } + !matches!(expr.kind, hir::ExprKind::Path(_)) } From 30d08d35f2fdbaa197d597395d69b603155fcccf Mon Sep 17 00:00:00 2001 From: Philipp Krones Date: Fri, 30 Jun 2023 16:09:15 +0200 Subject: [PATCH 301/310] Bump nightly version -> 2023-06-29 --- rust-toolchain | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rust-toolchain b/rust-toolchain index 0d2e1eee643..4475d914ced 100644 --- a/rust-toolchain +++ b/rust-toolchain @@ -1,3 +1,3 @@ [toolchain] -channel = "nightly-2023-06-02" +channel = "nightly-2023-06-29" components = ["cargo", "llvm-tools", "rust-src", "rust-std", "rustc", "rustc-dev", "rustfmt"] From efac83813dda709a835764bcaeb66697becedfe6 Mon Sep 17 00:00:00 2001 From: Catherine <114838443+Centri3@users.noreply.github.com> Date: Fri, 30 Jun 2023 11:39:33 -0500 Subject: [PATCH 302/310] Make `eq_op` suggest `.is_nan()` --- clippy_lints/src/operators/eq_op.rs | 9 +++-- tests/ui/eq_op.rs | 2 ++ tests/ui/eq_op.stderr | 56 ++++++++++++++++------------- 3 files changed, 41 insertions(+), 26 deletions(-) diff --git a/clippy_lints/src/operators/eq_op.rs b/clippy_lints/src/operators/eq_op.rs index 67913f7392c..78965b7d6f7 100644 --- a/clippy_lints/src/operators/eq_op.rs +++ b/clippy_lints/src/operators/eq_op.rs @@ -1,4 +1,4 @@ -use clippy_utils::diagnostics::span_lint; +use clippy_utils::diagnostics::{span_lint, span_lint_and_then}; use clippy_utils::macros::{find_assert_eq_args, first_node_macro_backtrace}; use clippy_utils::{ast_utils::is_useless_with_eq_exprs, eq_expr_value, is_in_test_function}; use rustc_hir::{BinOpKind, Expr}; @@ -35,11 +35,16 @@ pub(crate) fn check<'tcx>( right: &'tcx Expr<'_>, ) { if is_useless_with_eq_exprs(op.into()) && eq_expr_value(cx, left, right) && !is_in_test_function(cx.tcx, e.hir_id) { - span_lint( + span_lint_and_then( cx, EQ_OP, e.span, &format!("equal expressions as operands to `{}`", op.as_str()), + |diag| { + if let BinOpKind::Ne = op && cx.typeck_results().expr_ty(left).is_floating_point() { + diag.note("if you intended to check if the operand is NaN, use `.is_nan()` instead"); + } + }, ); } } diff --git a/tests/ui/eq_op.rs b/tests/ui/eq_op.rs index 38372378168..e973e5ba2fb 100644 --- a/tests/ui/eq_op.rs +++ b/tests/ui/eq_op.rs @@ -10,6 +10,8 @@ fn main() { let _ = false != false; let _ = 1.5 < 1.5; let _ = 1u64 >= 1u64; + let x = f32::NAN; + let _ = x != x; // casts, methods, parentheses let _ = (1u32 as u64) & (1u32 as u64); diff --git a/tests/ui/eq_op.stderr b/tests/ui/eq_op.stderr index 2c013b6b6fe..c7fa253bdca 100644 --- a/tests/ui/eq_op.stderr +++ b/tests/ui/eq_op.stderr @@ -30,143 +30,151 @@ error: equal expressions as operands to `>=` LL | let _ = 1u64 >= 1u64; | ^^^^^^^^^^^^ +error: equal expressions as operands to `!=` + --> $DIR/eq_op.rs:14:13 + | +LL | let _ = x != x; + | ^^^^^^ + | + = note: if you intended to check if the operand is NaN, use `.is_nan()` instead + error: equal expressions as operands to `&` - --> $DIR/eq_op.rs:15:13 + --> $DIR/eq_op.rs:17:13 | LL | let _ = (1u32 as u64) & (1u32 as u64); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: equal expressions as operands to `^` - --> $DIR/eq_op.rs:18:17 + --> $DIR/eq_op.rs:20:17 | LL | let _ = 1 ^ ((((((1)))))); | ^^^^^^^^^^^^^^^^^ error: equal expressions as operands to `<` - --> $DIR/eq_op.rs:22:13 + --> $DIR/eq_op.rs:24:13 | LL | let _ = (-(2) < -(2)); | ^^^^^^^^^^^^^ error: equal expressions as operands to `==` - --> $DIR/eq_op.rs:23:13 + --> $DIR/eq_op.rs:25:13 | LL | let _ = ((1 + 1) & (1 + 1) == (1 + 1) & (1 + 1)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: equal expressions as operands to `&` - --> $DIR/eq_op.rs:23:14 + --> $DIR/eq_op.rs:25:14 | LL | let _ = ((1 + 1) & (1 + 1) == (1 + 1) & (1 + 1)); | ^^^^^^^^^^^^^^^^^ error: equal expressions as operands to `&` - --> $DIR/eq_op.rs:23:35 + --> $DIR/eq_op.rs:25:35 | LL | let _ = ((1 + 1) & (1 + 1) == (1 + 1) & (1 + 1)); | ^^^^^^^^^^^^^^^^^ error: equal expressions as operands to `==` - --> $DIR/eq_op.rs:24:13 + --> $DIR/eq_op.rs:26:13 | LL | let _ = (1 * 2) + (3 * 4) == 1 * 2 + 3 * 4; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: equal expressions as operands to `!=` - --> $DIR/eq_op.rs:27:13 + --> $DIR/eq_op.rs:29:13 | LL | let _ = ([1] != [1]); | ^^^^^^^^^^^^ error: equal expressions as operands to `!=` - --> $DIR/eq_op.rs:28:13 + --> $DIR/eq_op.rs:30:13 | LL | let _ = ((1, 2) != (1, 2)); | ^^^^^^^^^^^^^^^^^^ error: equal expressions as operands to `==` - --> $DIR/eq_op.rs:32:13 + --> $DIR/eq_op.rs:34:13 | LL | let _ = 1 + 1 == 2; | ^^^^^^^^^^ error: equal expressions as operands to `==` - --> $DIR/eq_op.rs:33:13 + --> $DIR/eq_op.rs:35:13 | LL | let _ = 1 - 1 == 0; | ^^^^^^^^^^ error: equal expressions as operands to `-` - --> $DIR/eq_op.rs:33:13 + --> $DIR/eq_op.rs:35:13 | LL | let _ = 1 - 1 == 0; | ^^^^^ error: equal expressions as operands to `-` - --> $DIR/eq_op.rs:35:13 + --> $DIR/eq_op.rs:37:13 | LL | let _ = 1 - 1; | ^^^^^ error: equal expressions as operands to `/` - --> $DIR/eq_op.rs:36:13 + --> $DIR/eq_op.rs:38:13 | LL | let _ = 1 / 1; | ^^^^^ error: equal expressions as operands to `&&` - --> $DIR/eq_op.rs:37:13 + --> $DIR/eq_op.rs:39:13 | LL | let _ = true && true; | ^^^^^^^^^^^^ error: equal expressions as operands to `||` - --> $DIR/eq_op.rs:39:13 + --> $DIR/eq_op.rs:41:13 | LL | let _ = true || true; | ^^^^^^^^^^^^ error: equal expressions as operands to `&&` - --> $DIR/eq_op.rs:44:13 + --> $DIR/eq_op.rs:46:13 | LL | let _ = a == b && b == a; | ^^^^^^^^^^^^^^^^ error: equal expressions as operands to `&&` - --> $DIR/eq_op.rs:45:13 + --> $DIR/eq_op.rs:47:13 | LL | let _ = a != b && b != a; | ^^^^^^^^^^^^^^^^ error: equal expressions as operands to `&&` - --> $DIR/eq_op.rs:46:13 + --> $DIR/eq_op.rs:48:13 | LL | let _ = a < b && b > a; | ^^^^^^^^^^^^^^ error: equal expressions as operands to `&&` - --> $DIR/eq_op.rs:47:13 + --> $DIR/eq_op.rs:49:13 | LL | let _ = a <= b && b >= a; | ^^^^^^^^^^^^^^^^ error: equal expressions as operands to `==` - --> $DIR/eq_op.rs:50:13 + --> $DIR/eq_op.rs:52:13 | LL | let _ = a == a; | ^^^^^^ error: equal expressions as operands to `/` - --> $DIR/eq_op.rs:60:20 + --> $DIR/eq_op.rs:62:20 | LL | const D: u32 = A / A; | ^^^^^ error: equal expressions as operands to `==` - --> $DIR/eq_op.rs:91:5 + --> $DIR/eq_op.rs:93:5 | LL | (n1.inner.0).0 == (n1.inner.0).0 && (n1.inner.1).0 == (n2.inner.1).0 && (n1.inner.2).0 == (n2.inner.2).0 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: aborting due to 28 previous errors +error: aborting due to 29 previous errors From 354172a18efcf104db76fd7dba884b329e9bac7d Mon Sep 17 00:00:00 2001 From: Catherine <114838443+Centri3@users.noreply.github.com> Date: Fri, 23 Jun 2023 05:43:53 -0500 Subject: [PATCH 303/310] New lint `manual_try_fold` --- CHANGELOG.md | 1 + clippy_lints/src/declared_lints.rs | 1 + clippy_lints/src/methods/manual_try_fold.rs | 55 ++++++++++++++ clippy_lints/src/methods/mod.rs | 33 +++++++- clippy_utils/src/msrvs.rs | 1 + tests/ui/manual_try_fold.rs | 84 +++++++++++++++++++++ tests/ui/manual_try_fold.stderr | 22 ++++++ 7 files changed, 195 insertions(+), 2 deletions(-) create mode 100644 clippy_lints/src/methods/manual_try_fold.rs create mode 100644 tests/ui/manual_try_fold.rs create mode 100644 tests/ui/manual_try_fold.stderr diff --git a/CHANGELOG.md b/CHANGELOG.md index ff39c6a0a6c..14d822083d8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4959,6 +4959,7 @@ Released 2018-09-13 [`manual_string_new`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_string_new [`manual_strip`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_strip [`manual_swap`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_swap +[`manual_try_fold`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_try_fold [`manual_unwrap_or`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_unwrap_or [`manual_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 diff --git a/clippy_lints/src/declared_lints.rs b/clippy_lints/src/declared_lints.rs index 52bc2010207..9d9ee6ba307 100644 --- a/clippy_lints/src/declared_lints.rs +++ b/clippy_lints/src/declared_lints.rs @@ -364,6 +364,7 @@ pub(crate) static LINTS: &[&crate::LintInfo] = &[ crate::methods::MANUAL_SATURATING_ARITHMETIC_INFO, crate::methods::MANUAL_SPLIT_ONCE_INFO, crate::methods::MANUAL_STR_REPEAT_INFO, + crate::methods::MANUAL_TRY_FOLD_INFO, crate::methods::MAP_CLONE_INFO, crate::methods::MAP_COLLECT_RESULT_UNIT_INFO, crate::methods::MAP_ERR_IGNORE_INFO, diff --git a/clippy_lints/src/methods/manual_try_fold.rs b/clippy_lints/src/methods/manual_try_fold.rs new file mode 100644 index 00000000000..9f92524d356 --- /dev/null +++ b/clippy_lints/src/methods/manual_try_fold.rs @@ -0,0 +1,55 @@ +use clippy_utils::{ + diagnostics::span_lint_and_sugg, + is_from_proc_macro, + msrvs::{Msrv, ITERATOR_TRY_FOLD}, + source::snippet_opt, + ty::implements_trait, +}; +use rustc_errors::Applicability; +use rustc_hir::{ + def::{DefKind, Res}, + Expr, ExprKind, +}; +use rustc_lint::{LateContext, LintContext}; +use rustc_middle::lint::in_external_macro; +use rustc_span::Span; + +use super::MANUAL_TRY_FOLD; + +pub(super) fn check<'tcx>( + cx: &LateContext<'tcx>, + expr: &Expr<'tcx>, + init: &Expr<'_>, + acc: &Expr<'_>, + fold_span: Span, + msrv: &Msrv, +) { + if !in_external_macro(cx.sess(), fold_span) + && msrv.meets(ITERATOR_TRY_FOLD) + && let init_ty = cx.typeck_results().expr_ty(init) + && let Some(try_trait) = cx.tcx.lang_items().try_trait() + && implements_trait(cx, init_ty, try_trait, &[]) + && let ExprKind::Call(path, [first, rest @ ..]) = init.kind + && let ExprKind::Path(qpath) = path.kind + && let Res::Def(DefKind::Ctor(_, _), _) = cx.qpath_res(&qpath, path.hir_id) + && let ExprKind::Closure(closure) = acc.kind + && let Some(args_snip) = closure.fn_arg_span.and_then(|fn_arg_span| snippet_opt(cx, fn_arg_span)) + && !is_from_proc_macro(cx, expr) + { + let init_snip = rest + .is_empty() + .then_some(first.span) + .and_then(|span| snippet_opt(cx, span)) + .unwrap_or("...".to_owned()); + + span_lint_and_sugg( + cx, + MANUAL_TRY_FOLD, + fold_span, + "you seem to be using `Iterator::fold` on a type that implements `Try`", + "use `try_fold` instead", + format!("try_fold({init_snip}, {args_snip}, ...)", ), + Applicability::HasPlaceholders, + ); + } +} diff --git a/clippy_lints/src/methods/mod.rs b/clippy_lints/src/methods/mod.rs index b1d3b61aea3..a8d03bb95e6 100644 --- a/clippy_lints/src/methods/mod.rs +++ b/clippy_lints/src/methods/mod.rs @@ -50,6 +50,7 @@ mod manual_next_back; mod manual_ok_or; mod manual_saturating_arithmetic; mod manual_str_repeat; +mod manual_try_fold; mod map_clone; mod map_collect_result_unit; mod map_err_ignore; @@ -3286,6 +3287,30 @@ declare_clippy_lint! { "calling `.drain(..).collect()` to move all elements into a new collection" } +declare_clippy_lint! { + /// ### What it does + /// Checks for usage of `Iterator::fold` with a type that implements `Try`. + /// + /// ### Why is this bad? + /// This is better represented with `try_fold`, but this has one major difference: It will + /// short-circuit on failure. *This is almost always what you want*. This can also open the door + /// for additional optimizations as well, as rustc can guarantee the function is never + /// called on `None`, `Err`, etc., alleviating otherwise necessary checks. + /// + /// ### Example + /// ```rust + /// vec![1, 2, 3].iter().fold(Some(0i32), |sum, i| sum?.checked_add(*i)); + /// ``` + /// Use instead: + /// ```rust + /// vec![1, 2, 3].iter().try_fold(0i32, |sum, i| sum.checked_add(*i)); + /// ``` + #[clippy::version = "1.72.0"] + pub MANUAL_TRY_FOLD, + perf, + "checks for usage of `Iterator::fold` with a type that implements `Try`" +} + pub struct Methods { avoid_breaking_exported_api: bool, msrv: Msrv, @@ -3416,7 +3441,8 @@ impl_lint_pass!(Methods => [ CLEAR_WITH_DRAIN, MANUAL_NEXT_BACK, UNNECESSARY_LITERAL_UNWRAP, - DRAIN_COLLECT + DRAIN_COLLECT, + MANUAL_TRY_FOLD, ]); /// Extracts a method call name, args, and `Span` of the method name. @@ -3709,7 +3735,10 @@ impl Methods { Some(("cloned", recv2, [], _, _)) => iter_overeager_cloned::check(cx, expr, recv, recv2, false, true), _ => {}, }, - ("fold", [init, acc]) => unnecessary_fold::check(cx, expr, init, acc, span), + ("fold", [init, acc]) => { + manual_try_fold::check(cx, expr, init, acc, call_span, &self.msrv); + unnecessary_fold::check(cx, expr, init, acc, span); + }, ("for_each", [_]) => { if let Some(("inspect", _, [_], span2, _)) = method_call(recv) { inspect_for_each::check(cx, expr, span2); diff --git a/clippy_utils/src/msrvs.rs b/clippy_utils/src/msrvs.rs index 1f70f11bd67..3637476c408 100644 --- a/clippy_utils/src/msrvs.rs +++ b/clippy_utils/src/msrvs.rs @@ -44,6 +44,7 @@ msrv_aliases! { 1,34,0 { TRY_FROM } 1,30,0 { ITERATOR_FIND_MAP, TOOL_ATTRIBUTES } 1,28,0 { FROM_BOOL } + 1,27,0 { ITERATOR_TRY_FOLD } 1,26,0 { RANGE_INCLUSIVE, STRING_RETAIN } 1,24,0 { IS_ASCII_DIGIT } 1,18,0 { HASH_MAP_RETAIN, HASH_SET_RETAIN } diff --git a/tests/ui/manual_try_fold.rs b/tests/ui/manual_try_fold.rs new file mode 100644 index 00000000000..f43519dd44f --- /dev/null +++ b/tests/ui/manual_try_fold.rs @@ -0,0 +1,84 @@ +//@aux-build:proc_macros.rs +#![allow(clippy::unnecessary_fold, unused)] +#![warn(clippy::manual_try_fold)] +#![feature(try_trait_v2)] + +use std::ops::ControlFlow; +use std::ops::FromResidual; +use std::ops::Try; + +#[macro_use] +extern crate proc_macros; + +// Test custom `Try` with more than 1 argument +struct NotOption(i32, i32); + +impl FromResidual for NotOption { + fn from_residual(_: R) -> Self { + todo!() + } +} + +impl Try for NotOption { + type Output = (); + type Residual = (); + + fn from_output(_: Self::Output) -> Self { + todo!() + } + + fn branch(self) -> ControlFlow { + todo!() + } +} + +// Test custom `Try` with only 1 argument +#[derive(Default)] +struct NotOptionButWorse(i32); + +impl FromResidual for NotOptionButWorse { + fn from_residual(_: R) -> Self { + todo!() + } +} + +impl Try for NotOptionButWorse { + type Output = (); + type Residual = (); + + fn from_output(_: Self::Output) -> Self { + todo!() + } + + fn branch(self) -> ControlFlow { + todo!() + } +} + +fn main() { + [1, 2, 3] + .iter() + .fold(Some(0i32), |sum, i| sum?.checked_add(*i)) + .unwrap(); + [1, 2, 3] + .iter() + .fold(NotOption(0i32, 0i32), |sum, i| NotOption(0i32, 0i32)); + [1, 2, 3] + .iter() + .fold(NotOptionButWorse(0i32), |sum, i| NotOptionButWorse(0i32)); + // Do not lint + [1, 2, 3].iter().try_fold(0i32, |sum, i| sum.checked_add(*i)).unwrap(); + [1, 2, 3].iter().fold(0i32, |sum, i| sum + i); + [1, 2, 3] + .iter() + .fold(NotOptionButWorse::default(), |sum, i| NotOptionButWorse::default()); + external! { + [1, 2, 3].iter().fold(Some(0i32), |sum, i| sum?.checked_add(*i)).unwrap(); + [1, 2, 3].iter().try_fold(0i32, |sum, i| sum.checked_add(*i)).unwrap(); + } + with_span! { + span + [1, 2, 3].iter().fold(Some(0i32), |sum, i| sum?.checked_add(*i)).unwrap(); + [1, 2, 3].iter().try_fold(0i32, |sum, i| sum.checked_add(*i)).unwrap(); + } +} diff --git a/tests/ui/manual_try_fold.stderr b/tests/ui/manual_try_fold.stderr new file mode 100644 index 00000000000..1a17435b459 --- /dev/null +++ b/tests/ui/manual_try_fold.stderr @@ -0,0 +1,22 @@ +error: you seem to be using `Iterator::fold` on a type that implements `Try` + --> $DIR/manual_try_fold.rs:61:10 + | +LL | .fold(Some(0i32), |sum, i| sum?.checked_add(*i)) + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `try_fold` instead: `try_fold(0i32, |sum, i|, ...)` + | + = note: `-D clippy::manual-try-fold` implied by `-D warnings` + +error: you seem to be using `Iterator::fold` on a type that implements `Try` + --> $DIR/manual_try_fold.rs:65:10 + | +LL | .fold(NotOption(0i32, 0i32), |sum, i| NotOption(0i32, 0i32)); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `try_fold` instead: `try_fold(..., |sum, i|, ...)` + +error: you seem to be using `Iterator::fold` on a type that implements `Try` + --> $DIR/manual_try_fold.rs:68:10 + | +LL | .fold(NotOptionButWorse(0i32), |sum, i| NotOptionButWorse(0i32)); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `try_fold` instead: `try_fold(0i32, |sum, i|, ...)` + +error: aborting due to 3 previous errors + From 24039ca2c66bf32b3b9112095f27c94694a012b9 Mon Sep 17 00:00:00 2001 From: Catherine <114838443+Centri3@users.noreply.github.com> Date: Fri, 23 Jun 2023 05:48:59 -0500 Subject: [PATCH 304/310] Add msrv tests --- tests/ui/manual_try_fold.rs | 16 ++++++++++++++++ tests/ui/manual_try_fold.stderr | 8 +++++++- 2 files changed, 23 insertions(+), 1 deletion(-) diff --git a/tests/ui/manual_try_fold.rs b/tests/ui/manual_try_fold.rs index f43519dd44f..e00371eb228 100644 --- a/tests/ui/manual_try_fold.rs +++ b/tests/ui/manual_try_fold.rs @@ -82,3 +82,19 @@ fn main() { [1, 2, 3].iter().try_fold(0i32, |sum, i| sum.checked_add(*i)).unwrap(); } } + +#[clippy::msrv = "1.26.0"] +fn msrv_too_low() { + [1, 2, 3] + .iter() + .fold(Some(0i32), |sum, i| sum?.checked_add(*i)) + .unwrap(); +} + +#[clippy::msrv = "1.27.0"] +fn msrv_juust_right() { + [1, 2, 3] + .iter() + .fold(Some(0i32), |sum, i| sum?.checked_add(*i)) + .unwrap(); +} diff --git a/tests/ui/manual_try_fold.stderr b/tests/ui/manual_try_fold.stderr index 1a17435b459..0c8a08e6c7d 100644 --- a/tests/ui/manual_try_fold.stderr +++ b/tests/ui/manual_try_fold.stderr @@ -18,5 +18,11 @@ error: you seem to be using `Iterator::fold` on a type that implements `Try` LL | .fold(NotOptionButWorse(0i32), |sum, i| NotOptionButWorse(0i32)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `try_fold` instead: `try_fold(0i32, |sum, i|, ...)` -error: aborting due to 3 previous errors +error: you seem to be using `Iterator::fold` on a type that implements `Try` + --> $DIR/manual_try_fold.rs:98:10 + | +LL | .fold(Some(0i32), |sum, i| sum?.checked_add(*i)) + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `try_fold` instead: `try_fold(0i32, |sum, i|, ...)` + +error: aborting due to 4 previous errors From 04b08576911cf06bc444fb0615f50c29ec82e675 Mon Sep 17 00:00:00 2001 From: Catherine <114838443+Centri3@users.noreply.github.com> Date: Sun, 25 Jun 2023 09:01:06 -0500 Subject: [PATCH 305/310] Typo --- clippy_lints/src/methods/manual_try_fold.rs | 4 ++-- tests/ui/manual_try_fold.stderr | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/clippy_lints/src/methods/manual_try_fold.rs b/clippy_lints/src/methods/manual_try_fold.rs index 9f92524d356..a1d83cf1419 100644 --- a/clippy_lints/src/methods/manual_try_fold.rs +++ b/clippy_lints/src/methods/manual_try_fold.rs @@ -33,8 +33,8 @@ pub(super) fn check<'tcx>( && let ExprKind::Path(qpath) = path.kind && let Res::Def(DefKind::Ctor(_, _), _) = cx.qpath_res(&qpath, path.hir_id) && let ExprKind::Closure(closure) = acc.kind - && let Some(args_snip) = closure.fn_arg_span.and_then(|fn_arg_span| snippet_opt(cx, fn_arg_span)) && !is_from_proc_macro(cx, expr) + && let Some(args_snip) = closure.fn_arg_span.and_then(|fn_arg_span| snippet_opt(cx, fn_arg_span)) { let init_snip = rest .is_empty() @@ -48,7 +48,7 @@ pub(super) fn check<'tcx>( fold_span, "you seem to be using `Iterator::fold` on a type that implements `Try`", "use `try_fold` instead", - format!("try_fold({init_snip}, {args_snip}, ...)", ), + format!("try_fold({init_snip}, {args_snip} ...)", ), Applicability::HasPlaceholders, ); } diff --git a/tests/ui/manual_try_fold.stderr b/tests/ui/manual_try_fold.stderr index 0c8a08e6c7d..2c0b0c67fd1 100644 --- a/tests/ui/manual_try_fold.stderr +++ b/tests/ui/manual_try_fold.stderr @@ -2,7 +2,7 @@ error: you seem to be using `Iterator::fold` on a type that implements `Try` --> $DIR/manual_try_fold.rs:61:10 | LL | .fold(Some(0i32), |sum, i| sum?.checked_add(*i)) - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `try_fold` instead: `try_fold(0i32, |sum, i|, ...)` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `try_fold` instead: `try_fold(0i32, |sum, i| ...)` | = note: `-D clippy::manual-try-fold` implied by `-D warnings` @@ -10,19 +10,19 @@ error: you seem to be using `Iterator::fold` on a type that implements `Try` --> $DIR/manual_try_fold.rs:65:10 | LL | .fold(NotOption(0i32, 0i32), |sum, i| NotOption(0i32, 0i32)); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `try_fold` instead: `try_fold(..., |sum, i|, ...)` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `try_fold` instead: `try_fold(..., |sum, i| ...)` error: you seem to be using `Iterator::fold` on a type that implements `Try` --> $DIR/manual_try_fold.rs:68:10 | LL | .fold(NotOptionButWorse(0i32), |sum, i| NotOptionButWorse(0i32)); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `try_fold` instead: `try_fold(0i32, |sum, i|, ...)` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `try_fold` instead: `try_fold(0i32, |sum, i| ...)` error: you seem to be using `Iterator::fold` on a type that implements `Try` --> $DIR/manual_try_fold.rs:98:10 | LL | .fold(Some(0i32), |sum, i| sum?.checked_add(*i)) - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `try_fold` instead: `try_fold(0i32, |sum, i|, ...)` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `try_fold` instead: `try_fold(0i32, |sum, i| ...)` error: aborting due to 4 previous errors From fbb3f759e2c6d90456f42a72eaaa741201d8e463 Mon Sep 17 00:00:00 2001 From: Catherine <114838443+Centri3@users.noreply.github.com> Date: Mon, 26 Jun 2023 14:32:01 -0500 Subject: [PATCH 306/310] update docs --- clippy_lints/src/methods/mod.rs | 13 +++++++++---- tests/ui/manual_try_fold.rs | 2 +- 2 files changed, 10 insertions(+), 5 deletions(-) diff --git a/clippy_lints/src/methods/mod.rs b/clippy_lints/src/methods/mod.rs index a8d03bb95e6..2cd7ca02755 100644 --- a/clippy_lints/src/methods/mod.rs +++ b/clippy_lints/src/methods/mod.rs @@ -3292,10 +3292,15 @@ declare_clippy_lint! { /// Checks for usage of `Iterator::fold` with a type that implements `Try`. /// /// ### Why is this bad? - /// This is better represented with `try_fold`, but this has one major difference: It will - /// short-circuit on failure. *This is almost always what you want*. This can also open the door - /// for additional optimizations as well, as rustc can guarantee the function is never - /// called on `None`, `Err`, etc., alleviating otherwise necessary checks. + /// This should use `try_fold` instead, which short-circuits on failure, thus opening the door + /// for additional optimizations not possible with `fold` as rustc can guarantee the function is + /// never called on `None`, `Err`, etc., alleviating otherwise necessary checks. It's also + /// slightly more idiomatic. + /// + /// ### Known issues + /// This lint doesn't take into account whether a function does something on the failure case, + /// i.e., whether short-circuiting will affect behavior. Refactoring to `try_fold` is not + /// desirable in those cases. /// /// ### Example /// ```rust diff --git a/tests/ui/manual_try_fold.rs b/tests/ui/manual_try_fold.rs index e00371eb228..4521e9fa1a5 100644 --- a/tests/ui/manual_try_fold.rs +++ b/tests/ui/manual_try_fold.rs @@ -1,4 +1,4 @@ -//@aux-build:proc_macros.rs +//@aux-build:proc_macros.rs:proc-macro #![allow(clippy::unnecessary_fold, unused)] #![warn(clippy::manual_try_fold)] #![feature(try_trait_v2)] From cb5d7e344a4f42eefb5b7d3df42f8899a684e73b Mon Sep 17 00:00:00 2001 From: Catherine <114838443+Centri3@users.noreply.github.com> Date: Thu, 29 Jun 2023 02:26:45 -0500 Subject: [PATCH 307/310] address comments --- book/src/lint_configuration.md | 1 + clippy_lints/src/methods/manual_try_fold.rs | 2 +- clippy_lints/src/methods/mod.rs | 8 ++++---- clippy_lints/src/utils/conf.rs | 2 +- tests/ui/manual_try_fold.stderr | 8 ++++---- 5 files changed, 11 insertions(+), 10 deletions(-) diff --git a/book/src/lint_configuration.md b/book/src/lint_configuration.md index ae0b5140316..60d7ce6e615 100644 --- a/book/src/lint_configuration.md +++ b/book/src/lint_configuration.md @@ -150,6 +150,7 @@ The minimum rust version that the project supports * [`manual_retain`](https://rust-lang.github.io/rust-clippy/master/index.html#manual_retain) * [`type_repetition_in_bounds`](https://rust-lang.github.io/rust-clippy/master/index.html#type_repetition_in_bounds) * [`tuple_array_conversions`](https://rust-lang.github.io/rust-clippy/master/index.html#tuple_array_conversions) +* [`manual_try_fold`](https://rust-lang.github.io/rust-clippy/master/index.html#manual_try_fold) ## `cognitive-complexity-threshold` diff --git a/clippy_lints/src/methods/manual_try_fold.rs b/clippy_lints/src/methods/manual_try_fold.rs index a1d83cf1419..576a58499b1 100644 --- a/clippy_lints/src/methods/manual_try_fold.rs +++ b/clippy_lints/src/methods/manual_try_fold.rs @@ -46,7 +46,7 @@ pub(super) fn check<'tcx>( cx, MANUAL_TRY_FOLD, fold_span, - "you seem to be using `Iterator::fold` on a type that implements `Try`", + "usage of `Iterator::fold` on a type that implements `Try`", "use `try_fold` instead", format!("try_fold({init_snip}, {args_snip} ...)", ), Applicability::HasPlaceholders, diff --git a/clippy_lints/src/methods/mod.rs b/clippy_lints/src/methods/mod.rs index 2cd7ca02755..24dbe8c1d75 100644 --- a/clippy_lints/src/methods/mod.rs +++ b/clippy_lints/src/methods/mod.rs @@ -3292,10 +3292,10 @@ declare_clippy_lint! { /// Checks for usage of `Iterator::fold` with a type that implements `Try`. /// /// ### Why is this bad? - /// This should use `try_fold` instead, which short-circuits on failure, thus opening the door - /// for additional optimizations not possible with `fold` as rustc can guarantee the function is - /// never called on `None`, `Err`, etc., alleviating otherwise necessary checks. It's also - /// slightly more idiomatic. + /// The code should use `try_fold` instead, which short-circuits on failure, thus opening the + /// door for additional optimizations not possible with `fold` as rustc can guarantee the + /// function is never called on `None`, `Err`, etc., alleviating otherwise necessary checks. It's + /// also slightly more idiomatic. /// /// ### Known issues /// This lint doesn't take into account whether a function does something on the failure case, diff --git a/clippy_lints/src/utils/conf.rs b/clippy_lints/src/utils/conf.rs index 89063964622..f1d05c7529b 100644 --- a/clippy_lints/src/utils/conf.rs +++ b/clippy_lints/src/utils/conf.rs @@ -294,7 +294,7 @@ define_Conf! { /// /// Suppress lints whenever the suggested change would cause breakage for other crates. (avoid_breaking_exported_api: bool = true), - /// Lint: MANUAL_SPLIT_ONCE, MANUAL_STR_REPEAT, CLONED_INSTEAD_OF_COPIED, REDUNDANT_FIELD_NAMES, OPTION_MAP_UNWRAP_OR, REDUNDANT_STATIC_LIFETIMES, FILTER_MAP_NEXT, CHECKED_CONVERSIONS, MANUAL_RANGE_CONTAINS, USE_SELF, MEM_REPLACE_WITH_DEFAULT, MANUAL_NON_EXHAUSTIVE, OPTION_AS_REF_DEREF, MAP_UNWRAP_OR, MATCH_LIKE_MATCHES_MACRO, MANUAL_STRIP, MISSING_CONST_FOR_FN, UNNESTED_OR_PATTERNS, FROM_OVER_INTO, PTR_AS_PTR, IF_THEN_SOME_ELSE_NONE, APPROX_CONSTANT, DEPRECATED_CFG_ATTR, INDEX_REFUTABLE_SLICE, MAP_CLONE, BORROW_AS_PTR, MANUAL_BITS, ERR_EXPECT, CAST_ABS_TO_UNSIGNED, UNINLINED_FORMAT_ARGS, MANUAL_CLAMP, MANUAL_LET_ELSE, UNCHECKED_DURATION_SUBTRACTION, COLLAPSIBLE_STR_REPLACE, SEEK_FROM_CURRENT, SEEK_REWIND, UNNECESSARY_LAZY_EVALUATIONS, TRANSMUTE_PTR_TO_REF, ALMOST_COMPLETE_RANGE, NEEDLESS_BORROW, DERIVABLE_IMPLS, MANUAL_IS_ASCII_CHECK, MANUAL_REM_EUCLID, MANUAL_RETAIN, TYPE_REPETITION_IN_BOUNDS, TUPLE_ARRAY_CONVERSIONS. + /// Lint: MANUAL_SPLIT_ONCE, MANUAL_STR_REPEAT, CLONED_INSTEAD_OF_COPIED, REDUNDANT_FIELD_NAMES, OPTION_MAP_UNWRAP_OR, REDUNDANT_STATIC_LIFETIMES, FILTER_MAP_NEXT, CHECKED_CONVERSIONS, MANUAL_RANGE_CONTAINS, USE_SELF, MEM_REPLACE_WITH_DEFAULT, MANUAL_NON_EXHAUSTIVE, OPTION_AS_REF_DEREF, MAP_UNWRAP_OR, MATCH_LIKE_MATCHES_MACRO, MANUAL_STRIP, MISSING_CONST_FOR_FN, UNNESTED_OR_PATTERNS, FROM_OVER_INTO, PTR_AS_PTR, IF_THEN_SOME_ELSE_NONE, APPROX_CONSTANT, DEPRECATED_CFG_ATTR, INDEX_REFUTABLE_SLICE, MAP_CLONE, BORROW_AS_PTR, MANUAL_BITS, ERR_EXPECT, CAST_ABS_TO_UNSIGNED, UNINLINED_FORMAT_ARGS, MANUAL_CLAMP, MANUAL_LET_ELSE, UNCHECKED_DURATION_SUBTRACTION, COLLAPSIBLE_STR_REPLACE, SEEK_FROM_CURRENT, SEEK_REWIND, UNNECESSARY_LAZY_EVALUATIONS, TRANSMUTE_PTR_TO_REF, ALMOST_COMPLETE_RANGE, NEEDLESS_BORROW, DERIVABLE_IMPLS, MANUAL_IS_ASCII_CHECK, MANUAL_REM_EUCLID, MANUAL_RETAIN, TYPE_REPETITION_IN_BOUNDS, TUPLE_ARRAY_CONVERSIONS, MANUAL_TRY_FOLD. /// /// The minimum rust version that the project supports (msrv: Option = None), diff --git a/tests/ui/manual_try_fold.stderr b/tests/ui/manual_try_fold.stderr index 2c0b0c67fd1..a0cf5b3b5fc 100644 --- a/tests/ui/manual_try_fold.stderr +++ b/tests/ui/manual_try_fold.stderr @@ -1,4 +1,4 @@ -error: you seem to be using `Iterator::fold` on a type that implements `Try` +error: usage of `Iterator::fold` on a type that implements `Try` --> $DIR/manual_try_fold.rs:61:10 | LL | .fold(Some(0i32), |sum, i| sum?.checked_add(*i)) @@ -6,19 +6,19 @@ LL | .fold(Some(0i32), |sum, i| sum?.checked_add(*i)) | = note: `-D clippy::manual-try-fold` implied by `-D warnings` -error: you seem to be using `Iterator::fold` on a type that implements `Try` +error: usage of `Iterator::fold` on a type that implements `Try` --> $DIR/manual_try_fold.rs:65:10 | LL | .fold(NotOption(0i32, 0i32), |sum, i| NotOption(0i32, 0i32)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `try_fold` instead: `try_fold(..., |sum, i| ...)` -error: you seem to be using `Iterator::fold` on a type that implements `Try` +error: usage of `Iterator::fold` on a type that implements `Try` --> $DIR/manual_try_fold.rs:68:10 | LL | .fold(NotOptionButWorse(0i32), |sum, i| NotOptionButWorse(0i32)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `try_fold` instead: `try_fold(0i32, |sum, i| ...)` -error: you seem to be using `Iterator::fold` on a type that implements `Try` +error: usage of `Iterator::fold` on a type that implements `Try` --> $DIR/manual_try_fold.rs:98:10 | LL | .fold(Some(0i32), |sum, i| sum?.checked_add(*i)) From 0cbe963e51faa7e3e771c1f9cea9aa443a648455 Mon Sep 17 00:00:00 2001 From: Philipp Krones Date: Sun, 2 Jul 2023 14:59:44 +0200 Subject: [PATCH 308/310] Fix valtree changes --- src/tools/clippy/clippy_utils/src/consts.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/tools/clippy/clippy_utils/src/consts.rs b/src/tools/clippy/clippy_utils/src/consts.rs index 068820801df..dd3cda8ec52 100644 --- a/src/tools/clippy/clippy_utils/src/consts.rs +++ b/src/tools/clippy/clippy_utils/src/consts.rs @@ -725,8 +725,8 @@ fn field_of_struct<'tcx>( result: mir::ConstantKind<'tcx>, field: &Ident, ) -> Option> { - let dc = lcx.tcx.destructure_mir_constant(lcx.param_env, result); - if let Some(dc_variant) = dc.variant + if let Some(dc) = lcx.tcx.try_destructure_mir_constant(lcx.param_env.and(result)) + && let Some(dc_variant) = dc.variant && let Some(variant) = adt_def.variants().get(dc_variant) && let Some(field_idx) = variant.fields.iter().position(|el| el.name == field.name) && let Some(dc_field) = dc.fields.get(field_idx) From de69d556eb5006a21f868b8c12d48f0ef1308a5a Mon Sep 17 00:00:00 2001 From: Philipp Krones Date: Sun, 2 Jul 2023 15:07:39 +0200 Subject: [PATCH 309/310] Fix compile-test tests to work with the new ui_test crate --- Cargo.toml | 1 + src/bootstrap/test.rs | 22 +++++----------------- src/tools/clippy/tests/compile-test.rs | 12 +++--------- 3 files changed, 9 insertions(+), 26 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 6e84df5c693..20b1c656d35 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -9,6 +9,7 @@ members = [ "src/tools/cargotest", "src/tools/clippy", "src/tools/clippy/clippy_dev", + "src/tools/clippy/clippy_test_deps", "src/tools/compiletest", "src/tools/error_index_generator", "src/tools/linkchecker", diff --git a/src/bootstrap/test.rs b/src/bootstrap/test.rs index a2938ab4caf..227275066cc 100644 --- a/src/bootstrap/test.rs +++ b/src/bootstrap/test.rs @@ -788,27 +788,15 @@ impl Step for Clippy { cargo.add_rustc_lib_path(builder, compiler); let mut cargo = prepare_cargo_test(cargo, &[], &[], "clippy", compiler, host, builder); + // propagate --bless + if builder.config.cmd.bless() { + cargo.env("BLESS", "Gesundheit"); + } + if builder.try_run(&mut cargo).is_ok() { // The tests succeeded; nothing to do. return; } - - if !builder.config.cmd.bless() { - crate::detail_exit_macro!(1); - } - - let mut cargo = builder.cargo(compiler, Mode::ToolRustc, SourceType::InTree, host, "run"); - cargo.arg("-p").arg("clippy_dev"); - // clippy_dev gets confused if it can't find `clippy/Cargo.toml` - cargo.current_dir(&builder.src.join("src").join("tools").join("clippy")); - if builder.config.rust_optimize.is_release() { - cargo.env("PROFILE", "release"); - } else { - cargo.env("PROFILE", "debug"); - } - cargo.arg("--"); - cargo.arg("bless"); - builder.run(&mut cargo.into()); } } diff --git a/src/tools/clippy/tests/compile-test.rs b/src/tools/clippy/tests/compile-test.rs index dce6f2fc272..0fd37c640ae 100644 --- a/src/tools/clippy/tests/compile-test.rs +++ b/src/tools/clippy/tests/compile-test.rs @@ -31,7 +31,7 @@ fn base_config(test_dir: &str) -> compiletest::Config { }, dependencies_crate_manifest_path: Some("clippy_test_deps/Cargo.toml".into()), target: None, - out_dir: "target/ui_test".into(), + out_dir: PathBuf::from(std::env::var_os("CARGO_TARGET_DIR").unwrap_or("target".into())).join("ui_test"), ..compiletest::Config::rustc(Path::new("tests").join(test_dir)) }; @@ -116,10 +116,7 @@ fn run_ui_toml() { config.stderr_filter( ®ex::escape( - &std::path::Path::new(file!()) - .parent() - .unwrap() - .canonicalize() + &fs::canonicalize("tests") .unwrap() .parent() .unwrap() @@ -175,10 +172,7 @@ fn run_ui_cargo() { config.stderr_filter( ®ex::escape( - &std::path::Path::new(file!()) - .parent() - .unwrap() - .canonicalize() + &fs::canonicalize("tests") .unwrap() .parent() .unwrap() From a6d3c82360b8debd134ffe6144ecce056cf8c041 Mon Sep 17 00:00:00 2001 From: Philipp Krones Date: Sun, 2 Jul 2023 15:07:47 +0200 Subject: [PATCH 310/310] Update Cargo.lock --- Cargo.lock | 97 +++++++++++++++++++++--------------------------------- 1 file changed, 38 insertions(+), 59 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 2483390a243..64aa1d874af 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -343,9 +343,9 @@ checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610" [[package]] name = "bytes" -version = "1.0.1" +version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b700ce4376041dcd0a327fd0097c41095743c4c8af8887265942faf1100bd040" +checksum = "89b2fd2a0dcf38d7971e2194b6b6eebab45ae01067456a7fd93d5547a61b70be" [[package]] name = "camino" @@ -536,27 +536,16 @@ checksum = "8a2dd5a6fe8c6e3502f568a6353e5273bbb15193ad9a89e457b9970798efbea1" name = "clippy" version = "0.1.72" dependencies = [ - "clap", "clippy_lints", - "clippy_utils", - "compiletest_rs", - "derive-new", "filetime", - "futures", - "if_chain", "itertools", - "parking_lot 0.12.1", - "quote", "regex", - "rustc-semver", "rustc_tools_util", - "serde", - "syn 2.0.8", "tempfile", "termize", "tester", - "tokio", "toml 0.7.4", + "ui_test", "walkdir", ] @@ -585,6 +574,7 @@ dependencies = [ "itertools", "pulldown-cmark", "quine-mc_cluskey", + "regex", "regex-syntax 0.7.1", "rustc-semver", "semver", @@ -597,6 +587,24 @@ dependencies = [ "url", ] +[[package]] +name = "clippy_test_deps" +version = "0.1.0" +dependencies = [ + "clippy_lints", + "clippy_utils", + "derive-new", + "futures", + "if_chain", + "itertools", + "parking_lot 0.12.1", + "quote", + "regex", + "serde", + "syn 2.0.8", + "tokio", +] + [[package]] name = "clippy_utils" version = "0.1.72" @@ -677,7 +685,7 @@ dependencies = [ "glob", "lazycell", "libc", - "miow 0.5.0", + "miow", "miropt-test-tools", "once_cell", "regex", @@ -691,29 +699,6 @@ dependencies = [ "windows", ] -[[package]] -name = "compiletest_rs" -version = "0.10.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e2731272cf25196735df1b52ab5bcba22cf9f99455626c4c8dc092bd5f7f66d0" -dependencies = [ - "diff", - "filetime", - "getopts", - "lazy_static", - "libc", - "log", - "miow 0.3.7", - "regex", - "rustfix", - "serde", - "serde_derive", - "serde_json", - "tempfile", - "tester", - "winapi", -] - [[package]] name = "concolor-override" version = "1.0.0" @@ -881,9 +866,9 @@ dependencies = [ [[package]] name = "derive-new" -version = "0.5.8" +version = "0.5.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "71f31892cd5c62e414316f2963c5689242c43d8e7bbcaaeca97e5e28c95d91d9" +checksum = "3418329ca0ad70234b9735dc4ceed10af4df60eff9c8e7b06cb5e520d92c3535" dependencies = [ "proc-macro2", "quote", @@ -2156,15 +2141,6 @@ dependencies = [ "rustc-std-workspace-core", ] -[[package]] -name = "miow" -version = "0.3.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b9f1c5b025cda876f66ef43a113f91ebc9f4ccef34843000e0adf6ebbab84e21" -dependencies = [ - "winapi", -] - [[package]] name = "miow" version = "0.5.0" @@ -2386,7 +2362,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3742b2c103b9f06bc9fff0a37ff4912935851bee6d36f3c02bcc755bcfec228f" dependencies = [ "lock_api", - "parking_lot_core 0.9.4", + "parking_lot_core 0.9.8", ] [[package]] @@ -2405,15 +2381,15 @@ dependencies = [ [[package]] name = "parking_lot_core" -version = "0.9.4" +version = "0.9.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4dc9e0dc2adc1c69d09143aff38d3d30c5c3f0df0dad82e6d25547af174ebec0" +checksum = "93f00c865fe7cabf650081affecd3871070f26767e7b2070a3ffae14c654b447" dependencies = [ "cfg-if", "libc", - "redox_syscall 0.2.10", + "redox_syscall 0.3.5", "smallvec", - "windows-sys 0.42.0", + "windows-targets 0.48.0", ] [[package]] @@ -4467,9 +4443,12 @@ checksum = "fa8f3741c7372e75519bd9346068370c9cdaabcc1f9599cbcf2a2719352286b7" [[package]] name = "slab" -version = "0.4.2" +version = "0.4.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c111b5bd5695e56cffe5129854aa230b39c93a305372fdbb2668ca2394eea9f8" +checksum = "6528351c9bc8ab22353f9d776db39a20288e8d6c37ef8cfe3317cf875eecfc2d" +dependencies = [ + "autocfg", +] [[package]] name = "smallvec" @@ -4901,14 +4880,14 @@ checksum = "cda74da7e1a664f795bb1f8a87ec406fb89a02522cf6e50620d016add6dbbf5c" [[package]] name = "tokio" -version = "1.28.2" +version = "1.29.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "94d7b1cfd2aa4011f2de74c2c4c63665e27a71006b0a192dcd2710272e73dfa2" +checksum = "532826ff75199d5833b9d2c5fe410f29235e25704ee5f0ef599fb51c21f4a4da" dependencies = [ "autocfg", + "backtrace", "bytes", "pin-project-lite", - "windows-sys 0.48.0", ] [[package]]