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 28ecdea7ea06c..e872d190c8216 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 { + 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 { - arch_32_suffix - }, + 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 362f70d12d185..877bee5e4d113 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 a86b85706a345..60a0eabf55b0b 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 65ecf1aa37aaa..a7d78a95d59cd 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 0000000000000..1d1e566cbf6fe --- /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 4d8698d383ba5..6e126aff7512e 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 fc084e30d7fe8..0055fe061e2aa 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 ac724ac93e3f2..50473868005e0 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 018f875d60bfa..ca81808a8636c 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 7ce9e855b5e05..77210ca7a9da1 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 0bcafde658a43..0f5cdb6aaea17 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 9be2d0eae80aa..126356c968263 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 a9a4a0f5a6b5c..99c3f468f04a7 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 14748f583f0cd..7b866d274d586 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 | 504 ++++++++++-------- .../internal_lints/metadata_collector.rs | 10 +- clippy_lints/src/utils/mod.rs | 9 +- 3 files changed, 289 insertions(+), 234 deletions(-) diff --git a/book/src/lint_configuration.md b/book/src/lint_configuration.md index 5646c9b15208f..4c888b63793b8 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` | - -### arithmetic-side-effects-allowed +# Lint Configuration Options + +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) - - -### msrv +--- +**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` 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) - - -### cognitive-complexity-threshold +--- +**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` 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 7a1cd3effaef2..2a9aba0a11628 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 d3ea7cafa80c2..884edec2d796e 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 f0be7771bb1a6..2dfab259915bd 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 e8f992e6ddedb..1dd3f3b8bc409 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 51a3b0d972e68..e69de29bb2d1d 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 2dfab259915bd..942453498cdde 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 1dd3f3b8bc409..510eca21f71bc 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 704d448644e28..b2eafb345e33b 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 a2648d9faa6d7..7a127c08197ad 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 4ade25e1257e0..fceb6e4b2ae53 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 0000000000000..007a3f4344934 --- /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 10404d51ba556..bfe52e182b294 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 0000000000000..219b60bd051bf --- /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 0000000000000..358f4bc661d10 --- /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 0000000000000..a0bd81c21eac4 --- /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 455f0df7cd0ad..a08113bf9e65a 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 007a3f4344934..a56d72f0dead9 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 d4c3f76b86417..7d1f8ef29c817 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 a56d72f0dead9..ff4144df9b9aa 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 219b60bd051bf..9d778faf8e0c5 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 358f4bc661d10..1e051fd06ecfe 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 a0bd81c21eac4..14b95fb097a0c 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 d62639caca1b6..bf38aab94a9af 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 804ae841100a5..08ed8a63e1add 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 2189c3d2f8556..c45d669fd733d 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 b77f01883bf38..27e03ebb7197d 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 81af88962a64d..19ab03418eed3 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 8484da2415ab3..95ef6425fad9a 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 96e4af12ba386..1963d08014b15 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 575dadde90630..215f0ac184225 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 4238ff804780e..3528e13790393 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 bcc231ea7bce5..7038a2915cb23 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 282b2f1283ee9..5e76640580936 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 fcee4ee2a65cc..077274c23371b 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 0d1d9258433b2..9389426238ce5 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 9389426238ce5..7d71947e42814 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 c45d669fd733d..2189c3d2f8556 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 | 96 ++++++++++++++++++++------------ 3 files changed, 88 insertions(+), 38 deletions(-) diff --git a/tests/ui/unnecessary_cast.fixed b/tests/ui/unnecessary_cast.fixed index 7038a2915cb23..42fcb6ef41149 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 5e76640580936..2daf2e9938f70 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 077274c23371b..61e165e2ddd5b 100644 --- a/tests/ui/unnecessary_cast.stderr +++ b/tests/ui/unnecessary_cast.stderr @@ -1,202 +1,226 @@ +error: casting raw pointers to the same type and constness is unnecessary (`*const T` -> `*const T`) + --> $DIR/unnecessary_cast.rs:15:5 + | +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:17:5 + --> $DIR/unnecessary_cast.rs:25:5 | LL | 1i32 as i32; | ^^^^^^^^^^^ help: try: `1_i32` - | - = note: `-D clippy::unnecessary-cast` implied by `-D warnings` 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 42fcb6ef41149..0fd49e7c81583 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 2daf2e9938f70..2766949232932 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 61e165e2ddd5b..0e511fb4c7a75 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 8791debad7231..1b4677a3c0e82 100644 --- a/util/gh-pages/index.html +++ b/util/gh-pages/index.html @@ -517,7 +517,8 @@

Clippy Lints

{{lint.id}} - + 📋 diff --git a/util/gh-pages/script.js b/util/gh-pages/script.js index 1c16ecd6b0b1f..3aaf455e12feb 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 3aaf455e12feb..868b63a27dffc 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 1b4677a3c0e82..99e211654d19c 100644 --- a/util/gh-pages/index.html +++ b/util/gh-pages/index.html @@ -501,9 +501,11 @@

Clippy Lints

- + - diff --git a/util/gh-pages/script.js b/util/gh-pages/script.js index 868b63a27dffc..fd32225dabc33 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 fd32225dabc33..bd4293662a0a5 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 10ce2a0f0c7ec..eb967e3f95e42 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 d18f93875658c..00895e594f6e2 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 de8ff0b06bdca..7f8c76693fd16 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 6039f86fe6703..498b00de5adb6 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 3b280b7488ae7..7303b80567396 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 7a127c08197ad..a2648d9faa6d7 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 fceb6e4b2ae53..4ade25e1257e0 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 ff4144df9b9aa..0000000000000 --- 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 bfe52e182b294..10404d51ba556 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 28c3fc859e332..6f1e9d5f9de28 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 9d778faf8e0c5..0000000000000 --- 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 1e051fd06ecfe..0000000000000 --- 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 14b95fb097a0c..0000000000000 --- 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 c16caa38fe93e..e9563b8a60a8a 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 c75a2bce4ca23..c2f4e3117d2ef 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 4dca3aac53361..68f38faab5930 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 5a924ca1830a4..5ea86a9ff37d1 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 10ce2a0f0c7ec..e725fb26c2223 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 d18f93875658c..f1333bb39a8b8 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 de8ff0b06bdca..4fb91971db9a4 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 6039f86fe6703..c514bb6146c89 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 8b609b47d8192..bfb528546342a 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 a7067d8b86aaf..aaaa38d4da533 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 0000000000000..bf6b92644e233 --- /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 a0a89e4967b8f..122fc3feeee50 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 0000000000000..1dfda9d53bfba --- /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 0000000000000..afbb8e3b16c73 --- /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 | 209 ++-- tests/ui/endian_bytes.rs | 260 ++--- tests/ui/endian_bytes.stderr | 1657 ++++++++++++++---------------- 3 files changed, 1014 insertions(+), 1112 deletions(-) diff --git a/clippy_lints/src/endian_bytes.rs b/clippy_lints/src/endian_bytes.rs index bf6b92644e233..6486430cf57f7 100644 --- a/clippy_lints/src/endian_bytes.rs +++ b/clippy_lints/src/endian_bytes.rs @@ -1,23 +1,23 @@ -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}; +use rustc_span::Symbol; +use std::borrow::Cow; 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 - /// // example code where clippy issues a warning - /// ``` - /// Use instead: - /// ```rust - /// // example code which does not raise clippy warning + /// ```rust,ignore + /// let _x = 2i32.to_ne_bytes(); + /// let _y = 2i64.to_ne_bytes(); /// ``` #[clippy::version = "1.71.0"] pub HOST_ENDIAN_BYTES, @@ -27,15 +27,16 @@ declare_clippy_lint! { declare_clippy_lint! { /// ### What it does - /// Checks for the usage of the `to_ne_bytes` method. + /// Checks for the usage of the `to_le_bytes` method. /// /// ### Why is this bad? - /// It's not, but some may prefer to specify the target endianness explicitly. + /// 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 - /// let _x = 2i32.to_ne_bytes(); - /// let _y = 2i64.to_ne_bytes(); + /// let _x = 2i32.to_le_bytes(); + /// let _y = 2i64.to_le_bytes(); /// ``` #[clippy::version = "1.71.0"] pub LITTLE_ENDIAN_BYTES, @@ -45,13 +46,16 @@ 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_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 - /// // example code where clippy issues a warning + /// 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 1dfda9d53bfba..ccee8e20a3cc8 100644 --- a/tests/ui/endian_bytes.rs +++ b/tests/ui/endian_bytes.rs @@ -2,162 +2,126 @@ #![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!()); +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!()); + }; } -#[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!()); +// 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() { fn_body!(); } + +#[rustfmt::skip] +#[warn(clippy::little_endian_bytes)] +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 afbb8e3b16c73..ff8d1a98f4f52 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 - | -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 +error: usage of the method `to_ne_bytes` + --> $DIR/endian_bytes.rs:7:9 | -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 | 2u8.to_ne_bytes(); + | ^^^^^^^^^^^^^^^^^ +... +LL | fn host() { fn_body!(); } + | ---------- in this macro invocation | -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) + = 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 `from_ne_bytes` - --> $DIR/endian_bytes.rs:21:23 +error: usage of the method `to_ne_bytes` + --> $DIR/endian_bytes.rs:8:9 | -LL | u8::from_ne_bytes(todo!()); - | ^^^^^^^ +LL | 2i8.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).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) + = 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:21:23 +error: usage of the method `to_ne_bytes` + --> $DIR/endian_bytes.rs:9:9 | -LL | u8::from_ne_bytes(todo!()); - | ^^^^^^^ +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).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) + = 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:22:5 +error: usage of the method `to_ne_bytes` + --> $DIR/endian_bytes.rs:10:9 | -LL | i8::from_ne_bytes(todo!()); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | 2i16.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).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) } + = 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:22:5 +error: usage of the method `to_ne_bytes` + --> $DIR/endian_bytes.rs:11:9 | -LL | i8::from_ne_bytes(todo!()); - | ^^^^^^^^^^^^^^^^^ +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).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) } + = 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:22:23 +error: usage of the method `to_ne_bytes` + --> $DIR/endian_bytes.rs:12:9 | -LL | i8::from_ne_bytes(todo!()); - | ^^^^^^^ +LL | 2i32.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).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) + = 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:22:23 +error: usage of the method `to_ne_bytes` + --> $DIR/endian_bytes.rs:13:9 | -LL | i8::from_ne_bytes(todo!()); - | ^^^^^^^ +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).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) + = 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:22:23 +error: usage of the method `to_ne_bytes` + --> $DIR/endian_bytes.rs:14:9 | -LL | i8::from_ne_bytes(todo!()); - | ^^^^^^^ +LL | 2i64.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).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) + = 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:23:5 +error: usage of the method `to_ne_bytes` + --> $DIR/endian_bytes.rs:15:9 | -LL | u16::from_ne_bytes(todo!()); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ +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).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) } + = 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:23:5 +error: usage of the method `to_ne_bytes` + --> $DIR/endian_bytes.rs:16:9 | -LL | u16::from_ne_bytes(todo!()); - | ^^^^^^^^^^^^^^^^^^ +LL | 2i128.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).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) } + = 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:23:24 +error: usage of the method `to_ne_bytes` + --> $DIR/endian_bytes.rs:17:9 | -LL | u16::from_ne_bytes(todo!()); - | ^^^^^^^ +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).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) + = 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:23:24 +error: usage of the method `to_ne_bytes` + --> $DIR/endian_bytes.rs:18:9 | -LL | u16::from_ne_bytes(todo!()); - | ^^^^^^^ +LL | 2.0f64.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).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) + = 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:23:24 +error: usage of the method `to_ne_bytes` + --> $DIR/endian_bytes.rs:19:9 | -LL | u16::from_ne_bytes(todo!()); - | ^^^^^^^ +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).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) + = 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:24:5 +error: usage of the method `to_ne_bytes` + --> $DIR/endian_bytes.rs:20:9 | -LL | i16::from_ne_bytes(todo!()); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | 2isize.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).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) } + = 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:24:5 +error: usage of the method `from_ne_bytes` + --> $DIR/endian_bytes.rs:21:9 | -LL | i16::from_ne_bytes(todo!()); - | ^^^^^^^^^^^^^^^^^^ +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).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) } + = 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:24:24 +error: usage of the method `from_ne_bytes` + --> $DIR/endian_bytes.rs:22:9 | -LL | i16::from_ne_bytes(todo!()); - | ^^^^^^^ +LL | i8::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).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) + = 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:24:24 +error: usage of the method `from_ne_bytes` + --> $DIR/endian_bytes.rs:23:9 | -LL | i16::from_ne_bytes(todo!()); - | ^^^^^^^ +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).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) + = 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:24:24 +error: usage of the method `from_ne_bytes` + --> $DIR/endian_bytes.rs:24:9 | -LL | i16::from_ne_bytes(todo!()); - | ^^^^^^^ +LL | i16::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).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) + = 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:25:5 +error: usage of the method `from_ne_bytes` + --> $DIR/endian_bytes.rs:25:9 | -LL | u32::from_ne_bytes(todo!()); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ +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).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) } + = 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:25:5 +error: usage of the method `from_ne_bytes` + --> $DIR/endian_bytes.rs:26:9 | -LL | u32::from_ne_bytes(todo!()); - | ^^^^^^^^^^^^^^^^^^ +LL | i32::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).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) } + = 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:25:24 +error: usage of the method `from_ne_bytes` + --> $DIR/endian_bytes.rs:27:9 | -LL | u32::from_ne_bytes(todo!()); - | ^^^^^^^ +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).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) + = 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:25:24 +error: usage of the method `from_ne_bytes` + --> $DIR/endian_bytes.rs:28:9 | -LL | u32::from_ne_bytes(todo!()); - | ^^^^^^^ +LL | i64::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).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) + = 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:25:24 +error: usage of the method `from_ne_bytes` + --> $DIR/endian_bytes.rs:29:9 | -LL | u32::from_ne_bytes(todo!()); - | ^^^^^^^ +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).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) + = 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:26:5 +error: usage of the method `from_ne_bytes` + --> $DIR/endian_bytes.rs:30:9 | -LL | i32::from_ne_bytes(todo!()); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | i128::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).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) } + = 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:26:5 +error: usage of the method `from_ne_bytes` + --> $DIR/endian_bytes.rs:31:9 | -LL | i32::from_ne_bytes(todo!()); - | ^^^^^^^^^^^^^^^^^^ +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).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) } + = 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:26:24 +error: usage of the method `from_ne_bytes` + --> $DIR/endian_bytes.rs:32:9 | -LL | i32::from_ne_bytes(todo!()); - | ^^^^^^^ +LL | isize::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).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) + = 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:26:24 +error: usage of the method `from_ne_bytes` + --> $DIR/endian_bytes.rs:33:9 | -LL | i32::from_ne_bytes(todo!()); - | ^^^^^^^ +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).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) + = 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:26:24 +error: usage of the method `from_ne_bytes` + --> $DIR/endian_bytes.rs:34:9 | -LL | i32::from_ne_bytes(todo!()); - | ^^^^^^^ +LL | f64::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).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) + = 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:27:5 +error: usage of the method `to_le_bytes` + --> $DIR/endian_bytes.rs:36:9 | -LL | u64::from_ne_bytes(todo!()); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ +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).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) } + = 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 `from_ne_bytes` - --> $DIR/endian_bytes.rs:27:5 +error: usage of the method `to_le_bytes` + --> $DIR/endian_bytes.rs:37:9 | -LL | u64::from_ne_bytes(todo!()); - | ^^^^^^^^^^^^^^^^^^ +LL | 2i8.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).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) } + = 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 `from_ne_bytes` - --> $DIR/endian_bytes.rs:27:24 +error: usage of the method `to_le_bytes` + --> $DIR/endian_bytes.rs:38:9 | -LL | u64::from_ne_bytes(todo!()); - | ^^^^^^^ +LL | 2u16.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).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) + = 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 `from_ne_bytes` - --> $DIR/endian_bytes.rs:27:24 +error: usage of the method `to_le_bytes` + --> $DIR/endian_bytes.rs:39:9 | -LL | u64::from_ne_bytes(todo!()); - | ^^^^^^^ +LL | 2i16.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).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) + = 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 `from_ne_bytes` - --> $DIR/endian_bytes.rs:27:24 +error: usage of the method `to_le_bytes` + --> $DIR/endian_bytes.rs:40:9 | -LL | u64::from_ne_bytes(todo!()); - | ^^^^^^^ +LL | 2u32.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).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) + = 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 `from_ne_bytes` - --> $DIR/endian_bytes.rs:28:5 +error: usage of the method `to_le_bytes` + --> $DIR/endian_bytes.rs:41:9 | -LL | i64::from_ne_bytes(todo!()); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | 2i32.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).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) } + = 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 `from_ne_bytes` - --> $DIR/endian_bytes.rs:28:5 +error: usage of the method `to_le_bytes` + --> $DIR/endian_bytes.rs:42:9 | -LL | i64::from_ne_bytes(todo!()); - | ^^^^^^^^^^^^^^^^^^ +LL | 2u64.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).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) } + = 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 `from_ne_bytes` - --> $DIR/endian_bytes.rs:28:24 +error: usage of the method `to_le_bytes` + --> $DIR/endian_bytes.rs:43:9 | -LL | i64::from_ne_bytes(todo!()); - | ^^^^^^^ +LL | 2i64.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).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) + = 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 `from_ne_bytes` - --> $DIR/endian_bytes.rs:28:24 +error: usage of the method `to_le_bytes` + --> $DIR/endian_bytes.rs:44:9 | -LL | i64::from_ne_bytes(todo!()); - | ^^^^^^^ +LL | 2u128.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).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) + = 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 `from_ne_bytes` - --> $DIR/endian_bytes.rs:28:24 +error: usage of the method `to_le_bytes` + --> $DIR/endian_bytes.rs:45:9 | -LL | i64::from_ne_bytes(todo!()); - | ^^^^^^^ +LL | 2i128.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).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) + = 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 `from_ne_bytes` - --> $DIR/endian_bytes.rs:29:5 +error: usage of the method `to_le_bytes` + --> $DIR/endian_bytes.rs:46:9 | -LL | u128::from_ne_bytes(todo!()); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | 2.0f32.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).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) } + = 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 `from_ne_bytes` - --> $DIR/endian_bytes.rs:29:5 +error: usage of the method `to_le_bytes` + --> $DIR/endian_bytes.rs:47:9 | -LL | u128::from_ne_bytes(todo!()); - | ^^^^^^^^^^^^^^^^^^^ +LL | 2.0f64.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).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) } + = 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 `from_ne_bytes` - --> $DIR/endian_bytes.rs:29:25 +error: usage of the method `to_le_bytes` + --> $DIR/endian_bytes.rs:48:9 | -LL | u128::from_ne_bytes(todo!()); - | ^^^^^^^ +LL | 2usize.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).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) + = 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 `from_ne_bytes` - --> $DIR/endian_bytes.rs:29:25 +error: usage of the method `to_le_bytes` + --> $DIR/endian_bytes.rs:49:9 | -LL | u128::from_ne_bytes(todo!()); - | ^^^^^^^ +LL | 2isize.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).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) + = 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 `from_ne_bytes` - --> $DIR/endian_bytes.rs:29:25 +error: usage of the method `from_le_bytes` + --> $DIR/endian_bytes.rs:50:9 | -LL | u128::from_ne_bytes(todo!()); - | ^^^^^^^ +LL | u8::from_le_bytes(todo!()); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ +... +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).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) + = 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 `from_ne_bytes` - --> $DIR/endian_bytes.rs:30:5 +error: usage of the method `from_le_bytes` + --> $DIR/endian_bytes.rs:51:9 | -LL | i128::from_ne_bytes(todo!()); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | i8::from_le_bytes(todo!()); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ +... +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).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) } + = 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 `from_ne_bytes` - --> $DIR/endian_bytes.rs:30:5 +error: usage of the method `from_le_bytes` + --> $DIR/endian_bytes.rs:52:9 | -LL | i128::from_ne_bytes(todo!()); - | ^^^^^^^^^^^^^^^^^^^ +LL | u16::from_le_bytes(todo!()); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ +... +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).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) } + = 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 `from_ne_bytes` - --> $DIR/endian_bytes.rs:30:25 +error: usage of the method `from_le_bytes` + --> $DIR/endian_bytes.rs:53:9 | -LL | i128::from_ne_bytes(todo!()); - | ^^^^^^^ +LL | i16::from_le_bytes(todo!()); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ +... +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).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) + = 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 `from_ne_bytes` - --> $DIR/endian_bytes.rs:30:25 +error: usage of the method `from_le_bytes` + --> $DIR/endian_bytes.rs:54:9 | -LL | i128::from_ne_bytes(todo!()); - | ^^^^^^^ +LL | u32::from_le_bytes(todo!()); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ +... +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).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) + = 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 `from_ne_bytes` - --> $DIR/endian_bytes.rs:30:25 +error: usage of the method `from_le_bytes` + --> $DIR/endian_bytes.rs:55:9 | -LL | i128::from_ne_bytes(todo!()); - | ^^^^^^^ +LL | i32::from_le_bytes(todo!()); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ +... +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).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) + = 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 `from_ne_bytes` - --> $DIR/endian_bytes.rs:31:5 +error: usage of the method `from_le_bytes` + --> $DIR/endian_bytes.rs:56:9 | -LL | f32::from_ne_bytes(todo!()); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | u64::from_le_bytes(todo!()); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ +... +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).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) } + = 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 `from_ne_bytes` - --> $DIR/endian_bytes.rs:31:5 +error: usage of the method `from_le_bytes` + --> $DIR/endian_bytes.rs:57:9 | -LL | f32::from_ne_bytes(todo!()); - | ^^^^^^^^^^^^^^^^^^ +LL | i64::from_le_bytes(todo!()); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ +... +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).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) } + = 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 `from_ne_bytes` - --> $DIR/endian_bytes.rs:31:24 +error: usage of the method `from_le_bytes` + --> $DIR/endian_bytes.rs:58:9 | -LL | f32::from_ne_bytes(todo!()); - | ^^^^^^^ +LL | u128::from_le_bytes(todo!()); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +... +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).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) + = 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 `from_ne_bytes` - --> $DIR/endian_bytes.rs:31:24 +error: usage of the method `from_le_bytes` + --> $DIR/endian_bytes.rs:59:9 | -LL | f32::from_ne_bytes(todo!()); - | ^^^^^^^ +LL | i128::from_le_bytes(todo!()); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +... +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).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) + = 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 `from_ne_bytes` - --> $DIR/endian_bytes.rs:31:24 +error: usage of the method `from_le_bytes` + --> $DIR/endian_bytes.rs:60:9 | -LL | f32::from_ne_bytes(todo!()); - | ^^^^^^^ +LL | usize::from_le_bytes(todo!()); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +... +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).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) + = 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 `from_ne_bytes` - --> $DIR/endian_bytes.rs:32:5 +error: usage of the method `from_le_bytes` + --> $DIR/endian_bytes.rs:61:9 | -LL | f64::from_ne_bytes(todo!()); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | isize::from_le_bytes(todo!()); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +... +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).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) } + = 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 `from_ne_bytes` - --> $DIR/endian_bytes.rs:32:5 +error: usage of the method `from_le_bytes` + --> $DIR/endian_bytes.rs:62:9 | -LL | f64::from_ne_bytes(todo!()); - | ^^^^^^^^^^^^^^^^^^ +LL | f32::from_le_bytes(todo!()); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ +... +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).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) } + = 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 `from_ne_bytes` - --> $DIR/endian_bytes.rs:32:24 +error: usage of the method `from_le_bytes` + --> $DIR/endian_bytes.rs:63:9 | -LL | f64::from_ne_bytes(todo!()); - | ^^^^^^^ +LL | f64::from_le_bytes(todo!()); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ +... +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).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) + = 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 `from_ne_bytes` - --> $DIR/endian_bytes.rs:32:24 +error: usage of the method `to_ne_bytes` + --> $DIR/endian_bytes.rs:70:9 | -LL | f64::from_ne_bytes(todo!()); - | ^^^^^^^ +LL | 2u8.to_ne_bytes(); + | ^^^^^^^^^^^^^^^^^ +... +LL | fn host_encourage_little() { fn_body_small!(); } + | ---------------- in this macro invocation | - = 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) + = 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 `from_ne_bytes` - --> $DIR/endian_bytes.rs:32:24 +error: usage of the method `from_ne_bytes` + --> $DIR/endian_bytes.rs:71:9 | -LL | f64::from_ne_bytes(todo!()); - | ^^^^^^^ +LL | u8::from_ne_bytes(todo!()); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ +... +LL | fn host_encourage_little() { fn_body_small!(); } + | ---------------- in this macro invocation | - = 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) + = 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_le_bytes` - --> $DIR/endian_bytes.rs:37:5 +error: usage of the method `to_be_bytes` + --> $DIR/endian_bytes.rs:76:9 | -LL | 2u8.to_le_bytes(); - | ^^^^^^^^^^^^^^^^^ +LL | 2u8.to_be_bytes(); + | ^^^^^^^^^^^^^^^^^ +... +LL | fn host_encourage_little() { fn_body_small!(); } + | ---------------- in this macro invocation | - = help: use `to_be_bytes` instead - = note: `-D clippy::little-endian-bytes` implied by `-D warnings` + = 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_le_bytes` - --> $DIR/endian_bytes.rs:38:5 +error: usage of the method `from_be_bytes` + --> $DIR/endian_bytes.rs:77:9 | -LL | 2i8.to_le_bytes(); - | ^^^^^^^^^^^^^^^^^ +LL | u8::from_be_bytes(todo!()); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ +... +LL | fn host_encourage_little() { fn_body_small!(); } + | ---------------- in this macro invocation | - = help: use `to_be_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_le_bytes` - --> $DIR/endian_bytes.rs:39:5 +error: usage of the method `to_ne_bytes` + --> $DIR/endian_bytes.rs:70:9 | -LL | 2u16.to_le_bytes(); - | ^^^^^^^^^^^^^^^^^^ +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: use of the method `to_le_bytes` - --> $DIR/endian_bytes.rs:40:5 +error: usage of the method `from_ne_bytes` + --> $DIR/endian_bytes.rs:71:9 | -LL | 2i16.to_le_bytes(); - | ^^^^^^^^^^^^^^^^^^ +LL | u8::from_ne_bytes(todo!()); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ +... +LL | fn host_encourage_big() { fn_body_small!(); } + | ---------------- in this macro invocation | - = help: use `to_be_bytes` instead + = 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: 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:73:9 | -LL | 2u32.to_le_bytes(); - | ^^^^^^^^^^^^^^^^^^ +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: use of the method `to_le_bytes` - --> $DIR/endian_bytes.rs:42:5 +error: usage of the method `from_le_bytes` + --> $DIR/endian_bytes.rs:74:9 | -LL | 2i32.to_le_bytes(); - | ^^^^^^^^^^^^^^^^^^ +LL | u8::from_le_bytes(todo!()); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ +... +LL | fn host_encourage_big() { fn_body_small!(); } + | ---------------- in this macro invocation | - = help: use `to_be_bytes` instead + = 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: use of the method `to_le_bytes` - --> $DIR/endian_bytes.rs:43:5 +error: usage of the method `to_ne_bytes` + --> $DIR/endian_bytes.rs:70:9 | -LL | 2u64.to_le_bytes(); - | ^^^^^^^^^^^^^^^^^^ +LL | 2u8.to_ne_bytes(); + | ^^^^^^^^^^^^^^^^^ +... +LL | fn no_help() { 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: use of the method `to_le_bytes` - --> $DIR/endian_bytes.rs:44:5 +error: usage of the method `from_ne_bytes` + --> $DIR/endian_bytes.rs:71:9 | -LL | 2i64.to_le_bytes(); - | ^^^^^^^^^^^^^^^^^^ +LL | u8::from_ne_bytes(todo!()); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ +... +LL | fn no_help() { 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: 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:73:9 | -LL | 2u128.to_le_bytes(); - | ^^^^^^^^^^^^^^^^^^^ +LL | 2u8.to_le_bytes(); + | ^^^^^^^^^^^^^^^^^ +... +LL | fn no_help() { 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: use of the method `to_le_bytes` - --> $DIR/endian_bytes.rs:46:5 +error: usage of the method `from_le_bytes` + --> $DIR/endian_bytes.rs:74:9 | -LL | 2i128.to_le_bytes(); - | ^^^^^^^^^^^^^^^^^^^ +LL | u8::from_le_bytes(todo!()); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ +... +LL | fn no_help() { 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: use of the method `to_le_bytes` - --> $DIR/endian_bytes.rs:47:5 +error: usage of the method `to_be_bytes` + --> $DIR/endian_bytes.rs:76:9 | -LL | 2usize.to_le_bytes(); - | ^^^^^^^^^^^^^^^^^^^^ +LL | 2u8.to_be_bytes(); + | ^^^^^^^^^^^^^^^^^ +... +LL | fn no_help() { 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: use of the method `to_le_bytes` - --> $DIR/endian_bytes.rs:48:5 +error: usage of the method `from_be_bytes` + --> $DIR/endian_bytes.rs:77:9 | -LL | 2isize.to_le_bytes(); - | ^^^^^^^^^^^^^^^^^^^^ +LL | u8::from_be_bytes(todo!()); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ +... +LL | fn no_help() { 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: 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:73:9 | -LL | 2.0f32.to_le_bytes(); - | ^^^^^^^^^^^^^^^^^^^^ +LL | 2u8.to_le_bytes(); + | ^^^^^^^^^^^^^^^^^ +... +LL | fn little_encourage_host() { fn_body_small!(); } + | ---------------- 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_small` (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 `from_le_bytes` + --> $DIR/endian_bytes.rs:74:9 | -LL | 2.0f64.to_le_bytes(); - | ^^^^^^^^^^^^^^^^^^^^ +LL | u8::from_le_bytes(todo!()); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ +... +LL | fn little_encourage_host() { fn_body_small!(); } + | ---------------- 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_small` (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 `to_be_bytes` + --> $DIR/endian_bytes.rs:76:9 | -LL | 2u8.to_be_bytes(); - | ^^^^^^^^^^^^^^^^^ +LL | 2u8.to_be_bytes(); + | ^^^^^^^^^^^^^^^^^ +... +LL | fn little_encourage_host() { fn_body_small!(); } + | ---------------- in this macro invocation | - = help: use `to_le_bytes` instead - = note: `-D clippy::big-endian-bytes` implied by `-D warnings` + = 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: 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 little_encourage_host() { fn_body_small!(); } + | ---------------- in this macro invocation | - = help: use `to_le_bytes` instead + = 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: use of the method `to_be_bytes` - --> $DIR/endian_bytes.rs:71:5 +error: usage of the method `to_ne_bytes` + --> $DIR/endian_bytes.rs:70:9 | -LL | 2u16.to_be_bytes(); - | ^^^^^^^^^^^^^^^^^^ +LL | 2u8.to_ne_bytes(); + | ^^^^^^^^^^^^^^^^^ +... +LL | fn little_encourage_big() { fn_body_small!(); } + | ---------------- in this macro invocation | - = 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 + = 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: use of the method `to_be_bytes` - --> $DIR/endian_bytes.rs:73:5 +error: usage of the method `from_ne_bytes` + --> $DIR/endian_bytes.rs:71:9 | -LL | 2u32.to_be_bytes(); - | ^^^^^^^^^^^^^^^^^^ +LL | u8::from_ne_bytes(todo!()); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ +... +LL | fn little_encourage_big() { fn_body_small!(); } + | ---------------- in this macro invocation | - = help: use `to_le_bytes` instead + = 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: use of the method `to_be_bytes` - --> $DIR/endian_bytes.rs:74:5 +error: usage of the method `to_le_bytes` + --> $DIR/endian_bytes.rs:73:9 | -LL | 2i32.to_be_bytes(); - | ^^^^^^^^^^^^^^^^^^ +LL | 2u8.to_le_bytes(); + | ^^^^^^^^^^^^^^^^^ +... +LL | fn little_encourage_big() { fn_body_small!(); } + | ---------------- in this macro invocation | - = help: use `to_le_bytes` instead + = 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: use of the method `to_be_bytes` - --> $DIR/endian_bytes.rs:75:5 +error: usage of the method `from_le_bytes` + --> $DIR/endian_bytes.rs:74:9 | -LL | 2u64.to_be_bytes(); - | ^^^^^^^^^^^^^^^^^^ +LL | u8::from_le_bytes(todo!()); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ +... +LL | fn little_encourage_big() { fn_body_small!(); } + | ---------------- in this macro invocation | - = help: use `to_le_bytes` instead + = 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: use of the method `to_be_bytes` - --> $DIR/endian_bytes.rs:76:5 +error: usage of the method `to_le_bytes` + --> $DIR/endian_bytes.rs:73:9 | -LL | 2i64.to_be_bytes(); - | ^^^^^^^^^^^^^^^^^^ +LL | 2u8.to_le_bytes(); + | ^^^^^^^^^^^^^^^^^ +... +LL | fn big_encourage_host() { fn_body_small!(); } + | ---------------- in this macro invocation | - = help: use `to_le_bytes` instead + = 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: use of the method `to_be_bytes` - --> $DIR/endian_bytes.rs:77:5 +error: usage of the method `from_le_bytes` + --> $DIR/endian_bytes.rs:74:9 | -LL | 2u128.to_be_bytes(); - | ^^^^^^^^^^^^^^^^^^^ +LL | u8::from_le_bytes(todo!()); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ +... +LL | fn big_encourage_host() { fn_body_small!(); } + | ---------------- in this macro invocation | - = help: use `to_le_bytes` instead + = 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: use of the method `to_be_bytes` - --> $DIR/endian_bytes.rs:78:5 +error: usage of the method `to_be_bytes` + --> $DIR/endian_bytes.rs:76:9 | -LL | 2i128.to_be_bytes(); - | ^^^^^^^^^^^^^^^^^^^ +LL | 2u8.to_be_bytes(); + | ^^^^^^^^^^^^^^^^^ +... +LL | fn big_encourage_host() { fn_body_small!(); } + | ---------------- in this macro invocation | - = help: use `to_le_bytes` instead + = 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: use of the method `to_be_bytes` - --> $DIR/endian_bytes.rs:79:5 +error: usage of the method `from_be_bytes` + --> $DIR/endian_bytes.rs:77:9 | -LL | 2.0f32.to_be_bytes(); - | ^^^^^^^^^^^^^^^^^^^^ +LL | u8::from_be_bytes(todo!()); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ +... +LL | fn big_encourage_host() { fn_body_small!(); } + | ---------------- in this macro invocation | - = help: use `to_le_bytes` instead + = 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: use of the method `to_be_bytes` - --> $DIR/endian_bytes.rs:80:5 +error: usage of the method `to_ne_bytes` + --> $DIR/endian_bytes.rs:70:9 | -LL | 2.0f64.to_be_bytes(); - | ^^^^^^^^^^^^^^^^^^^^ +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:81:5 +error: usage of the method `from_ne_bytes` + --> $DIR/endian_bytes.rs:71:9 | -LL | 2usize.to_be_bytes(); - | ^^^^^^^^^^^^^^^^^^^^ +LL | u8::from_ne_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:82:5 +error: usage of the method `to_be_bytes` + --> $DIR/endian_bytes.rs:76:9 | -LL | 2isize.to_be_bytes(); - | ^^^^^^^^^^^^^^^^^^^^ +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_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 +error: usage of the method `from_be_bytes` + --> $DIR/endian_bytes.rs:77:9 | -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 | u8::from_be_bytes(todo!()); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ +... +LL | fn big_encourage_little() { fn_body_small!(); } + | ---------------- in this macro invocation | -LL | 2.0f64.to_be_bytes(); - | ^^^^^^^^^^^^^^^^^^^^ + = 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: 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 6486430cf57f7..88e0d4dcd53d2 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 88e0d4dcd53d2..434125932c4c0 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 ccee8e20a3cc8..6bf014fc80951 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 ff8d1a98f4f52..5e64ea5b5ab8b 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 434125932c4c0..05005a791c2ab 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 05005a791c2ab..19fb74b90509d 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 b27ffe73ffda4..96d1bcea6e5bd 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 60482c66da7c4..6cf7a28cafa59 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 e3613e216bb22..77501fa6b6eca 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 4b10ed1377b0d..30ebcd47b2b36 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 5a459548153aa..a41d5a9ce8d2f 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 e725fb26c2223..c4405feaa978a 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 f1333bb39a8b8..98310ac5c6cda 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 c514bb6146c89..6039f86fe6703 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 c4405feaa978a..e25b45eaa2e97 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 98310ac5c6cda..d18f93875658c 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 4fb91971db9a4..de8ff0b06bdca 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 3b280b7488ae7..92d3504bc2366 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 251f1d84e74e3..2ab9b9d6b17cc 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 631ecf1428d6a..92913ddc4aa53 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 04ecdef5e994e..83a76f81d4e78 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 389b0a4a62dc5..d5e847e718331 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 dfca3b023cd58..07cd5a53a7c4f 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 13ed35bc1d5db..ead2f28e609a1 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 aea1507cc5bd9..08916398cbb28 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 aade3b1fa4571..6aacc73b90dc1 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 8b609b47d8192..995f6d4562dae 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 96d1bcea6e5bd..93b6e2083b547 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 6cf7a28cafa59..1710b170fb813 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 77501fa6b6eca..85147e1cb6977 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 30ebcd47b2b36..592563ffa8c8b 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 3df40942e7b5a..e05b88e4cd085 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 c3728886ec9c6..f8d4c0bd912d7 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 76e50fa5b0304..b968894f87039 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 0339755442c5a..c3d106cd1096e 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 2f10e3d258133..8fcf42564d526 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 7c1835e8cd18f..832d0304ffa46 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 16bf83c708fe8..26400363f5d18 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 554efdc58e1cb..69ccbeb7b06f6 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 897495ba10874..e989cde0f3cb0 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 9edaae853734c..8a8ccc30205bc 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 f0936b2608e9e..be93c5bffe7b3 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 2fb9e86126e55..10d2ed1a8a95b 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 681837e9ed770..37149104a4768 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 5c3407628be27..0000000000000 --- 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 1a0d4e886576e..95a9fa2aa4763 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 23f17e9a7afb4..96f747d0026df 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 8a8ccc30205bc..e0dbc1c970109 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 be93c5bffe7b3..5c30a9d29411f 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 e0dbc1c970109..fd04f2ddf7ce4 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 5c30a9d29411f..fa04f53ca9106 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 37149104a4768..d17fd86cb866c 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 8fcf42564d526..4f8c5ff58b585 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 832d0304ffa46..ae1a480bcfc55 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 26400363f5d18..a749552c7fac8 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 8b609b47d8192..fd619368e8f48 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 897495ba10874..891ee8af82b38 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 a7067d8b86aaf..d867ab39294c7 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 0000000000000..bc4109c2c8964 --- /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 0000000000000..00405985d48c7 --- /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 | 209 +++++---- 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, 2971 insertions(+), 654 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 0b43d8d70c007..b49493edce1ba 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 79f2a47110b9e..8b609b47d8192 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 3c72bb62ed19e..ca8bf9fac91a0 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 1304f6a8c2f09..e8274bc4575d0 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 ccae8d3742018..c26aa883ebae2 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 e2457e5a8a5e9..c03fbe9d275f3 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 98e69c7fd264a..be9261a47041c 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 add73d0aeeed3..554efdc58e1cb 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 455f0df7cd0ad..ff0102255a0a9 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 0c175372aab83..b90dab07a274a 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 0000000000000..ab015f8822e1b --- /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 5e2eb5789f627..ac5ac542cf944 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 212e809d4c564..15ff8be0fd942 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 9bd7a0dc0f3b8..fb037bbcbf3eb 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 0ca31033b169b..087c4a65250a9 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 32c6312e06946..0a5901bce046e 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 c01e3882d529f..2f10e3d258133 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 fcca595c2bc4c..4a23edb58aaa4 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 3f8b42ffe8053..389b0a4a62dc5 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 42f1e2629d41a..6424ac31d9f68 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 55ec9d4474f59..0d91051632a18 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 e81e09da42547..479cfd835126c 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 9a594d964ab22..88cbefbb5d3d5 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 2214a568d9c6d..4dbb79334caf3 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 0000000000000..b6f0de7e504f0 --- /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 0000000000000..4ff1bf7ffc0de --- /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 6c909e5ed73ea..2d79a5c90081c 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 a0f831764d071..05e52e6b38b12 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 ef19c6f461729..674f8bf4c0f30 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 df126d7617ebe..631ecf1428d6a 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 483f860a8b5e2..8658009eba43f 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 55651a28be924..117dda092223e 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 f6de66bb5145b..35f40830681d6 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![], } } } +impl From for TryConf { + fn from(value: io::Error) -> Self { + ConfError::from(value).into() + } +} + #[derive(Debug)] -struct ConfError(String); +pub struct ConfError { + pub message: String, + pub span: Option, +} + +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, + } + } + } -impl fmt::Display for ConfError { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - ::fmt(&self.0, f) + 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 Error for ConfError {} - -fn conf_error(s: impl Into) -> Box { - Box::new(ConfError(s.into())) +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(); - - if_chain! { - if error.downcast::().is_ok(); - if let Some((prefix, mut fields, suffix)) = parse_unknown_field_message(&s); - then { - use fmt::Write; - - 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 - } +#[derive(Debug)] +struct FieldError(String); + +impl std::error::Error for FieldError {} + +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 a9089fba3c539..b6e4cd22789f9 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 66a5079fa85ef..cfe686eb9b01d 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 575c29a6b6f97..8c883445a7984 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 e05de2dc99c05..6f102308f0bf6 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 0f0792fdaa963..38ee84fb76c7a 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 0f60290644a18..582337b47e813 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 139102798c42a..4dc906d00db16 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 27d32f390035d..a828d12370467 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 bc7fb711ed8b8..0d2e1eee64384 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 59bf447a7cd07..3c5b6e12b9688 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 7e96aa36feb45..e4de82ad3b83e 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", -] - -[[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", + "winapi 0.2.8", ] -[[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 4f97b01133402..79317659ac072 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 99ce702839094..9b0db660c9975 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 0fc385cd6935a..b9ea5a64de75e 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 28c1a568a632b..5b7e8c0db744d 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 e3ec60192040e..386e1135df90d 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 630bad07c5b71..123ad94dd09da 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 63a893cc6c795..55789afc1b71c 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 d99490a242d4f..54997735274e4 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 0000000000000..7932c43ebd217 --- /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 0000000000000..f328e4d9d04c3 --- /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 0000000000000..2ae7848f183b5 --- /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 0000000000000..53c634b727ed5 --- /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 0000000000000..f328e4d9d04c3 --- /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 0000000000000..53ad427124691 --- /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 d623ac7e02008..4882416c414ac 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 554b87cc50be1..b77b4580051ef 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 44710b09648ee..b6038f031f3c3 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 d75cdd625f9ec..44f49c080cdd6 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 2d6055eb6c422..5780ea0893777 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 ce7fff0122f1f..a7e72b780affc 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 ffe20ab1c3101..a5373cdcae120 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 e1012f38bba2a..ac5fe38ff4439 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 c7b4313dbf0c9..de7f14ffbd95c 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 61a32fb10e53b..13abb9149da24 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 9ce9a87626a79..f62da157d1b94 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 99787ffd3d395..3e9d5e6a4ca32 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 24e90094982aa..118d39566abee 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 3996d775f55f4..351ea0e4f509e 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 f6f56f7b00e51..0e87679713474 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 73b7467912597..dfca3b023cd58 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 bacc14dc96720..13ed35bc1d5db 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 823be65efe065..5a552e4ae51a5 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 b016d682698c8..a9f54feacdb58 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 0000000000000..c156d394eceaa --- /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 0000000000000..ef9d02abab7db --- /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 0000000000000..06a16162790cc --- /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 0000000000000..728032c47a66b --- /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 0000000000000..ea69308516449 --- /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 d49ae5d8636f5..4dabf313963de 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 367638261746c..542f562b31496 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 05f6038cd2553..1d9d23d30083c 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 80cc7c60f56e5..fec6b7713eef8 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 0000000000000..24de573d0838e --- /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 0000000000000..63d973a9fca87 --- /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 0000000000000..43816c87c1907 --- /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 bebdf89716fa2..481c9b263fbb8 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 8fb6ed5f7eca0..86e46d41e65a1 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 accdf1da9ddc9..dae931541d454 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 ec684bdf71c11..3f2fa3f53ce99 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 a69eb3905205f..93760ce97a8f6 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 e4032ae44b715..d77a2af761642 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 39eb10df8789e..aa884ac6bb1ee 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 5893ae4dcc492..b462f7f41b9cc 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 a5f79b139bc2a..1c8e47ab59494 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 6b8a772e7f0d5..1e8a21283cd95 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 f7854b89ee4ea..30f2bfc8c1a9a 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 fa347d395ef5d..3939914d42241 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 9dffe51e5d7d3..7290cf32e5b60 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 0000000000000..77a2cf3b991f6 --- /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 d0c9b7b5663e7..8d0ab5b99ad51 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 7cecc1b739506..dad66e2ab2ec3 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 0000000000000..f88498655a418 --- /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 c8ac768b60f68..b34b95539190c 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 62876a55dc616..228236f3bb8e8 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 e0153cdd8cdcf..4823d9092089b 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 4ca7f29b34cd0..bfaa5dadfa59e 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 cff3eccbd32bb..8ac2066a6b24d 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 bd845361fa89d..733bbcfbcefab 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 fb51f7bdfcc6b..4acdd374bdeca 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 6b469cdfc4449..235be2d57081b 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 d5e847e718331..77d673fec24cf 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 351ea0e4f509e..61c3a1650097f 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 0e87679713474..4e83e638cdf96 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 77d673fec24cf..59e421c162202 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 61c3a1650097f..b5c2a5dba34b1 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 4e83e638cdf96..9d4aef4cad66e 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 | 60 ++++++++++++++--------------- tests/ui/unnecessary_to_owned.fixed | 2 +- tests/ui/unnecessary_to_owned.rs | 2 +- 6 files changed, 35 insertions(+), 33 deletions(-) diff --git a/clippy_lints/src/redundant_clone.rs b/clippy_lints/src/redundant_clone.rs index 944a33cc3e53f..685d738cbb7c9 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 8bebb5183bc1a..cb9583aa6ee37 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 b4bd5d16b1a68..e5aeacbb56ce8 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 782590034d051..bb5c602d63a09 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 + --> $DIR/redundant_clone.rs:128:15 | LL | let _s = s.clone(); | ^^^^^^^^ help: remove this | note: this value is dropped without further use - --> $DIR/redundant_clone.rs:127:14 + --> $DIR/redundant_clone.rs:128:14 | LL | let _s = s.clone(); | ^ error: redundant clone - --> $DIR/redundant_clone.rs:128:15 + --> $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:128:14 + --> $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 c879fdc3b6aec..08733906b0ed6 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 10588beb263b6..e3589ea0d65e8 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 ab015f8822e1b..f0c1df0143072 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 24de573d0838e..36304e4a0f0ff 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 63d973a9fca87..315e828bebea2 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 43816c87c1907..0c3ff863685ba 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 _ = &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 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: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 36304e4a0f0ff..ba3eca061df49 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 315e828bebea2..adeb43edf687e 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 be9261a47041c..c23054443bb96 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 4e8d5c3bccd47..d2166872d9301 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 a0b8e055f1d68..01ef3ef431c71 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 fb037bbcbf3eb..ca9514ccc7d00 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 4a23edb58aaa4..43ab8a96d861c 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 f83ad388a742f..c7c1180975225 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 0d91051632a18..2d27be499f956 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 71f6c9909ddda..e222a5448c9cd 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 0000000000000..e4cb5316a985a --- /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 0000000000000..7d1e0f26a1ba6 --- /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 0000000000000..d6ebadf04c4fa --- /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 0000000000000..10eabca4b9d74 --- /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 7d1e0f26a1ba6..0000000000000 --- 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 d6ebadf04c4fa..43fc996033eac 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 19fb74b90509d..8328531deff13 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 8328531deff13..bc7dd8534c3b4 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 bd4293662a0a5..b961b7d2d9683 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 b961b7d2d9683..f59245e556cd2 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(','); + + const defaultParameter = Object.keys(defaultValue) + .filter(filter => defaultValue[filter]) + .sort() .map(processFilter) .filter(Boolean) // Filters out any falsy values, including null .join(','); - $location.search(urlKey, parameter || null); + // 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 6f1e9d5f9de28..c413e92ea915e 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 68f38faab5930..4957f73a469a6 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 bc7dd8534c3b4..f470987833e42 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 69ccbeb7b06f6..eb21184713e89 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 e989cde0f3cb0..b882eee8a6526 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 fd04f2ddf7ce4..7e9548984609b 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 95a9fa2aa4763..2b26624b4249d 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 2b26624b4249d..663c2eb2c3794 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 a9d42159c4bac..c582c28cd3cf1 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 30a156c925b07..d5ab313ba0e6f 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 514706d64c8c0..0f0e3f2db925c 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 c0d2c835d63d4..a38045cdcd160 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 5db73a7b8ead4..dffc23177d199 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 4648af231a41a..a65ac4d46deb5 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 68272e1a77a80..d014534cee91d 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 222b0cc092144..d53c6de545145 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 0000000000000..30d06a2cbc712 --- /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 0000000000000..5722621e83a15 --- /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 0000000000000..3356f4808608e --- /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 30d06a2cbc712..f277adfa94d02 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 f277adfa94d02..da139cdde92e0 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 da139cdde92e0..18647891ac6b8 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 5722621e83a15..cc507b8d658ce 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 3356f4808608e..e8b2fe5c3847a 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 18647891ac6b8..8e9234bba3c86 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 92913ddc4aa53..b5686e390ad56 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 4ccda15068bbb..913ef7644aaed 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 8b4613b3f6ec7..1d36f4b3c7b2a 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 a90df03c04ffc..56867f75b07e8 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 913ef7644aaed..90c6429ff3801 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 90c6429ff3801..2e6108d6b2427 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 e05b88e4cd085..addd3619a8432 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 f8d4c0bd912d7..565bd96cf30a2 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 b968894f87039..3627076b2af1c 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 c3d106cd1096e..2850a632fc774 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 b6f0de7e504f0..1138d1163a4a9 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 e872d190c8216..f77d7821539fa 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 a7d78a95d59cd..de29af78ef30c 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 7329e508106d9..ec21f3bb54f43 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 5a2df9f6c5d91..068b47bd09def 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 bc178b7e1319d..db88b1cbecb06 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 8e1a1710a6ce2..ebbc7fea328d9 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 148d1cae51f10..3dc83a40780a0 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 5d3e800caddfe..9f4d0ef1bf917 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 8a32750e3c92d..706f9a89cbb36 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 b50682ea00c44..ef45e97d1de14 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 780d2d040f124..ae87afc485ed8 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 d3ad26921bffa..4d168bfeab93a 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 2c1a42a72c149..e02c1c57230ad 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 dd2615ab25cf1..c92dd509ebb2d 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 5462784c6ac8a..b3489714380aa 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 f69d6bd5255df..cc09b17eb8951 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 b27d3bc100283..0bf739fe2d16b 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 825090c7c122e..2d796a24fec56 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 6b5b31a1a2ef1..4824067722890 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 cd9f1826e59bf..cb9b0c01862bf 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 0a07957386c23..1bcaa33a049e1 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 62a832caa67b6..cee937e07e17f 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 46565a97f0059..08e6de5dc19bf 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 88d3b0e749001..bbd395d50ef22 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 f578c98da1534..3e74e2a02d038 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 42bc6de0c7dda..45c6760f89e14 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 55fb3788a8b1a..8e3fb99bc7cbb 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 50a86eaa68f7d..8b163a142a595 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 9288956f51306..f214cabef67ab 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 b2b817e0f4c43..d9b28a4f7c091 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 0ef0ac655d394..f456c11924e5a 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 ef132b7961177..a29c0918a6dd8 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 4d8722356144e..2062f3ec23a04 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 466beff9c92df..4e267ba9a3b48 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 a58dfda798855..01a83e5bf343f 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 d626656c78f95..d82484b46d3ff 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 4950c47ddeb80..9061c9aa40495 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 6b1e8edb7bd2f..b5e4e4720377f 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 6dee4d5b4b624..a6a34620e92d6 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 26abc9edb5e44..16f9e47e8532c 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 8fd77913a3fd9..f4357c1d592d0 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 7b107db39f022..939b6ac36bde8 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 4367a12f820d5..b6208201409f1 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 8c7543cf03b39..fb2161312098a 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 2e3d7fc35de9c..f9aee0b7846d3 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 d862abc34e0bb..702edccdbad0d 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 da6fc46e42874..30bfc72de1793 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 d8b89061ff895..0db8201a1325c 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 e7fb97d4fbc8a..7c567bb81d88a 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 a0fe353bcf75c..975a5a62ad5ae 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 bf576e9cbfb34..2874513c049b8 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 df42d88eff00d..26f39734a5124 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 8f2cefc430434..b888d965e8d7e 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 71d83384f3a05..e44efdebc4718 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 ca6970b27f16c..4ee26e088ce35 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 13d1cfd428185..33ec78e9a4160 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 d792aea11dfa0..b470e2ed2eab9 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 ab9b375dc03d5..d8dde0236eae1 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 ab9b375dc03d5..d8dde0236eae1 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 eac52d1b5de57..0f87d6e2d2c93 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 755caa664d59a..5e3b12e510b84 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 faccfe9db12a6..b81604b0372b5 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 831323089e7f2..9dd376df2b48a 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 2692303d31382..6dd1e066aebdb 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 6e5bbe8f2aaf5..882468b0f5f19 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 554613a30a9ea..0c8eebf04b5c0 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 d6245758f9d09..b2feb48a839b7 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 c1ac499f7c601..693a06bb5590b 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 ea0535d076b81..4d5c70f19a064 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 c163ae061dfc9..1c6a7d5c04e0a 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 d7474f3571912..50c0eb1a81081 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 74978ae8006d7..91a084f2844dd 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 d84a5bf8d4de6..d768af1f48c97 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 30415e3b94dc4..d82a736963a2d 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 49446d715abe2..9b1f052867e0f 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 7c29bb08e64da..f59ff456bf298 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 c068d5e17c33d..e293bc33c8a93 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 9d16af76c6af9..8998786de7eaf 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 e0e2cac30a286..589eab5cdfc54 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 4643e09e27028..73ec48643e063 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 dcbed5a4d997f..ce5d19a8b6e8e 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 3a976d235276a..0615817ec925d 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 852f48e32d678..187714c75fb95 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 fe4209e99b2f5..55a7c2c21d990 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 92f7b3f777a19..b3ed0932ab590 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 be378c42f95d6..dbbbf24085e40 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 eff782f8bf104..78ba8e11c575c 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 70015fccf9ee5..ec981ad97e3d3 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 e2e35360cb36b..6360874f62365 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 bc07db5b38ed3..20d28a968c917 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 921801138a9b6..329cdc1f06ba1 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 7633316e0f877..516d99a3532af 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 1e6ec5e667aa0..8c4f5d954a975 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 1e42e1fbabfeb..6a726941be893 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 f10f2bcf2a8a0..64edfc32504e5 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 fec6b7713eef8..73e056c722e81 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 91b5805aa97ab..e2e4d6477c9f1 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 e1c0fa3f7fd39..4d1a6a1ab98d1 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 6f4917fd149c9..66d5a1250360d 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 f723a55f77f81..08a536a28443c 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 61ef6e27f3228..83ba68382efb8 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 ba3001db7a5f4..ec87674b100f3 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 f69bc131898f7..6ffa401d76172 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 eae36c27729e8..de1f86cb855c6 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 628282509c1a5..46edf0921bf2c 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 dcb5061371f80..ac83b67fde3aa 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 384060e6eae50..53fcbf3c49b46 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 7814f5b54036b..a8fd28b84b3a6 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 0394457fe1708..88ea39bf9083f 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 80deb7cb9f24d..eab464800ca97 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 693c9b553c562..03142165057d2 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 789e14a302f6f..1f7a849b18083 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 670599b0dcf59..3cdbfaa162614 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 6bea8c6747797..7eff614d17c69 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 9386618c123ef..08fb87cb306e0 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 6b2537a96c2af..ec3386933a61b 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 e9116fc59f10e..aa16f9da037d1 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 b152839945765..aeb6f118bedeb 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 ef64762291024..ec3ae12094254 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 826e0d0ba888d..bed88244eea70 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 62574e2c8ceaa..8e4cd82cec306 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 1370dd2df4dae..50c1fc71a3f9e 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 cd344dd123897..bd1bb428f2bbe 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 1432fdcff77ad..aa5d7b7e49146 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 fd3569cf36254..22f904e3fd9e6 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 34fbce0524b21..ada64f89e6d27 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 0c246268499d9..a3b9c2b744c98 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 ea30c1fda6fce..4bacf9efdaea2 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 7a3d33e5be5a2..723870ccc8040 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 86a7bd7b62735..816950110b201 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 bdb4710cc6972..f2a9694f99e5b 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 1d9564ce225e1..3a295af55eac9 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 e102df6259989..f13a5275e31b5 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 b87c15bc12635..6014d723a2f40 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 165cabd829890..19380ad00dcd9 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 8a2158d5a8416..cea1b65b52031 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 d77a4dd8e0b00..1bdde69f6f4ef 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 dfed3a29a03e1..89c6a72f3392e 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 7d1de05a5c836..f94a82d217155 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 c2f216a8911c4..11f0de07c62f3 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 971bd5f0c4a86..e54575dd3b43a 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 4d98666190d67..f8a66f2ad3e95 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 7e9548984609b..7f79b8f87dddc 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 4f8c5ff58b585..4e9d77ea156af 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 2e6108d6b2427..f4554fbcf9bc1 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 7f79b8f87dddc..05b349862745f 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 ec21f3bb54f43..467805d90ffec 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 4762b354392b8..d03480c21084c 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 4823d9092089b..a96cc1b090c92 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 c919b4de65dea..fcbf08988908a 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 b1baf462c0f88..934deb6636201 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 e113c3d6cd6b2..978aecd24b3e8 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 a521fb868607a..1f5db2d51296b 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 fcbf08988908a..58e62d1f3d377 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 934deb6636201..31a94cb10e8a4 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 1f5db2d51296b..19be5fc738915 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 a65ac4d46deb5..76fd81a25c666 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 d014534cee91d..2091134869084 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 0000000000000..84ae54f401e58 --- /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 d53c6de545145..8b08861bc1d5a 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 35f40830681d6..1bdb5e424183b 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 0000000000000..1824c8a3127d2 --- /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 0000000000000..261b937e72e97 --- /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 0000000000000..00dce391be0bb --- /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 0000000000000..218950f9684c6 --- /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 0000000000000..707a3796b5614 --- /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 84ae54f401e58..0e23b39a14e1b 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 76fd81a25c666..69ac2c893d9f4 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 2091134869084..0c51996b62539 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 0000000000000..a60e2442fa29d --- /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 0e23b39a14e1b..0000000000000 --- 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 8b08861bc1d5a..202b4709ad41d 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 1bdb5e424183b..cf0da266dc974 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 0000000000000..86663db68f24f --- /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 0000000000000..10be2751a8678 --- /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 0000000000000..66fc81663145f --- /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 0000000000000..0bd43da21e244 --- /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 1824c8a3127d2..0000000000000 --- 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 261b937e72e97..0000000000000 --- 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 00dce391be0bb..0000000000000 --- 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 b6038f031f3c3..28b6e7aa8248a 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 e5bb906663c56..d9a1e76c077a8 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 218950f9684c6..0000000000000 --- 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 707a3796b5614..0000000000000 --- 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 a60e2442fa29d..604448d2e9c93 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 | 177 ++++++------ 4 files changed, 145 insertions(+), 316 deletions(-) diff --git a/book/src/lint_configuration.md b/book/src/lint_configuration.md index 4c888b63793b8..4fa6b81c0027b 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 604448d2e9c93..a133bdc2edf04 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); - - match &local.kind { - LocalKind::Init(expr) => self.visit_expr(expr), - LocalKind::InitElse(expr, block) => { - self.visit_expr(expr); - self.visit_block(block); - }, - LocalKind::Decl => (), +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", + ); + + 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), - _ => (), - } - } -} - -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), - _ => (), - } + }, + // 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), } } - - 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 66fc81663145f..62cf51258160d 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 0bd43da21e244..c98c6fefe0108 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 + = help: try refactoring your code to minimize nesting error: this block is too nested - --> $DIR/excessive_nesting.rs:158:7 + --> $DIR/excessive_nesting.rs:159:7 | 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:158:19 + --> $DIR/excessive_nesting.rs:159: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 + --> $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 - -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 + = help: try refactoring your code to minimize nesting 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 a133bdc2edf04..5ade713f81642 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 0000000000000..967b3af3bcad2 --- /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 62cf51258160d..3e3ac7c923acd 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 c98c6fefe0108..524282d11f781 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 5ade713f81642..f1aafa3cbc380 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 202b4709ad41d..189096d7ba993 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 0000000000000..b01e482e48595 --- /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 0000000000000..1f069437dfe5f --- /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 0000000000000..02fa2cdcf9fa8 --- /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 3e3ac7c923acd..745031db1eb9a 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 524282d11f781..f1db396fe4808 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 4fa6b81c0027b..3c955c9e5748e 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 f1aafa3cbc380..1d68d7f94780d 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 cf0da266dc974..69143c3c72601 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 b01e482e48595..e8b115a0f7c6e 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 02fa2cdcf9fa8..e69de29bb2d1d 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 745031db1eb9a..5e436b97ee836 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} | 223 ++++---- .../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, 622 insertions(+), 233 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 1d68d7f94780d..1c6cd27789da2 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 0000000000000..e60ac978cac97 --- /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 86663db68f24f..0000000000000 --- 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 967b3af3bcad2..0000000000000 --- 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 0000000000000..87620fe91bab1 --- /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 e8b115a0f7c6e..0000000000000 --- 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 f1db396fe4808..0ec41fbaa0783 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 - | -LL | let x = { 1 }; // warning - | ^^^^^ + --> $DIR/excessive_nesting.rs:100:17 | - = 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 + --> $DIR/excessive_nesting.rs:173:13 | LL | loop {{{{{{}}}}}} - | ^^^^^^^^ + | ^^^^^^ | = help: try refactoring your code to minimize nesting error: this block is too nested - --> $DIR/excessive_nesting.rs:173:13 + --> $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:174:19 + --> $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 e69de29bb2d1d..0000000000000 diff --git a/tests/ui-toml/excessive_nesting/excessive_nesting.rs b/tests/ui-toml/excessive_nesting/excessive_nesting.rs index 5e436b97ee836..432c4132b57b7 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 1f069437dfe5f..237cc6c4a90b9 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 28b6e7aa8248a..5ec6f3decc3c1 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 8c883445a7984..e600dc58c9da3 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 a38045cdcd160..cdaf8985d5e72 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 dffc23177d199..4fe02a9cef877 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 a65ac4d46deb5..a53567f25c48b 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 0000000000000..2e14f81f8e44e --- /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 d014534cee91d..f82118e569f0a 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 d53c6de545145..2f5932104c19a 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 0000000000000..4c2d84be5db29 --- /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 0000000000000..99e38bcc1a2be --- /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 2e14f81f8e44e..ca2023ee0be8a 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 b6e4cd22789f9..2a3d86988bb04 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 2a3d86988bb04..b6e4cd22789f9 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 b6e4cd22789f9..2a3d86988bb04 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 ca2023ee0be8a..13e938327bbe9 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 4c2d84be5db29..ac786f68c123d 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 99e38bcc1a2be..fc2fc5f93b13b 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 13e938327bbe9..a1e44668e1adc 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 e600dc58c9da3..311f6dbc696db 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 cdaf8985d5e72..799b6ffeba6bd 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 4fe02a9cef877..286d208b25bd2 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 0246c8622ed3a..b1980b1b523fd 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 955e1ed263408..7be2cc0ca9306 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 15ff8be0fd942..6270d26131323 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 9c60edb179415..7a4b9a87aeb47 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 4cb4183002339..f76fa76f0764e 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 30f2bfc8c1a9a..954145fc4e64b 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 3939914d42241..067a3109afb97 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 7290cf32e5b60..1819d108c5740 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 f4cfc92e1cd02..0000000000000 --- 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 92611a9b7df4a..0000000000000 --- 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 87620fe91bab1..df17974de033c 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 432c4132b57b7..d771cb9b55e14 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 237cc6c4a90b9..0000000000000 --- 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 0ec41fbaa0783..a9fb159ef2a79 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 10be2751a8678..0000000000000 --- 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 c03fbe9d275f3..97d6a8353a068 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 13a2770342781..f970a32726b9a 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 2f5932104c19a..2dbdee977b085 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 467805d90ffec..25b6f40762dc4 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 1bdde69f6f4ef..55329ee843d5c 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 89c6a72f3392e..bab316fa620bd 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 f94a82d217155..f3a4bf925dd9d 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: 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 14 previous errors +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 c7a76e5f9077c..b9dda49ca4124 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 2f5932104c19a..163844f744804 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 890bf0b0a7eb2..48ca2f6d14375 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 54037a6499787..ca41d1378aa09 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 08ed8a63e1add..d3d80ff41008e 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 0fd49e7c81583..e74476044d9b2 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 2766949232932..a577fd79899ec 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 0e511fb4c7a75..7f748fcf4c2b9 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 309d2157b76ee..da7196ed0a81a 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 08733906b0ed6..592a53f3a8198 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 e3589ea0d65e8..f2e48b1c4a6a7 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 c225398ad2a8f..bbe4149fe2ab2 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 10d39762043ea..18b2a33469da3 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 0000000000000..69d7f2f395fff --- /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 0000000000000..a74ce731577d0 --- /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 942453498cdde..caa3463b86497 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 510eca21f71bc..3a4d66c5ba541 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 e69de29bb2d1d..e6396de2bb7e2 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 caa3463b86497..ac94820b40b0c 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 e6396de2bb7e2..f121159ca3e85 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 ac94820b40b0c..57ec3a1f1e63c 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 3a4d66c5ba541..9b1619baf0e6c 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 f121159ca3e85..243a5cf5369ad 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 1c6cd27789da2..4c8ea1ed18d3f 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 4c8ea1ed18d3f..d04d833e6304e 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 22ff5ef585976..30842cd651070 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 151c7f1d5d254..ba66af6237549 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 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, + } + } } -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, +/// 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 c7c1180975225..068166bdeb24c 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 6f102308f0bf6..e1b1a6f7184a4 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 7b4ed77e8edb9..78b14dc7abb03 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 3e74e2a02d038..992308564463b 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 45c6760f89e14..0d7fe3c03147b 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 ddfe66d675f91..4ad23e0b9db86 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 | 87 +++++++++++++------ tests/ui/map_unwrap_or.rs | 29 +++++++ 2 files changed, 88 insertions(+), 28 deletions(-) diff --git a/clippy_lints/src/methods/option_map_unwrap_or.rs b/clippy_lints/src/methods/option_map_unwrap_or.rs index 4c6328481e438..e931c6277f4ef 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,14 +114,19 @@ 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)); + 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); } @@ -107,32 +135,35 @@ impl<'a, 'tcx> Visitor<'tcx> for UnwrapVisitor<'a, 'tcx> { } } -struct MapExprVisitor<'a, 'tcx> { +struct ReferenceVisitor<'a, 'tcx> { cx: &'a LateContext<'tcx>, - identifiers: FxHashSet, - found_identifier: bool, + identifiers: FxHashSet, + found_reference: bool, + unwrap_or_span: Span, } -impl<'a, 'tcx> Visitor<'tcx> for MapExprVisitor<'a, 'tcx> { +impl<'a, 'tcx> Visitor<'tcx> for ReferenceVisitor<'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_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); } - walk_path(self, path); } fn nested_visit_map(&mut self) -> Self::Map { self.cx.tcx.hir() } } - -fn ident(path: &Path<'_>) -> Symbol { - path.segments - .last() - .expect("segments should be composed of at least 1 element") - .ident - .name -} diff --git a/tests/ui/map_unwrap_or.rs b/tests/ui/map_unwrap_or.rs index cb25d8567aa01..0cd49dd7760d6 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 08e6de5dc19bf..e02b8f62b3dd0 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 d3f3c626bbdfd..0677e4d78c8be 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 0000000000000..bc9ecb1e05abe --- /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 0000000000000..9b610fe3d1103 --- /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 0000000000000..1bd2b38a0e787 --- /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 0000000000000..b0de50ed92846 --- /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 0000000000000..33d3bada6e23a --- /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 0000000000000..1508080a24322 --- /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 992308564463b..0000000000000 --- 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 0d7fe3c03147b..0000000000000 --- 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 4ad23e0b9db86..0000000000000 --- 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 8e3fb99bc7cbb..0000000000000 --- 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 8b163a142a595..0000000000000 --- 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 0000000000000..548b799de44e8 --- /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 0000000000000..5bba0e635bba6 --- /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 b7e80af501547..17a56cdfc2f3b 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 680b6fa5b55f5..8615899e9792a 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 329cdc1f06ba1..1935ccb94bd58 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 175e2b382e3f6..bf5e018ce922b 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 ba66af6237549..621f0e0adcaad 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 068166bdeb24c..1231fefb180c2 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 bc9ecb1e05abe..dcef634031143 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 r = &t; - let rr = &&t; - - // This case is handled by `explicit_iter_loop`. No idea why. - for _ in t.into_iter() {} + let mut t = T; + for _ in &t {} + let r = &t; 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 9b610fe3d1103..bc048ed302bff 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 1bd2b38a0e787..fa89b884fa0fc 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 89540703bcf60..2ba78f99569ab 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 4e1a6cd4d7355..e53a9877b20ca 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 986ffcad883db..7bc901e4e7f1e 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 bf5e018ce922b..93d6b80864699 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 621f0e0adcaad..f3347e33077b7 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 1231fefb180c2..529189b52acda 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 9d9341559ac72..f7b3b2358a0bd 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 26ae4b409c795..cb3bda961333b 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 6424ac31d9f68..de911f7a02803 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 7945275393c04..da02de3e6678f 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 704c34c32bf74..3a7f1e034f310 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 ddb8b9173a537..9151cc6332004 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 9de4b56b77b56..28e041dee0dbb 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 b5686e390ad56..958351ad81bb7 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 b930b2c8dd7b8..f4e56489b096f 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 4ccda15068bbb..0dab0126e6c1b 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 f8978e30a8e2b..dced9fcf9abd3 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 c0d2c835d63d4..67369288b70b0 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 78b14dc7abb03..4132a6c4b18de 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 ab3976a13bdbb..9855085216feb 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 03d1877d6c644..de56a6f82757d 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 b0de50ed92846..746ef813c0481 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 33d3bada6e23a..fba230ee0eeaa 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 1508080a24322..94a264dcea8d5 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 799b6ffeba6bd..3dbda478b2fcf 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 6270d26131323..f1d1355123ab6 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 e18064b7061bf..0000000000000 --- 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 d63a836e73d6f..2cf15adda01a2 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 f76fa76f0764e..cbcd11debfd76 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 64ca52b010a7e..0000000000000 --- 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 867516661a539..0000000000000 --- 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 a238e7896fc6b..92821b6ecbbab 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 954145fc4e64b..f1b25dc094ef6 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 067a3109afb97..4af511c344c4d 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 1819d108c5740..156a8f96b5026 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 49c0e4dc7eb10..debc7e152e739 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 b60042923ea18..16140fd107917 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 584c428932fee..880673eef3e40 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 0d00f2c16e7d7..8a330b35d6938 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 b6ceab26006c5..874c173f70977 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 22ff5ef585976..882c5653c96d8 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 0000000000000..1568c3533a086 --- /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 52f7fee47b616..066b2657d0337 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 b0d89e038aa8b..b462b20e04c67 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 d8f1ffb21ba67..b12df2786520e 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 94f075ed09cce..5d849bfcf818e 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 a9f18782e58b7..2a3867ac8fc0e 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 0a70317c4d408..704d09fbad3d9 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 169589f6d4e70..7da12d89a610f 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 670eef6a21d7e..d6774c0359842 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 72851be635d0e..c0483fd737489 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 31522d4a52519..f4dded365fba9 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 3bf3deb9b9182..118346348564b 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 10107dc8f86d3..3a25d53a5d080 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 43bf8851fc620..4714a0daaa68a 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 8302cec45e781..c4116cd8520c0 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 5913dcf41cafc..8f51d0ee508ff 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 c6514a559340c..e305e1d7a8710 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 2c85b68df632c..7c52959d3b51b 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 c687bae1acc52..4a1a9e8a60aee 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 b402052882adc..21cd9d337cdd0 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 82095febc194a..b203252f0a14a 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 5a9cd32380a19..84e0af3f0d0a9 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 e937c49f3897f..5889f04439ff4 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 78cb55096ff0c..9ab68b641f137 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 c80ff671a5db7..f8ca92ef0b34b 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 bc78694aa6806..47ff87bea0ab0 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 05ef4e25f7f87..4df1c28ac4871 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 53e62760bef4d..1869301d2242c 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 55918a5bb1196..a78aec74a7b8b 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 a72d87bb7ba96..649495dded7df 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 ca81808a8636c..7963bf0f3a6a2 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 77210ca7a9da1..7ce9e855b5e05 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 5de8fe8cdd7b0..d3ad36e40b53c 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 e51a90d6cfd24..36142deb3092a 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 df5bc8420d57b..dfdea100c8fd7 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 660dd32397922..5b9f48a961caf 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 58167f4446dba..3b9b029d35467 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 704cfd9669ac8..a4d8a74167e38 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 f62da157d1b94..c321b08909f1f 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 9519f6904cb1e..8d70934476cbc 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 2c22abd7e4b14..fafee6a0d41d5 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 a011ff976448b..6a9006c477999 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 b5c2a5dba34b1..46241afec9472 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 9d4aef4cad66e..1eada4f992ec5 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 b4097fa96045e..b78c1fd06d44d 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 bf1911881c8a9..7d0e556528fa1 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 a6c465d4fbd11..88bfe8af73373 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 fa906374fb3ba..1476aea439ff2 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 6663520da8a1d..59a38425b0680 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 6c8efd2ce1804..e48b19cb19db8 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 8d0f0c258dd26..35497a01ec220 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 b7e80af501547..a1a27ca50515d 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 680b6fa5b55f5..237fd9540d6c3 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 55a7c2c21d990..d3d856c2c659c 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 0000000000000..7587a397dc9e3 --- /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 0000000000000..3006995e09da1 --- /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 0000000000000..bbb2a035668ac --- /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 73e056c722e81..e4aa0937b9779 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 05802a2c865fb..294f2aa48f1c8 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 cd5b576fa07e1..a165368ab17dd 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 e1e30114081ef..14a6b98d07d14 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 92d1d8ef911ef..3ec2298f828ae 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 2df87a26d6d15..95e184b1de6cb 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 df6233b9afd63..4fa50dcc11b6e 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 481c9b263fbb8..d1134de5ab475 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 86e46d41e65a1..d144086e791a3 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 23f08103f358f..e9ea3f2e6886c 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 a9faf12cd5a11..75ed143446c9f 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 574671d03d1c4..9ac77409f7919 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 536b589de54c0..6d1fb29646329 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 dae931541d454..a63ba5809e4bb 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 3f2fa3f53ce99..631f9091672d7 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 93760ce97a8f6..717b603c496e3 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 bf3e692202c36..f739deaf58ea0 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 892a21d9d298e..88dde02b38b72 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 1b480f3157f70..b89fde35fcfa6 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 d77a2af761642..343e0d04340de 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 aa884ac6bb1ee..4d64eafe590c2 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 b462f7f41b9cc..f6ce666bb4ffc 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 2c0fc3e3fd83f..c2895718a1aa4 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 77a2cf3b991f6..a54e658bf23a8 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 8d0ab5b99ad51..f296c6c4d1cd6 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 dad66e2ab2ec3..ef90151324043 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 29d56f852edde..b7237069dc5ce 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 56bbe2574d426..658312e87e47f 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 a96cc1b090c92..c0856427eaef7 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 2e512b47f1236..723fdd7e93e3b 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 9564e373c246d..3c5ca1762fe49 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 9f1289ccba0c0..52b0e99a1d3e8 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 3d271104361b6..fc75f548a1bcc 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 41cf19ae685ed..79c890d644cd4 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 89fedb145f88b..d858701ae8ac5 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 16c2de760e55f..d18c65a77095b 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 9d9eae1d90330..c80756c44955a 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 716d9ecff89af..8a004b77e941d 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 8ec35ba4eea7e..4ce6e86669532 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 efdb91b2402b7..07d60fac082a7 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 a1f193db555ad..d7b582fc8bdd7 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 de40e93674713..a88d7f51ac0a5 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 87f66d26c4678..f6029eee441d8 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 e9563b8a60a8a..5d2c5b11658e2 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 c2f4e3117d2ef..03a3e3f95ba42 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 4acf5b5fa2d1b..ec0512ce210b6 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 9aef9dda6f685..54189f8d28606 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 4c888b63793b8..2777119984e41 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 faac63404199c..d4df6f7aa2d09 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 43ab8a96d861c..3517d2f64f05f 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 35f40830681d6..3952ec7389f7e 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 0000000000000..787620d865cc5 --- /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 0000000000000..cd495c884a43a --- /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 0000000000000..a5a09c322e13d --- /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 b6038f031f3c3..22ea45d06222d 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 a23aba9164a5c..802c3ec39b64b 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 77564dce9eb48..ebb8e296f4646 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 066b2657d0337..52f7fee47b616 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 d771cb9b55e14..25f0d0d6230a7 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 a9fb159ef2a79..1a7311b33e869 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 790d725907f32..8f84c5596889c 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 1568c3533a086..8e27d3a400983 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 d3d80ff41008e..41055c168fcbe 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 e74476044d9b2..f56cee3a364a0 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 a577fd79899ec..b4623df690959 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 7f748fcf4c2b9..b52e5c32c8a99 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 8e27d3a400983..b118516e09b5e 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 7587a397dc9e3..2abde2ad42229 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 3006995e09da1..1608d261a360a 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 bbb2a035668ac..4236b0053ebd5 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 b52e5c32c8a99..618fbd4faaf4d 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 2abde2ad42229..bee579be1bf57 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 b118516e09b5e..dbffbd6f0d38a 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 05b349862745f..bcfac527c8a4e 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 | 163 +++++++++++++----- 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, 243 insertions(+), 51 deletions(-) diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index 2f5932104c19a..3e8d6af530239 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 2a42e73488f19..4e1ffc2fe378a 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) { +/// 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_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); + + 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 + ); + } } - } + ); } } -} -impl<'tcx> LateLintPass<'tcx> for RedundantClosureCall { 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 61aed2733fef6..1a2c1e592619b 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 56b2866353918..fec4665218970 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 8a1f0771659b1..351da54ef314e 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 4e1ffc2fe378a..d979087a6d7a0 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 5a3d12fd790ea..de29d99cf8d00 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 2bed14973caa7..bd1d4a152aebc 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 a3cec8ea3d554..d27cc460c44af 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 22c44588ab7af..98979f7477fbb 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 8a330b35d6938..5a03d768fee7e 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 874c173f70977..03c3e153a978e 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 fd10a9302c05c..9b8edc5d77e2b 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 0000000000000..e957b6fec6820 --- /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 6962299e4681e..7b5413647c7e1 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 bcfac527c8a4e..c6d0b654f57b6 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 c11835f56961d..2bc872e07e802 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 0000000000000..b33c569d31811 --- /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 0000000000000..712c166423503 --- /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 5a03d768fee7e..27a5fc06b0702 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 03c3e153a978e..1c494468226d2 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 9b8edc5d77e2b..463e4a429d13b 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 e957b6fec6820..0125b576f43a3 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 0125b576f43a3..17a2ebe93ed85 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 b33c569d31811..386633161feb2 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 0000000000000..ceedab9c0da4a --- /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 712c166423503..0000000000000 --- 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 27a5fc06b0702..2d62bfd4f99b7 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 1c494468226d2..769774b27c4cd 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 463e4a429d13b..dcf1c6f64a4bc 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 0000000000000..bbe7fc540e927 --- /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 17a2ebe93ed85..0000000000000 --- 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 7b5413647c7e1..c84d8d8d1f0ff 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 0000000000000..06a144f2218ce --- /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 0000000000000..0114ca7501432 --- /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 0000000000000..33100119ca5b0 --- /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 0000000000000..541f5b10051a6 --- /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 2bc872e07e802..c546d95eb464d 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 386633161feb2..134c17c553f3e 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 0000000000000..4b887617058bb --- /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 ceedab9c0da4a..0000000000000 --- 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 16dc5dcef42b5..1812d50ed1bc0 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 bbe7fc540e927..cc027b6f4988d 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 c84d8d8d1f0ff..f050782a16dd5 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 33100119ca5b0..4326c7159c832 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 541f5b10051a6..d9a27628ddb22 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 134c17c553f3e..85608d030edae 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 4b887617058bb..cd8825634c319 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: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:58:4 + --> $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 cc027b6f4988d..316c2bf122cb5 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 f050782a16dd5..0a581e0ab9b19 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 85608d030edae..c5e03468ef9df 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 cd8825634c319..66a63f6575656 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 1812d50ed1bc0..b2e11d8de677e 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 316c2bf122cb5..d49bb0ca6e291 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 2d62bfd4f99b7..8624fa136e719 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 b2e11d8de677e..9e8729a1afec6 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 769774b27c4cd..8fd8705b445d0 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 0000000000000..2ab1f66946062 --- /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 dcf1c6f64a4bc..2fa95e2b447cc 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 0a581e0ab9b19..f6c7c1fa065a0 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 c546d95eb464d..79af9cc9ac0b0 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 0000000000000..cd9d0c8a67a8a --- /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 0000000000000..d57df8596fe56 --- /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 8624fa136e719..e8337c3b6d0b8 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 8fd8705b445d0..523faa302dc70 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 2fa95e2b447cc..7144772479065 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 2ab1f66946062..0da953e691776 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 0da953e691776..87daa2e7da0af 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 87daa2e7da0af..d638279b5d166 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 d638279b5d166..9c0cc978a391f 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 e8337c3b6d0b8..85fddc970473f 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 9e8729a1afec6..d87938812186d 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 79af9cc9ac0b0..d8ce0e2f55d45 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 d87938812186d..085dff8e63bab 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 25b6f40762dc4..2a594e750b9b2 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}]") + }, + SuggestedType::SliceRef(Mutability::Not) => { + format!("&[{args}]") }, - Mutability::Not => { - format!( - "{borrow_prefix}[{}]", - snippet_with_applicability(cx, span, "..", &mut applicability) - ) + 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 b6e09ab319086..34bd2233440bf 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 fa9e1a996139d..fa8444937b6b1 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 e0361acd95607..3ce482006e949 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 31a94cb10e8a4..bf44bcb564ecc 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 978aecd24b3e8..b2af4bf095373 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 19be5fc738915..0ac0b901df446 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 915ff4fb079d2..1671987cb673e 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 e926f8c529df3..48509b32f1092 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 8aa3c3c01f818..8f08ac8c3ff43 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 88f08bb991b8d..2baea06f84ba9 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 d3438b7f51a2c..9eac94eb8d975 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 b2cc497bf433a..b38cf547dc5fb 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 55329ee843d5c..fcdc917c1b139 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 bab316fa620bd..0404d8cdb8421 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 f3a4bf925dd9d..33d565b2d5250 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 dbffbd6f0d38a..ad5c3e1dc8229 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 bee579be1bf57..8fd945f1a54c7 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 1608d261a360a..04868299a5484 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 4236b0053ebd5..5cb42c36921d2 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 - | -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 + --> $DIR/needless_if.rs:30:5 | -LL | if has_side_effects(&mut x) {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: you can remove it: `has_side_effects(&mut x);` +LL | if maybe_side_effect() {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^ help: you can remove it: `maybe_side_effect();` 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: 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 4 previous errors +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 0000000000000..917ef2126f512 --- /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 88cbefbb5d3d5..f24f00ef6a7f9 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 0000000000000..39b30b7769db8 --- /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 0000000000000..9ae50517a3ea9 --- /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 917ef2126f512..0000000000000 --- 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 f24f00ef6a7f9..9d7b607ec7bb8 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 39b30b7769db8..3572f4965ef7f 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 523faa302dc70..62317dc60ebfd 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 9d7b607ec7bb8..6eb97227e0acf 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 6eb97227e0acf..7a7d5a588b00a 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 3572f4965ef7f..181e4a06664b8 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 0000000000000..5f9881b2ae34f --- /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 7a7d5a588b00a..cb82aef1ef0fd 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 5f9881b2ae34f..414d4445caeb6 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 cb82aef1ef0fd..a5c55a42ea551 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 181e4a06664b8..9a82d7e58ea6a 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 0000000000000..8696048d33249 --- /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 9ae50517a3ea9..ae41634495b34 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 414d4445caeb6..00d7f186fc415 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 9a82d7e58ea6a..0c8a70fedb9c8 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 8696048d33249..b59dec7d48a51 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 ae41634495b34..c46204f7a99eb 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 00d7f186fc415..c5e3cd1657bea 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 a5c55a42ea551..5e42123a8dada 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 0c8a70fedb9c8..9a9c659b23250 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 b59dec7d48a51..55a210bdb985e 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 c46204f7a99eb..80f72ce3cf29d 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 c5e3cd1657bea..b8b5a612da13a 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 85fddc970473f..abc35e8546f88 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 5e42123a8dada..4686adda68349 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 55a210bdb985e..a388a7f83d2d9 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 80f72ce3cf29d..fe557957dd9f8 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 b8b5a612da13a..60499fe700bcc 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 9a9c659b23250..54160a27cb29f 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 0000000000000..ac3a84934afeb --- /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 0000000000000..abc789ccda4b0 --- /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 4686adda68349..66789e6137a92 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 54160a27cb29f..56d3c16a5d27a 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 a388a7f83d2d9..9733993d6191a 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 fe557957dd9f8..775d744c13e7e 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 60499fe700bcc..622743f8c8556 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 | 91 +++++++++++-------- tests/ui/unnecessary_literal_unwrap.fixed | 15 ++- tests/ui/unnecessary_literal_unwrap.rs | 15 ++- tests/ui/unnecessary_literal_unwrap.stderr | 87 +++++++++++++++--- 5 files changed, 163 insertions(+), 61 deletions(-) diff --git a/clippy_lints/src/methods/mod.rs b/clippy_lints/src/methods/mod.rs index 66789e6137a92..912cce39e2ea1 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 56d3c16a5d27a..fe6b86b34f5e2 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; - }; + } + } else if is_res_lang_ctor(cx, path_res(cx, init), hir::LangItem::OptionNone) { + let call_args: &[hir::Expr<'_>] = &[]; + ("None", 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()), - ]; + let help_message = format!("used `{method}()` on `{constructor}` value"); + let suggestion_message = format!("remove the `{constructor}` and `{method}()`"); - 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}()`")); - }, - ); - } + 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 9733993d6191a..d622c984c5276 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 775d744c13e7e..926265a347114 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 622743f8c8556..1d23bb22bdd27 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 d622c984c5276..41c4dfda47fb8 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 926265a347114..f15c063fe5423 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 1d23bb22bdd27..cf057d7fe5af0 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 ac3a84934afeb..9ccf6b214470e 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 abc789ccda4b0..7931deeca7f77 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 | 307 ++++++++-- .../unnecessary_literal_unwrap_unfixable.rs | 84 ++- ...nnecessary_literal_unwrap_unfixable.stderr | 526 +++++++++++++++--- 7 files changed, 932 insertions(+), 224 deletions(-) diff --git a/clippy_lints/src/methods/mod.rs b/clippy_lints/src/methods/mod.rs index 912cce39e2ea1..183bd582a4837 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 fe6b86b34f5e2..7877f6a386cb3 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 41c4dfda47fb8..630a1bea3c879 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 f15c063fe5423..14f92cb370f6a 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 cf057d7fe5af0..0c71ee053231c 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 `Some` value + --> $DIR/unnecessary_literal_unwrap.rs:15:5 + | +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:12:5 + --> $DIR/unnecessary_literal_unwrap.rs:20:16 | -LL | None::.unwrap(); - | ^^^^^^^^^^^^^^^^^^^^^^ help: remove the `None` and `unwrap()`: `panic!()` +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 | 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 | Err::<(), usize>(1).unwrap(); +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 `Some` value + --> $DIR/unnecessary_literal_unwrap.rs:56:5 + | +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:37:16 + --> $DIR/unnecessary_literal_unwrap.rs:62:16 | -LL | let _val = Ok::(1).unwrap_or(2); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +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 9ccf6b214470e..711fdce39624e 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"); + 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"); - 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_err() { - let val = Err::<(), usize>(1); + let val = Err::<(), _>(1); + 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_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"); - val.unwrap(); - val.expect("this always 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 7931deeca7f77..feb9325b77a67 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 `Some` value + --> $DIR/unnecessary_literal_unwrap_unfixable.rs:12:16 + | +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:13:5 + --> $DIR/unnecessary_literal_unwrap_unfixable.rs:22:17 | -LL | val.unwrap(); - | ^^^^^^^^^^^^ +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); + | ^^^^^^^^^^^^^^ + +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); - | ^^^^^^^^^^^^^^^^^^ +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:48:15 + | +LL | let val = Err::<(), _>(1); + | ^^^^^^^^^^^^^^^ + +error: used `unwrap()` on `Err` value + --> $DIR/unnecessary_literal_unwrap_unfixable.rs:51:17 + | +LL | let _val2 = val.unwrap(); + | ^^^^^^^^^^^^ + | +help: remove the `Err` and `unwrap()` + --> $DIR/unnecessary_literal_unwrap_unfixable.rs:48:15 + | +LL | let val = Err::<(), _>(1); + | ^^^^^^^^^^^^^^^ + +error: used `expect()` on `Err` value + --> $DIR/unnecessary_literal_unwrap_unfixable.rs:52:17 + | +LL | let _val2 = val.expect("this always happens"); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: remove the `Err` and `expect()` + --> $DIR/unnecessary_literal_unwrap_unfixable.rs:48:15 + | +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:26:15 + --> $DIR/unnecessary_literal_unwrap_unfixable.rs:61:15 | -LL | let val = Err::<(), usize>(1); - | ^^^^^^^^^^^^^^^^^^^ +LL | let val = Err::<(), usize>([1, 2, 3].iter().sum()); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: used `unwrap()` on `Err` value - --> $DIR/unnecessary_literal_unwrap_unfixable.rs:29:5 + --> $DIR/unnecessary_literal_unwrap_unfixable.rs:64: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:61:15 | -LL | let val = Err::<(), usize>(1); - | ^^^^^^^^^^^^^^^^^^^ +LL | let val = Err::<(), usize>([1, 2, 3].iter().sum()); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: used `expect()` on `Err` value - --> $DIR/unnecessary_literal_unwrap_unfixable.rs:30:5 + --> $DIR/unnecessary_literal_unwrap_unfixable.rs:65: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:61:15 | -LL | let val = Err::<(), usize>(1); - | ^^^^^^^^^^^^^^^^^^^ +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:87:15 + | +LL | let val = Ok::<_, ()>(1); + | ^^^^^^^^^^^^^^ + +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:41:15 + --> $DIR/unnecessary_literal_unwrap_unfixable.rs:98:15 | -LL | let val = Ok::(1); - | ^^^^^^^^^^^^^^^^^^ +LL | let val = Ok::([1, 2, 3].iter().sum()); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: aborting due to 18 previous errors +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 23e7bc16d239a..c908568452809 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 d66b2b8ff6a03..661350c5c6d54 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 1be0cda12fc11..6ec79a618de14 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 fb5b1b193f841..33f7c8ba80424 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 ad89534aa1b04..4f98ca1923114 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 9e267c893005f..206788e19f025 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 1e9bb48c333ca..9eef0e1bfaa12 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 ea8b895664c49..3152bd3cae1a6 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 6fc20f8598872..42755e935aa41 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 298d63c9c34fb..be581030cb67b 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 7da12d89a610f..d6d085d7fd14f 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 941d604dd5f91..5ac02e7504e8a 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 ec082c73b44c0..16e54a7d969ef 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 d44d5072e4850..c395c5ba06f2e 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 043ea4148dc51..e417cf833cbb9 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 542ab53300c02..049a69d93bfe9 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 82dce81979fd9..61042bb90d27a 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 ef68827422233..93809f6551add 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 e1842c73f0e31..8ab36bbf93cbf 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 6ade6f5468917..46e2816da5226 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 a93fb59493fec..b9446034d50a2 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 d742595e14d4c..1588579bb0f2f 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 c08e0dbbf7449..be340340d4773 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 8e97054fb6bca..73c6c97de84b1 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 31e6bcc7ff643..a786138631c8d 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 cb55e32aee02e..36fb0e5de1567 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 1710b170fb813..4d72b58cdf867 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 85147e1cb6977..fcd945de33860 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 592563ffa8c8b..d025035b78942 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 c17634bffe303..20560b87c1a59 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 6d49a6949fa98..5dbc57565bff3 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 7dc44529206d5..10aa436d6cdce 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 425e6eb6200ec..80cdb4e472d41 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 3f7fa4a9d7dc4..99f735127eb8e 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 d26c317124b8d..f85b4fb46a650 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 1935ccb94bd58..a16ef5a5bca95 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 cffa19bec3a66..8ca6b880ceae7 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 ff68d38c73bf5..2047ee689d95c 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 6c40adbb53dc2..ab9df26ebc37e 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 08a536a28443c..703debb7a26ae 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 83ba68382efb8..bb86fe0d45fa0 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 ec87674b100f3..0b5c686bec0d9 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 40badac4424ac..773dfc3c5d148 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 76c9942fe6c1d..5867e014878e2 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 cb9583aa6ee37..5037c08ebd5f1 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 e5aeacbb56ce8..501898bf113c8 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 bb5c602d63a09..8660c0e1f6a04 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 e25d123dd51f1..972e0356b62a2 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 6793ec24441ce..7614ffb38e634 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 dc4af6ef42ecd..44ca61f008c5f 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 565bd96cf30a2..75a42809ad286 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 3627076b2af1c..3777b9c25c221 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 2850a632fc774..458eed1f359ad 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 b05dd143bfd74..b4a1f81679ad9 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 20acab6e844f8..7f353ba06982a 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 d9fd402e7cfb9..64d6437834e6b 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 d49bf2b322837..3796d942ff9fc 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 9f27fef82494b..7f57efc53c9c8 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 fe4ecef114535..1a551ab5ab8ea 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 a0c003f5b1eac..5bea85e669249 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 c3a7464fd470e..cf720eaaf052e 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 59a0ca3f192fc..08b89a18bbbd4 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 97cafa336eda6..ad2a744908fcb 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 85fddc970473f..238c2584221ac 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 523faa302dc70..ec127857ab261 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 243d1fd8606ac..cf6499b96161d 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 0000000000000..2d3f18a62c01a --- /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 1697a0cf29b8e..598f259415da5 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 860424f42ddf0..3fc461735a499 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 14437a59745e0..c40c6198945a0 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 0000000000000..abf784e0f0edb --- /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 0000000000000..fc03b2205e2e4 --- /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 11f0de07c62f3..41a380ab8f6a4 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 e54575dd3b43a..4c6433880b63e 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 f8a66f2ad3e95..3236765e1db0f 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 41055c168fcbe..71cf2aea0f8da 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 0000000000000..eb5a5d2b83685 --- /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 f56cee3a364a0..8efd44baf59fe 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 b4623df690959..c7723ef51f990 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 618fbd4faaf4d..f0443556fb4d5 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 abc35e8546f88..35b1075ff0118 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 2a9aba0a11628..107a62806a82b 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 884edec2d796e..fb08256931f66 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 | 29 +++------------------- 1 file changed, 4 insertions(+), 25 deletions(-) diff --git a/clippy_lints/src/needless_pass_by_value.rs b/clippy_lints/src/needless_pass_by_value.rs index 7d53fe65658a2..3b118239a21ca 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, "_")))]; - - // 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); - } + let spans = vec![(input.span, format!("&{}", snippet(cx, input.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 3dbda478b2fcf..9af6456924d53 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 e3712190e6722..a4c7da7e48db3 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 0000000000000..231dd063ad893 --- /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 0000000000000..779900e185908 --- /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 7bc901e4e7f1e..852f6736585bc 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 c5ea0b16d1be4..a166ccb3ee8fa 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 0b0e0ad2684a9..37484f5ebd702 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 fd553aa4538ad..5b60646ef21df 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 86acc4e00469f..0da67b600a3f5 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 294d22d34de95..e93f276533792 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 3f440ce0045a9..996cc3650ff0a 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 c1ca9180eef42..5eafaeb2fc306 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 be1ed73305674..c9990bb6f2266 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 384aca7feadd6..0617c3ea5e9f8 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 fb32aac94490d..666b7e67b4283 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 666b7e67b4283..f1a2c0575ee5e 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 e93f276533792..b7256dd2eae9d 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 0617c3ea5e9f8..11de7e6069700 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 0000000000000..5cb8a9691f4ee --- /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 0000000000000..f3e613bc79991 --- /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 2562314418172..ee559d45dd16d 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 56a269288c053..8aaa029f7760f 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 f970a32726b9a..f0ccdb0fe1045 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 ae8262ace9687..3d2fbea63f5e8 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 2d27be499f956..3fbd0867ea91f 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 0000000000000..07421173a3381 --- /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 0000000000000..088f7d5c06242 --- /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 2d3f18a62c01a..dfe8be7a6a619 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 fc03b2205e2e4..3e3d521f4a50e 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 8f68f90a2a130..618214f4aa25a 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 aa0efb85c297a..a10f3d0107076 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 8dc999ad58602..18cef1c5be895 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 618214f4aa25a..4ea58c4770963 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 4ea58c4770963..55cfe0d6b8b8c 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 55cfe0d6b8b8c..ec0ca50cfec70 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 de29d99cf8d00..e545abd8ba892 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 | 122 +++++++++---------- 1 file changed, 61 insertions(+), 61 deletions(-) diff --git a/clippy_lints/src/methods/unnecessary_fold.rs b/clippy_lints/src/methods/unnecessary_fold.rs index e545abd8ba892..8ec15a1c1b765 100644 --- a/clippy_lints/src/methods/unnecessary_fold.rs +++ b/clippy_lints/src/methods/unnecessary_fold.rs @@ -52,75 +52,75 @@ struct Replacement { has_generic_return: bool, } -pub(super) fn check( +fn check_fold_with_op( cx: &LateContext<'_>, expr: &hir::Expr<'_>, - init: &hir::Expr<'_>, acc: &hir::Expr<'_>, fold_span: Span, + op: hir::BinOpKind, + replacement: Replacement, ) { - 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, - ); - } + 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<'_>, + init: &hir::Expr<'_>, + acc: &hir::Expr<'_>, + fold_span: Span, +) { // 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 575dadde90630..ac55ab5a8e2d1 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 4238ff804780e..901a3e90dbecc 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 b3e6c09d2d7a1..68007edc41028 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 93bf50fd5e795..d182bb621950f 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 1bcaa33a049e1..7bb4da453c1cb 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 cee937e07e17f..e8d6ab6870a4e 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 42d9d4de193c4..348ad183d7d7f 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 a208857561030..e19f4980cd70d 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 1a75f214c856f..a2a1cfb317e11 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 d2193c0c81955..2d72b16430c40 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 218bca40cb032..c0925988ca146 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 9509e6d016ab3..1fd70fce14f6f 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 cf6499b96161d..e07959849a3cd 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 0000000000000..ccfd55886ec41 --- /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 8f9f2a0db8c43..06d8ad4844648 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 843e1df8bc6bb..857cd379fe235 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 0000000000000..05caf485db69d --- /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 0000000000000..e30469e09e8db --- /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 0000000000000..51e2ef4f7410e --- /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 bdf746cf2c425..aec9725c4b9cf 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 7271e2f957a87..a3b9b88dbc2fa 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 c0925988ca146..445e2366cc330 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 1fd70fce14f6f..2690336648d44 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 ccfd55886ec41..13cc0b23ba33d 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 e07959849a3cd..b254c05d48bf0 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 06d8ad4844648..b7c186bef7724 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 857cd379fe235..44e18bff83fbf 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 05caf485db69d..ac482dcda1eee 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 e30469e09e8db..00775874ff585 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 0000000000000..0021841aa860f --- /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 51e2ef4f7410e..0000000000000 --- 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 aec9725c4b9cf..eae1271d1aa72 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 a3b9b88dbc2fa..4abd560f84bec 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 218bca40cb032..ad7a101d38aee 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 9509e6d016ab3..b726f343ffe7a 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 0000000000000..6d9df5875180d --- /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 183bd582a4837..faddb036eaa19 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 0000000000000..1bedab75c0388 --- /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 0000000000000..d4e2b4a6fa279 --- /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 24a95c4d0fee4..7a8c677010104 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 a118c981ee3f5..cf3a935c349a4 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 6d9df5875180d..53f63266073dc 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 0000000000000..0d40a64837829 --- /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 1bedab75c0388..7144a1847ca2e 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 d4e2b4a6fa279..0792f0254cb54 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 53f63266073dc..8bd8f88a2142b 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 faddb036eaa19..bed70207f28e5 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 8bd8f88a2142b..d0c79dc11b071 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 bed70207f28e5..99c984ba65a8d 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 0d40a64837829..11001bd319f31 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 7144a1847ca2e..373a3ca3506da 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 d979087a6d7a0..b6ce4ebc28f2e 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 1a2c1e592619b..f3669a669ea1a 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 fec4665218970..db8c7f80df48c 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 351da54ef314e..618f5e071d6b2 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 5cb8a9691f4ee..0000000000000 --- 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 f3e613bc79991..0000000000000 --- 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 10aa436d6cdce..d544a0b1afb07 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 183c262ce0b51..39d97f08373a1 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 11de7e6069700..815495a7b7af9 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 b254c05d48bf0..cd1b63bdba253 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 cd1b63bdba253..f0a873b91eb07 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 188ff87abfc53..300c84a1442de 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 a1d2147cb4965..dbaf6aaa853c5 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 d18f93875658c..204019130ede3 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 de8ff0b06bdca..46e02847e3084 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 3b280b7488ae7..bd62c655216e8 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 251f1d84e74e3..bb966af4b0ffd 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 a2a30c8b931ce..4eff62b85ff68 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 2eaebfb5cac50..2b053b462b164 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 0000000000000..7bc6fec10ba64 --- /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 0000000000000..babb634fdcd1a --- /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 6e810a349bfcc..31ce881932952 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 0cfa007d1b271..c041fc606a8f3 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 085dff8e63bab..bd44af66d4235 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 f0a873b91eb07..6ea329a9542bc 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 2920684ade33c..bc739dca0b982 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 f6c7c1fa065a0..fccddfbdb8b54 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 d8ce0e2f55d45..db2071ecaafb7 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 0000000000000..1c2e7aeaff996 --- /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 0000000000000..ef208f2c3901f --- /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 229d150851a43..fa86352554bb4 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 d1c1bb5ffeac8..84a8e681f6762 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 bd44af66d4235..78a5f9da461c4 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 bc739dca0b982..1676c767a34f5 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 fccddfbdb8b54..e8c8d478ffcae 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 ef208f2c3901f..e1ba1b2f67e99 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 fa86352554bb4..f4e7f1943ae6d 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 84a8e681f6762..ee1d3aa285a28 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 0000000000000..c2326678d0d52 --- /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 e1ba1b2f67e99..533f90483e513 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 0000000000000..ac987a9e995f9 --- /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 269be545b0ab1..3eaa0d199fd1d 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 815495a7b7af9..87d88f707529c 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 d9a1e76c077a8..6b164967a28e4 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 d544a0b1afb07..0e1533fc1ab10 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 39d97f08373a1..3dbe2dfbd88fd 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 ffc3a4d780e5d..209d42ebabd1f 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 9061c9aa40495..3e4c2b499e4c7 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 b5e4e4720377f..a967971a7dce4 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 a6a34620e92d6..6221c23683099 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 e275efaba25fb..d85650712db82 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 3c55a563af455..5e0fcd743392d 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 abf2525a61c68..8be3c178a2912 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 4f967755bfa19..e0904f17b8de0 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 15dff126be76e..f3e0c58a78711 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 dd7ded491e792..d2018aba9e3dd 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 cc3183759ae7a..ff01c2ef7bed9 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 311f6dbc696db..5b5e9fba6af42 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 f95af1017bcbb..7dd14e3824dad 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 ff01c2ef7bed9..72582ba7e7859 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 e4a4936ff42fc..00f3abaec8a44 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 0000000000000..9f75ad895cda8 --- /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 0000000000000..67115f7c5a7b7 --- /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 0000000000000..a992c54291495 --- /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 c0d2c835d63d4..b132e69269d8d 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 b132e69269d8d..860a489494c88 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 3eaa0d199fd1d..6fb7ac740b0e4 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 7690e8f724707..9c1e1f6702df5 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 6ea329a9542bc..939b1136b4686 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 0000000000000..d0fbedee832ce --- /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 0000000000000..9806eaf3c4211 --- /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 0000000000000..decf561eed42b --- /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 | 52 ++++++++++++++++++++++-------- 4 files changed, 61 insertions(+), 20 deletions(-) diff --git a/clippy_lints/src/single_call_fn.rs b/clippy_lints/src/single_call_fn.rs index d0fbedee832ce..55a19b813b416 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 e8c8d478ffcae..987e2abec5022 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 9806eaf3c4211..e7f819cc8a1d9 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 decf561eed42b..9ef8c487844fb 100644 --- a/tests/ui/single_call_fn.stderr +++ b/tests/ui/single_call_fn.stderr @@ -1,31 +1,55 @@ error: this function is only used once - --> $DIR/single_call_fn.rs:26:1 + --> $DIR/single_call_fn.rs:33:1 + | +LL | / fn c() { +LL | | println!("really"); +LL | | println!("long"); +LL | | println!("function..."); +LL | | } + | |_^ + | +help: used here + --> $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: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:29:5 + --> $DIR/single_call_fn.rs:46: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:13:1 | -LL | / fn c() { -LL | | println!("really"); -LL | | println!("long"); -LL | | println!("function..."); -LL | | } - | |_^ +LL | fn j() {} + | ^^^^^^^^^ | help: used here - --> $DIR/single_call_fn.rs:23:5 + --> $DIR/single_call_fn.rs:24:9 | -LL | c(); - | ^ +LL | j(); + | ^ -error: aborting due to 2 previous errors +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 349fcd2274d3e..b393db53b3605 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 c9cbc50546cf3..699ab2be199a8 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 bf5b4ca5288a4..d24b278ccc282 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 0000000000000..15dcde4e30a1f --- /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 0000000000000..55569bc25ed75 --- /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 0000000000000..7b0966a458673 --- /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 0000000000000..99940dce528a6 --- /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 0000000000000..c62f9acbf2cbf --- /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 0000000000000..f19ab10d5fb06 --- /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 0000000000000..5cb4795e94518 --- /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 0000000000000..4a835673a596b --- /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 0000000000000..aa84f78cc2ca1 --- /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 0000000000000..d79569f78ffbe --- /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 0000000000000..060cb18dc9f97 --- /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 0000000000000..b25725cd5610e --- /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 0000000000000..4647424f2c2fd --- /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 0000000000000..91cd540a28fdd --- /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 0000000000000..7713fa9d35c4a --- /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 0000000000000..5a5eaf9670f90 --- /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 0000000000000..a12734db7cb5f --- /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 0000000000000..f19ab10d5fb06 --- /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 0000000000000..42eb99cd7a3e1 --- /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 c0d2c835d63d4..566eecf36a777 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 bd62c655216e8..3b280b7488ae7 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 bb966af4b0ffd..251f1d84e74e3 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 78a5f9da461c4..cc4caae566fbd 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 55a19b813b416..42753d2e95114 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 e7f819cc8a1d9..bfb773187fb65 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 9ef8c487844fb..bb92e3cf71aa8 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 b393db53b3605..439cae812b7ff 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 685d738cbb7c9..e36adef555e65 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 dcd372f689d6c..3e261b2046559 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 286d208b25bd2..abadf82fe4b1e 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 f477524eec5cc..a87d58110b0c1 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 dbaf6aaa853c5..ee6aef71980e3 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 8f5d319cd4fc1..8d84e756ff874 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 d1314795f5803..a391b76910ad6 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 99f810c27cf82..cf85d3174dbac 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 309d2157b76ee..06fa95cd657d4 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 7d53fe65658a2..3773975e9554b 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 fc550936165e6..b8911f109076a 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 289ca4e9bed3c..a375e5d5b4ca2 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 3df40942e7b5a..941df3318ae8b 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 860a489494c88..aea79984c7ad6 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 7b4ed77e8edb9..12f18614d713e 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 ad47c13896c58..35627d6c6491a 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 a54e658bf23a8..0da59a5332040 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 f296c6c4d1cd6..7afadececbf9b 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 3fbd0867ea91f..00fa3eb9bfe53 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 0da59a5332040..e7b1fd6a85f22 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 7afadececbf9b..1515a7053e5dd 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 b992d689aa979..40378ee8205cf 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 3eaa0d199fd1d..f7295ecf42c77 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 78a5f9da461c4..ccb24a536afde 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 6ea329a9542bc..a0ada107fbf64 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 1676c767a34f5..a9deee9678495 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 e8c8d478ffcae..b04b3177e98a9 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 db2071ecaafb7..475b15a24140f 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 1c2e7aeaff996..e6dbb3d37841b 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 533f90483e513..c0976f0d6007b 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 ac987a9e995f9..9a0fd05938962 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 3fb4e6c8fa513..0008f8f6d46cf 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 3917d8f02251f..2cf3529bd1bb2 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 e1b1a6f7184a4..b1f336461d13d 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 1d36f4b3c7b2a..874d97f7a46c7 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 56867f75b07e8..54973c5bda572 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 2cf3529bd1bb2..78e27b775fbdb 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 d6c235b5a693a..fdd552604830e 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 edb9d87d032ec..b6c8d9e53d80e 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 a90d8b1655dc4..50711120a15dc 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 32cc5d1edcc83..6c52563b8ed4d 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 3cf2fbf1f288f..f5d6cecc59c2b 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 d3aa2816cb6d3..14444df4c10ec 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 d1e7d8017d7d1..542d33b13a4c5 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 6c67c903c7508..94ef43afc08f3 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 209d42ebabd1f..ba5aae28bd6f4 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 3e4c2b499e4c7..f0d28dd93495c 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 a967971a7dce4..21c1ecb0af289 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 6221c23683099..154083ea654f4 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 - | -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(); - | ^^^^^^^^^^^^^^^^^^^^^ + --> $DIR/get_unwrap.rs:82:18 | - = 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 - | -LL | let _x = f.get(1 + 2).unwrap().abs(); - | ^^^^^^^^^^^^^^^^^^^^^ +error: called `.get_mut().unwrap()` on a slice. Using `[]` is more clear and more concise + --> $DIR/get_unwrap.rs:103:33 | - = 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 ba5aae28bd6f4..e35fb12ed7910 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 | 236 +++++++++++++++++------------- tests/ui/question_mark.fixed | 12 ++ tests/ui/question_mark.rs | 12 ++ tests/ui/question_mark.stderr | 30 ++-- 5 files changed, 178 insertions(+), 114 deletions(-) diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index 3fb4e6c8fa513..876fcd0f1974e 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 5269bbd1f1acc..036ad3e0d150c 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 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) { - check_is_none_or_err_and_early_return(cx, expr); - check_if_let_some_or_err_and_early_return(cx, expr); + 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 7f1660f31fa5b..f257378842bea 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 a90eae50ed457..29d79b078ac1f 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 23172d7e535dd..86d89942cc051 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 9c1e1f6702df5..0eec18a91bca7 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 9c60edb179415..36b231023a770 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 3fb4e6c8fa513..71b8af7a82122 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 fdd552604830e..0000000000000 --- 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 50711120a15dc..6e3c31804d7fb 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 ceee12784cbb7..121043104058f 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 d1609eebfdca9..e1f950d5a4a5f 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 975a5a62ad5ae..24be814548a29 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 587b0d1d366a7..91f4a7ba0d2fc 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 93b576ec56fed..160a895bb7b4e 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 5f1fdf00be8c3..4f2092492aa8f 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 72582ba7e7859..03dc9ca56ff23 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 4a8ba995da556..e0f6b3d9d3b44 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 67e0fceff6ef3..5bcf054884e41 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 29821ff96fc0f..eb179f30e75e2 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 b2eafb345e33b..0446c09cd5bcc 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 78e27b775fbdb..6db330dfa617b 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 3cf2fbf1f288f..54ee960c4723d 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 b1f336461d13d..0a4c3418a08e5 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 a391b76910ad6..818ebd1134de0 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 12f18614d713e..2b185943c59ca 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 32cc5d1edcc83..dd605b76a3d96 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 fc550936165e6..e885439415098 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 5f54101ca15ad..709f74ee6aa2a 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 6b4de98ce88c6..d663b070b9cfd 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 68c5c3673fe15..45f67020c2db5 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 4db13d650eb18..89423ffe1cf8c 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 d7be9a5f206c1..76762c4a1d1f7 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 eeb4de8b58f48..126bed6789c4a 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 adcd1f6d4076c..03ac9abf498be 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 c4c5227ac9187..731c89c18dcc0 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 c042a5a2290e5..b5277d49861c9 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 4506d1550bd4b..db34e6bfa7b2f 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 36b231023a770..6f8261ed84e3a 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 6e3c31804d7fb..8004b2aa8db7a 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 5f1fdf00be8c3..10b5e1edf9250 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 7945275393c04..93ef07d36aea7 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 3c2bf5abab2b5..6b51974d739af 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 941df3318ae8b..a42b2ccee889a 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 a49246a783272..3e1d735641468 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 a87d58110b0c1..b38b9553558c8 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 5dcd71cef127e..8dafa723afa00 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 3b58e25c61108..941efb1abff83 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 df9b1bbe18f32..52445494436c6 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 | 438 +++++++++------------------ tests/missing-test-files.rs | 6 +- util/etc/vscode-tasks.json | 4 +- 14 files changed, 209 insertions(+), 393 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 4d80d3ce63dac..48a63e4856815 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 ca8bf9fac91a0..76c804f935e29 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 c26aa883ebae2..cfcb060c46e37 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 7615dc12f9ebe..f4c109ff11917 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 92b2771f3fe73..0000000000000 --- 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 8aaa029f7760f..4624451cff4fc 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 97d6a8353a068..43eaccdf5a31a 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 f0ccdb0fe1045..f11aa547bd734 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 0000000000000..6d053253fc3dd --- /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 0000000000000..7d12d9af8195b --- /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 5b5e9fba6af42..078dcef19273b 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 35d75cc51c210..281e778ada655 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.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) { + 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()); + + // 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 name = config.root_dir.display().to_string(); - 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 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 name = config.root_dir.display().to_string(); - let current_dir = env::current_dir().unwrap(); - let res = run_tests(&config, &config.filters, tests); - env::set_current_dir(current_dir).unwrap(); + let test_filter = test_filter(); - match res { - Ok(true) => {}, - Ok(false) => panic!("Some tests failed"), - Err(e) => { - panic!("I/O failure during tests: {e:?}"); + 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 caedd5d76cd6f..0d35a22cd9a4e 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 ab98f9b4154ac..38e31b337a06b 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 | 43 +- .../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 | 16 +- 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, 1735 insertions(+), 1058 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 86953142befad..e161507b53395 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 ac1b5e8e90347..dbf494cc342d3 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 be32c0dc418fa..ae5967406f62f 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 0000000000000..dfbf19d33a5e5 --- /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 163f8bb35e79b..0000000000000 --- 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 0000000000000..407a9055de80c --- /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 259d39b12526c..0000000000000 --- 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 0000000000000..566f5a68689b2 --- /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 259d39b12526c..0000000000000 --- 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 0000000000000..83d4be3bae464 --- /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 259d39b12526c..14a6b5047b183 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 97e6c3d5a5592..0000000000000 --- 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 eeae5b7b275e9..e89388b501bf1 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 0000000000000..fde3a1e659915 --- /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 3b80d89a68655..0000000000000 --- 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 0000000000000..da2db45d3b836 --- /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 c6a11fa93eb5b..0000000000000 --- 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 0000000000000..c2907f319e643 --- /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 697c8b57c4a29..0000000000000 --- 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 0000000000000..fcf1a3c5e66c6 --- /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 ea6ea98064a79..0000000000000 --- 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 0000000000000..f61642ca2efd7 --- /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 f40ceea234b9d..0000000000000 --- 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 0000000000000..d82b9e73f786f --- /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 aa1b3c638a036..0000000000000 --- 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 0000000000000..5bcce920455cf --- /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 f3113e0936502..0000000000000 --- 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 4391499a1e1f8..d42043070261e 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 0000000000000..b1578c9f32490 --- /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 9e65d2f99420a..0000000000000 --- 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 b9ea5a64de75e..19904318575c3 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 f328e4d9d04c3..c69fcd300335f 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 5b7e8c0db744d..f7d53763a4388 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 f328e4d9d04c3..688c92d8717d1 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 386e1135df90d..fb0a14081524b 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 123ad94dd09da..89d84eb24556d 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 f328e4d9d04c3..187775545ed77 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 54997735274e4..7c56dfdb948e9 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 2ae7848f183b5..0af8c0add6c6a 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 53ad427124691..a4b1e9c335ca2 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 df17974de033c..ebadd4e440a95 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 25f0d0d6230a7..c28220b973ec3 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 2ebf28645e51e..03fa719975b68 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 2498672d77fb0..bd5110138c8c5 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 be505bda4792c..ac9d89d0cbeeb 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 21849a14fa95e..da76bb20fd961 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 1e3ec123a3c8b..e1dc3f4389c0b 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 f5761c6afeb37..e7ac05dd3c63c 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 e4747bedddb88..054db5d933059 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 54edded99f41b..95d1a2297e531 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 068b47bd09def..17c1b03d88c61 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 db88b1cbecb06..14e13194427c0 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 179b1266169ef..f267a67f40ee5 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 b3ef5928e8ea2..d2b55eff16dbf 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 569fd2c3553b1..38009627757c2 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 475b15a24140f..69678057917d9 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 c2326678d0d52..1c591fc76f3e9 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 c0976f0d6007b..33d63670958dc 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 9f4d0ef1bf917..dde1c6d7c37d6 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 706f9a89cbb36..eb66a5cf50ba9 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 4391499a1e1f8..d42043070261e 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 fa04f53ca9106..cc95a06817d69 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 10d2ed1a8a95b..2eb6ad304ea47 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 663c2eb2c3794..d223d56422177 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 5cd0dcce6f765..50a13f16b4456 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 db0bfc8afc39a..fd8223a2309c2 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 7dd14e3824dad..4f38e50c81d55 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 48ca2f6d14375..427842a51d9bd 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 c93995f939acc..af02e202b17bb 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 7ed8a28dbd935..cab216b51ac71 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 d164dd0e54505..fdfe5fc418122 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 5ea86a9ff37d1..37f0ec2b37d88 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 f13b76e44b04f..79e8eff3aa101 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 c2326678d0d52..1c591fc76f3e9 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 5d849bfcf818e..4d008c8cb59fc 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 755264617920e..b951ba04c37f4 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 e319d365f7e77..52980e55fbea0 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 29b08ab36430d..da940a4cfb50b 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 b0cab977a0384..b753ec92608a8 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 7c57864245a94..0ea93dd84625c 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 c87ad206c2ae2..200e04b8f6be5 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 06b5d62e8f9a8..4da3833cbf5a0 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 f34ae8814c335..add223acd68c7 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 69b8b6a0e68c3..c5addd53434c9 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 76f90ab2a9d11..bf1a58588a856 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 5824631fa83ba..d867246301abd 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 66419656a327a..5dffddc119aa3 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 c7f0224820ed0..0df22f41374f1 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 3106a2e721694..268c5ba0ad0f6 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 0769bce5fc809..f77f691c19276 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 4506d1550bd4b..b72037b7d4a69 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 8da2965c63512..68a5766c90c0e 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 ccde6aa2b0f77..b6555ac5c4072 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 f9ee3e058c111..1d336b3cdc0c8 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 9cfcccf1e3cd9..671933157c809 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 a5373cdcae120..a2683b3ce3402 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 4b3fb76401082..ca68ba3d03a51 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 78c567b8e772e..712bd14c685f0 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 d6cd594d7c971..aa76688d80101 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 3d79a115cb301..0000000000000 --- 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 a382135bb6951..32eba9695920c 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 10788d4048164..6c63c098916b7 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 530e766331777..3d29262595902 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 f44518694b89c..a88bf7b21b8b7 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 84198d5461578..6070df749ca98 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 + --> $DIR/enums.rs:60:5 | -LL | const TO_BE_UNFROZEN_VARIANT: OptionalCell; //~ ERROR interior mutable +LL | const TO_BE_UNFROZEN_VARIANT: OptionalCell; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: a `const` item should never be interior mutable - --> $DIR/enums.rs:60:5 + --> $DIR/enums.rs:61:5 | -LL | const TO_BE_FROZEN_VARIANT: OptionalCell; //~ ERROR interior mutable +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 896596b567922..1cec2980652c1 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 1fd6d7322a76c..0259f6a4a286b 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 256a336db821d..a6ccdd2707989 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 7debe059ff4ee..ef62919dfead3 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 f7819068ac5ab..da0816830b85f 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 9520efe6329b1..02eb78060130f 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 cacbdb4a95bf4..79a9669833fad 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 fbabb8bcf8e33..23272d07eec66 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 7bfc390e4bfab..fb149141609dc 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 bf5dca976416d..14eb6d572cfac 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 5e8e9ce85b1c5..aa2ced0a7f035 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 0bf739fe2d16b..0ecca1b8ffaaa 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 2d796a24fec56..9f91310e61f3e 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 c7e60f3650603..ce4b94a73bd25 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 0c8eac5ccffc3..d21b046f167ef 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 879b3ac398e45..eb5e2266540c9 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 90ccfb4fad641..11baf75441ae2 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 e843770f57854..83db2a07d334e 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 269e66ea0a816..b2d7ddae42746 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 54e8fb4907c0f..f1a55415c8d50 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 d564b2d24f5c4..f9ab443dfd94a 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 f17556ea90709..abe42a2305f52 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 de5e121be8774..8389806c838e1 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 0eefb9f0ca978..0a6bdf15df8ee 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 cdd33ebe582ff..38372378168e2 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 d365ab27edc28..2c013b6b6fe1e 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 1869301d2242c..6cc070fb5526d 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 a78aec74a7b8b..f00a129bef1a0 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 cdfaf8d3afea8..50abe89da893a 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 03ac9abf498be..8420df6634d90 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 731c89c18dcc0..f63535d7ae6ee 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 2045b1eebcd7f..d6df114b8d262 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 f0d28dd93495c..56ee37f02d26d 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 21c1ecb0af289..af3a619adc5e9 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 154083ea654f4..fd961420dc41d 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 07d2002eb27f8..dad4543f84c09 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 fb23b81d36d72..a34fc565590b0 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 3b9b029d35467..0b171f21d0cc4 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 a4d8a74167e38..56e5f3e45b22c 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 c321b08909f1f..5c338e3c5c8f2 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 ca7c12213728b..7ed7bf94a4b3c 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 620d45e6828cc..d84346e8789d5 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 10ffadcb2ba90..87fba7448e3a3 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 9f550acb1577c..af197e33fd835 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 3381ae04dcecd..3ac13d7dd3e1d 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 28003b365bbd5..06014a93f8c18 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 586d13647d15e..0b07de1144ce7 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 a35032aa150dc..d7c2c88a20470 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 597f1b9510c56..1b6257471618c 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 ea8bc5b4aca1f..e677cc9a7b95c 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 2c313ff35d59d..431d83778e34f 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 ae1a480bcfc55..8214176cfd576 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 b4dabe3cae5d3..53b6a0250f99a 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 925a2c61f8d20..a40fa389895aa 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 6fd338cef8688..67a833e85e046 100644 --- a/tests/ui/macro_use_imports.stderr +++ b/tests/ui/macro_use_imports.stderr @@ -1,28 +1,28 @@ 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 + --> $DIR/macro_use_imports.rs:23:5 | LL | #[macro_use] - | ^^^^^^^^^^^^ help: remove the attribute and import the macro directly, try: `use mini_mac::ClippyMiniMacroTest;` + | ^^^^^^^^^^^^ 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:23:5 + --> $DIR/macro_use_imports.rs:25:5 | LL | #[macro_use] - | ^^^^^^^^^^^^ help: remove the attribute and import the macro directly, try: `use mac::{inner::mut_mut, inner::try_err};` + | ^^^^^^^^^^^^ 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:19:5 + --> $DIR/macro_use_imports.rs:21: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 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 b9677851b92de..3971aadbef853 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 f2e44e56f0205..594a76897bbe2 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 b2329c33a47d5..d5f98e71517ee 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 ac85bd8d3acac..5b9629f4bc10f 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 1f824b12bc263..297887a9cfc82 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 3914b45464c71..fad6a7db988c4 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 db85b5964e842..88b9a20a3726f 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 60b2975be0454..b1b9a6ae3e8ab 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 8fb461bd28667..7f0c70745ac0b 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 132873858b7c5..e53342f2ed368 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 c5e03468ef9df..b5b9e66aa7a02 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 89404ca882718..af1358f61b5cb 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 ecd0380127797..33a5c1f8e0526 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 abadf82fe4b1e..06e0535247982 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 bf587e774f743..cff1706a8426e 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 520ddbe16b829..2d45132f968eb 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 3c68fb905f12d..e47a198c6aeaf 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 62cfeafdc49fb..9c2ffcb02ea11 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 f83b7c3dbda5e..a0a1e96a775d2 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 4ef6f0ca92f2d..23ad36bb47304 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 4f7cf4e56d152..c460fd7c6b0d5 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 3a814ce16859e..fe95624f79960 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 d838098de113e..b721342836771 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 00871f9f450ca..876f16a3854d9 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 8fd945f1a54c7..5e6e140c2db38 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 04868299a5484..eb28ce73be8f9 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 b3ed0932ab590..933dd8bed2a26 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 dbbbf24085e40..ba3a04e0825eb 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 7b99042f7449b..302a3f9edbecb 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 6fcf1efc2ee67..b15477c92e814 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 78a0e92d17979..c603163c145f2 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 583096ac054a1..987a4775ef074 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 116d5da8729c0..b62748d4989df 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 89d127528347c..5d0da8dce6702 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 1b3a322d72658..04a3643050e69 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 aa362e96321bd..63fdfe486e812 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 ee1fe3f1fc0fc..65a1b467f8114 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 0000000000000..6098dea39911b --- /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 ff79ca75ffaab..d9c7acc274802 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 b9f5675faec73..b97711e777dd7 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 59914b8b8f627..b77874034d0ba 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 c795f6ad0d25f..d912b50275512 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 2c2567d67cd9c..26a64c861cf4d 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 6000e5c08acbc..ea40d4947331b 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 ba3eca061df49..1ef1809d15305 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 adeb43edf687e..2c15cd429daf6 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 f65c0fdd35da1..a1ed491bbc6e4 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 fb07fed98befb..9accd297fc936 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 2651735d10364..a83699ec68da7 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 7286652899d6b..b165cbaa3aa16 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 b2cbd2d9d01b0..a13e5eadf15dd 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 f57dd58e230a3..b3f263a7d66d8 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 cc7e55a757a32..4e7500903f811 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 1e8a21283cd95..c74dc8108fe37 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 aea1507cc5bd9..02e347ed9f6cd 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 aade3b1fa4571..d7b2d762db721 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 c2895718a1aa4..9be8c5e59d014 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 0000000000000..acc78d6bb0439 --- /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 bfb773187fb65..76e175014b877 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 bb92e3cf71aa8..9ef8c487844fb 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 5564aac674d97..5ae2450c22681 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 f88498655a418..fcc8f14803d31 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 b34b95539190c..77afd58a08dc7 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 abf784e0f0edb..833e1c43bfc0b 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 de78dfe4d6990..6980242ae727b 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 c0856427eaef7..0473ccdc3f636 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 21fdfdf900516..d53c692b78e13 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 125a79d6edfed..71c649c5d2706 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 4bacf9efdaea2..9ad45c7a817b4 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 723870ccc8040..45ccc024cbdec 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 8aaf47b1bd0c5..464762af82536 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 f06ffab5d9be9..61a6c98ed5ac7 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 dc773ad4bad95..1816740870ad6 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 7a7433a7ec29a..0e47c4d023ef7 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 f4e7f1943ae6d..a9cc429543563 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 910968afa7f44..032040c4805c8 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 bc4b84d34354a..dd215bc604870 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 ea74a81451e3a..21cc22a778bc5 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 972e0356b62a2..a042731a9bf5f 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 7614ffb38e634..d830b74d6072d 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 d082063c8e820..fded8db5daf93 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 75a42809ad286..dca38034177b2 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 3777b9c25c221..7fda719edc1b7 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 373b18470f695..2d55dc664a32d 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 b6241612d9da9..1251208726703 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 ae583f4bde379..0a3ffc4784b2d 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 4391499a1e1f8..d42043070261e 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 89ea14759b7db..4179f21c51002 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 49e5bcb7ed961..01a36def9e97f 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 c672eff1c2710..879e2e24ab341 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 de6660c95e6e9..8e77ec444b52e 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 8de4331e8a690..27498d9bc132c 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 733bbcfbcefab..2961b062ec37c 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 4acdd374bdeca..28508a2538b28 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 235be2d57081b..c96b3041a005f 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 d5956db9ff0b4..bf22738480deb 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 0000000000000..0a10e526a2f56 --- /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 9035275b29db4..03a18a4dc3f37 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 281e778ada655..c5e8622bc85c5 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 aa6d40042688d..abdccc47f5475 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 2b8ce5477cc6d..44ab8ebb50aa6 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 cfbec8cb27da1..9358c20ab95a5 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 91d52fc79b810..fde27f2169069 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 78be6b9e23fa2..78253ab6cdc42 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 a1da47d84fd5c..714143e758694 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 399066b813e3e..153e264070173 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 2c46b4eb593e3..276330d21c424 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 fa639aa70d61d..48ae1cf66405e 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 6f7c315456969..3f15684986fe0 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 d18c65a77095b..2eeba509e8338 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 c80756c44955a..5416cfaa5425f 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 8a004b77e941d..ffbdc049506e0 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 ee6aef71980e3..1ecaa1a123ce4 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 8d84e756ff874..10a2f0cb1e7ee 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 cf85d3174dbac..0699997d0d2bd 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 06fa95cd657d4..80eb00a1b42d9 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 3773975e9554b..c0970048cdfe2 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 a375e5d5b4ca2..99a1d197678bb 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 a42b2ccee889a..659c693f87aee 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 a10eb8646af53..b7e83ce6caaca 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 2b185943c59ca..8d3aecd4785b1 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 99c984ba65a8d..403fac123a92d 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 e931c6277f4ef..6a4d288abbfdd 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 0cd49dd7760d6..51b88c7cf2e58 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 41781b050fa20..6f23d2e4f8854 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 403fac123a92d..b1d3b61aea370 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 6a4d288abbfdd..4387090fe2329 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 0a4c3418a08e5..1541dc8392c1e 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 51b88c7cf2e58..bb36cb2c598b7 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 6f23d2e4f8854..9f4a4a9ae6bf4 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 b1d3b61aea370..cdabb1689123b 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 4387090fe2329..b0d902e608861 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 cdabb1689123b..b1d3b61aea370 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 b0d902e608861..4387090fe2329 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 4387090fe2329..e836a1395a26f 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 e836a1395a26f..f4f158c0439ed 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 1541dc8392c1e..5aacca4514654 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 941efb1abff83..7cb820b0c43c2 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 0eec18a91bca7..8753bcee5ce42 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 6d77b828f1490..aadba6581a172 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 0000000000000..85dffa5613d39 --- /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 300c84a1442de..fd0da5a170bcc 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 f214cabef67ab..2e24e07ea268f 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 d9b28a4f7c091..0e64a310b01e2 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 0000000000000..43616860a2e71 --- /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 0000000000000..e2d85c52e78cc --- /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 0000000000000..44b878cec40ab --- /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 1c8e47ab59494..3b2086519468a 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 cbcf1ab21c9bd..2d4c08412199f 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 a1f005cc833b1..463b19da09e08 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 55d91583ad04d..3f93c18470eac 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 dba89872070e8..f1dc3ea9894ad 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 6a145a14bfdc7..00b38498001d6 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 3fc11b8b0885e..0edd81acc7afb 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 7d54acf630e6c..2647f02f0e92c 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 7cb820b0c43c2..5b17072df40db 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 8753bcee5ce42..c67ed14b3b046 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 aadba6581a172..e1a7eedd93e73 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 85dffa5613d39..0000000000000 --- 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 0000000000000..52814693f3c3d --- /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 12197666b30d8..9f88960f7ce3d 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 e4cb5316a985a..570a88a0ed2b4 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 fd0da5a170bcc..cdc85cb33ca2b 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 8feea800fdbe3..15e5cdd6992cc 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 ebbc7fea328d9..d26bc72787b86 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 3dc83a40780a0..fc137c225d83a 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 69678057917d9..8724dc29d2959 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 f456c11924e5a..78a11a3354f6b 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 0000000000000..ffc1644335d23 --- /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 0000000000000..b06b9a0ec857f --- /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 0000000000000..3eb699dea36ec --- /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 43616860a2e71..1bfb573719dea 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 e2d85c52e78cc..dedd774ea0a6c 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 3b2086519468a..850c9813462a1 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 c74dc8108fe37..21f1cb44460ef 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 2d4c08412199f..ee0177776bf0a 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 463b19da09e08..e3b7d8597c2fd 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 f1dc3ea9894ad..920d43318aeaa 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 00b38498001d6..3a53084e30b2b 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 55a11daa1d344..1d9b9603bd809 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 bf22738480deb..a69d031b01142 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 52814693f3c3d..81afe18ebc6fe 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 5b17072df40db..e81e87bf0770a 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 9bf7b1949c4e1..efb48131502d5 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 81afe18ebc6fe..b465c7566f02c 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 1bfb573719dea..8d443dabcb77f 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 44b878cec40ab..dff47a2d04212 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 e81e87bf0770a..a7284a70a1ff6 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 efb48131502d5..293195e858c0b 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 c67ed14b3b046..dbd4a53d8367c 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 e1a7eedd93e73..d926b7b84ea74 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 b465c7566f02c..f45bb1ef3e1f8 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 == 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 < 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 9f88960f7ce3d..9be94920f96fc 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 c5e8622bc85c5..13013f646e593 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 d26bc72787b86..63fdea710cb6e 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 8724dc29d2959..6ba26e9773023 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 ffc1644335d23..6438e46977bbd 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 b06b9a0ec857f..f7ddc68265edf 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 3eb699dea36ec..0179978b7b08c 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 8d443dabcb77f..e4d7d8fb017a9 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 dedd774ea0a6c..e2d85c52e78cc 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 850c9813462a1..89d1d94945454 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 ee0177776bf0a..cb301c8bc1529 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 e3b7d8597c2fd..99baf35ac2979 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 920d43318aeaa..7ae62231acc0f 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 3a53084e30b2b..0604624e767be 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 1d9b9603bd809..805127e275005 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 a69d031b01142..18591250aad9e 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 941efb1abff83..6350d9c118f6d 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 0eec18a91bca7..13b0f9d5ee388 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 99f810c27cf82..3c3919dffe5f8 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 5ea12c441840d..88a3c2620a406 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 78253ab6cdc42..fcf19f17958fc 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 0000000000000..87e1ed8317c68 --- /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 f477524eec5cc..bc3e58169e619 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 07cd5a53a7c4f..073094ea789d9 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 d82a736963a2d..fe21490436557 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 0000000000000..d9a98622c4271 --- /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 0000000000000..60a12bfd6fb65 --- /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 0000000000000..630909a0a1629 --- /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 6350d9c118f6d..7b2179bddfdfc 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 13b0f9d5ee388..190148881148e 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 fcf19f17958fc..cff8538095d99 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 87e1ed8317c68..0c81ee5eced85 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 073094ea789d9..73ff69eec4ed7 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 ead2f28e609a1..3fd9a637605b5 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 fe21490436557..cf9c279cd2f16 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 d9a98622c4271..080cf13b5dac2 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 60a12bfd6fb65..a8a8028295640 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 630909a0a1629..e2a4d9ffd57cb 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 3c5b6e12b9688..f3cc94aeff01c 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 cfcb060c46e37..a0db808925021 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 6d053253fc3dd..362c08e0d7790 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 c5e8622bc85c5..3ea33c3d2338e 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 13013f646e593..745faaddda6ed 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 117dda092223e..21153973dff19 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 bfaa5dadfa59e..69e46ab473622 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 8ac2066a6b24d..ffae8366b88c3 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 a7284a70a1ff6..045c269d62a3f 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 dbd4a53d8367c..53d92c089eafe 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 d926b7b84ea74..d23dd29f81551 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 0000000000000..0ef75792b7ae2 --- /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 0000000000000..14a5f822d600a --- /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 0000000000000..ea63953af0459 --- /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 0000000000000..a8969ede4e077 --- /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 4ce6e86669532..ca999f241f77f 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 07d60fac082a7..a09c3c6609065 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 d7b582fc8bdd7..b997e4ce85fb9 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 a88d7f51ac0a5..ebaba019cfd00 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 f6029eee441d8..50b6ca585cf67 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 41e8d3fc70924..76e890b3a2e3e 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 045c269d62a3f..5193db5a35d09 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 53d92c089eafe..881ff9baf18cf 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 d23dd29f81551..0c71fdccae087 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 0ef75792b7ae2..65ff555209a69 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 14a5f822d600a..9eee8f371874a 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 ea63953af0459..10743a7d04c66 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 a8969ede4e077..bc9e335016457 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 ca999f241f77f..738045595c0bc 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 a09c3c6609065..9e0e7b5def980 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 ebaba019cfd00..11dc34378758f 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 50b6ca585cf67..b255608274130 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 745faaddda6ed..08d41adf9e7ba 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 cff8538095d99..b226b87812377 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 5193db5a35d09..4debe3048572b 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 881ff9baf18cf..46f4082f0c7f9 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 0c71fdccae087..2f88fe8dcd5d7 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 0000000000000..635d0ab9652d1 --- /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 e458f0d254f66..e609b4b1bdb03 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 dd5ca1c9b5b7e..6c1a9edaa110d 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 0000000000000..bf5e70d9a05f8 --- /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 0000000000000..a49a6658f8b45 --- /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 0000000000000..3aa2feb5ecd82 --- /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 0000000000000..c9487ed7fc3a6 --- /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 0000000000000..e47c926520b63 --- /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 0000000000000..323b5a23b247b --- /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 0000000000000..55159efb5bfe5 --- /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 0000000000000..38f4da85a49ca --- /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 0000000000000..a18c9bf893449 --- /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 635d0ab9652d1..43248bccc13d5 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 bf5e70d9a05f8..672b4c318a8da 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 a49a6658f8b45..5ac1edf8e9907 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 c9487ed7fc3a6..a774faa0a673b 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 e47c926520b63..4a4bbc18728e9 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 55159efb5bfe5..fdb49ac4d9065 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 38f4da85a49ca..1f2ef7ece391e 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 21153973dff19..5e42cf7e4f3f6 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 078dcef19273b..727b59f1f432a 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 036ad3e0d150c..e3d940ad2a44c 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 f257378842bea..2d8920ccc42f9 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 29d79b078ac1f..69451c17ee7a6 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 86d89942cc051..2cfd75863081b 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 44ab8ebb50aa6..8e59e4375d2e8 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 9358c20ab95a5..e72edf2a8e318 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 fde27f2169069..aa2da21740032 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 12197666b30d8..5c17b243d7c0b 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 9bf7b1949c4e1..86b5d472a5203 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 4debe3048572b..04917871c406b 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 46f4082f0c7f9..316645e4066a2 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 5ab28b5c70c11..39301b5344aba 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 0000000000000..9640083f764f4 --- /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 0000000000000..061c05e98d067 --- /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 0000000000000..aba461e51f728 --- /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 39301b5344aba..87329ee5e14ac 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 9640083f764f4..9d5e872bd78fd 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 1d2d3eb12e114..4df1e3299ed9c 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 972e24aac5127..890639646228d 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 5aacca4514654..1f70f11bd677d 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 061c05e98d067..64aaa53be5cae 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 aba461e51f728..d9d59a611a019 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 9d5e872bd78fd..6564666d186b3 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 64aaa53be5cae..f96a7c97f1aa6 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 d9d59a611a019..7352b089d6b50 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 | 180 +++++++++----------- tests/ui/tuple_array_conversions.stderr | 6 +- 3 files changed, 89 insertions(+), 98 deletions(-) diff --git a/book/src/lint_configuration.md b/book/src/lint_configuration.md index 8bb3a57ba9a32..ae0b51403167e 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 6564666d186b3..bd983306508ba 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); - } - - 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| { + }, + ) || should_lint( + cx, + elements, + |(i, expr)| { + if let ExprKind::Field(path, field) = expr.kind && field.as_str() == i.to_string() { + 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 @@ -108,29 +100,20 @@ 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; - }; - - 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 +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 { @@ -140,32 +123,22 @@ fn check_tuple<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>) -> bool { ); } - false - }) - { - return emit_lint(cx, expr, ToType::Tuple); - } + 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)); + }; - 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| { + None + }, + |(first_id, local)| { if let Node::Pat(pat) = local && let parent = parent_pat(cx, pat) && parent.hir_id == first_id @@ -177,12 +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); } - - 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 7352b089d6b50..be653e8efb799 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 f4e56489b096f..140dc66badb0e 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 ee7f2b0631ad6..7b848ead78467 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 9c139deb95f2d..36f77cf1bdb6e 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 ab8ce356ec7b5..3bdac0b0a6b7b 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 140dc66badb0e..fffa8a380c2f8 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 0d2e1eee64384..4475d914cedb0 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 67913f7392c04..78965b7d6f74b 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 38372378168e2..e973e5ba2fb1e 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 2c013b6b6fe1e..c7fa253bdca26 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 ff39c6a0a6c3d..14d822083d8ba 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 52bc2010207ad..9d9ee6ba30792 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 0000000000000..9f92524d356d4 --- /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 b1d3b61aea370..a8d03bb95e687 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 1f70f11bd677d..3637476c40872 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 0000000000000..f43519dd44fa7 --- /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 0000000000000..1a17435b45956 --- /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 f43519dd44fa7..e00371eb22887 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 1a17435b45956..0c8a08e6c7d3a 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 9f92524d356d4..a1d83cf141990 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 0c8a08e6c7d3a..2c0b0c67fd162 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 a8d03bb95e687..2cd7ca02755f7 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 e00371eb22887..4521e9fa1a502 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 ae0b51403167e..60d7ce6e61559 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 a1d83cf141990..576a58499b154 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 2cd7ca02755f7..24dbe8c1d7518 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 890639646228d..f1d05c7529bef 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 2c0b0c67fd162..a0cf5b3b5fc8a 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 068820801dfe0..dd3cda8ec5277 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 6e84df5c693b9..20b1c656d3558 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 a2938ab4caf37..227275066cc62 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 dce6f2fc27269..0fd37c640aef8 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 2483390a24398..64aa1d874afe5 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]]