From b12ef56efd242f9a9a2f947cb3b689c8c5cb786f Mon Sep 17 00:00:00 2001 From: Samuel Tardieu Date: Sun, 22 Feb 2026 11:37:44 +0100 Subject: [PATCH] Remove `no-rustfix` marker for tests with valid suggestions --- tests/ui/crashes/ice-6250.fixed | 19 + tests/ui/crashes/ice-6250.rs | 3 +- tests/ui/crashes/ice-6250.stderr | 4 +- tests/ui/crashes/ice-9041.fixed | 12 + tests/ui/crashes/ice-9041.rs | 4 +- tests/ui/crashes/ice-9041.stderr | 2 +- .../ui/manual_memcpy/with_loop_counters.fixed | 55 +++ tests/ui/manual_memcpy/with_loop_counters.rs | 3 +- .../manual_memcpy/with_loop_counters.stderr | 22 +- .../manual_memcpy/without_loop_counters.fixed | 175 +++++++++ .../ui/manual_memcpy/without_loop_counters.rs | 4 +- tests/ui/map_flatten.fixed | 69 ++++ tests/ui/map_flatten.rs | 4 +- tests/ui/needless_collect_indirect.fixed | 344 ++++++++++++++++++ tests/ui/needless_collect_indirect.rs | 10 +- tests/ui/needless_collect_indirect.stderr | 32 +- tests/ui/track-diagnostics-clippy.fixed | 22 ++ tests/ui/track-diagnostics-clippy.rs | 1 - tests/ui/transmute_ref_to_ref.fixed | 38 ++ tests/ui/transmute_ref_to_ref.rs | 4 +- tests/ui/transmute_ref_to_ref.stderr | 12 +- tests/ui/transmute_ref_to_ref_no_std.fixed | 30 ++ tests/ui/transmute_ref_to_ref_no_std.rs | 4 +- tests/ui/transmute_ref_to_ref_no_std.stderr | 8 +- 24 files changed, 825 insertions(+), 56 deletions(-) create mode 100644 tests/ui/crashes/ice-6250.fixed create mode 100644 tests/ui/crashes/ice-9041.fixed create mode 100644 tests/ui/manual_memcpy/with_loop_counters.fixed create mode 100644 tests/ui/manual_memcpy/without_loop_counters.fixed create mode 100644 tests/ui/map_flatten.fixed create mode 100644 tests/ui/needless_collect_indirect.fixed create mode 100644 tests/ui/track-diagnostics-clippy.fixed create mode 100644 tests/ui/transmute_ref_to_ref.fixed create mode 100644 tests/ui/transmute_ref_to_ref_no_std.fixed diff --git a/tests/ui/crashes/ice-6250.fixed b/tests/ui/crashes/ice-6250.fixed new file mode 100644 index 000000000000..71b3c90d56b0 --- /dev/null +++ b/tests/ui/crashes/ice-6250.fixed @@ -0,0 +1,19 @@ +// originally from glacier/fixed/77218.rs +// ice while adjusting... +#![expect(clippy::useless_vec)] + +pub struct Cache { + data: Vec, +} + +pub fn list_data(cache: &Cache, key: usize) { + for reference in vec![1, 2, 3] { + if + /* let */ + let Some(reference) = cache.data.get(key) { + //~^ ERROR: mismatched types + //~| ERROR: mismatched types + unimplemented!() + } + } +} diff --git a/tests/ui/crashes/ice-6250.rs b/tests/ui/crashes/ice-6250.rs index 65cdce793142..8c6100e2054d 100644 --- a/tests/ui/crashes/ice-6250.rs +++ b/tests/ui/crashes/ice-6250.rs @@ -1,6 +1,7 @@ // originally from glacier/fixed/77218.rs // ice while adjusting... -//@no-rustfix +#![expect(clippy::useless_vec)] + pub struct Cache { data: Vec, } diff --git a/tests/ui/crashes/ice-6250.stderr b/tests/ui/crashes/ice-6250.stderr index c126547611f3..83a7ef9fd2cf 100644 --- a/tests/ui/crashes/ice-6250.stderr +++ b/tests/ui/crashes/ice-6250.stderr @@ -1,5 +1,5 @@ error[E0308]: mismatched types - --> tests/ui/crashes/ice-6250.rs:12:14 + --> tests/ui/crashes/ice-6250.rs:13:14 | LL | for reference in vec![1, 2, 3] { | --------- expected due to the type of this binding @@ -8,7 +8,7 @@ LL | Some(reference) = cache.data.get(key) { | ^^^^^^^^^ expected integer, found `&i32` error[E0308]: mismatched types - --> tests/ui/crashes/ice-6250.rs:12:9 + --> tests/ui/crashes/ice-6250.rs:13:9 | LL | Some(reference) = cache.data.get(key) { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `bool`, found `()` diff --git a/tests/ui/crashes/ice-9041.fixed b/tests/ui/crashes/ice-9041.fixed new file mode 100644 index 000000000000..32399e4255d1 --- /dev/null +++ b/tests/ui/crashes/ice-9041.fixed @@ -0,0 +1,12 @@ +#![warn(clippy::search_is_some)] +#![allow(clippy::needless_borrow)] + +pub struct Thing; + +pub fn has_thing(things: &[Thing]) -> bool { + let is_thing_ready = |_peer: &Thing| -> bool { todo!() }; + things.iter().any(|p| is_thing_ready(&p)) + //~^ search_is_some +} + +fn main() {} diff --git a/tests/ui/crashes/ice-9041.rs b/tests/ui/crashes/ice-9041.rs index fae3233ba2f5..55e88fa6da5a 100644 --- a/tests/ui/crashes/ice-9041.rs +++ b/tests/ui/crashes/ice-9041.rs @@ -1,6 +1,8 @@ #![warn(clippy::search_is_some)] +#![allow(clippy::needless_borrow)] + pub struct Thing; -//@no-rustfix + pub fn has_thing(things: &[Thing]) -> bool { let is_thing_ready = |_peer: &Thing| -> bool { todo!() }; things.iter().find(|p| is_thing_ready(p)).is_some() diff --git a/tests/ui/crashes/ice-9041.stderr b/tests/ui/crashes/ice-9041.stderr index 256c8b833034..98bdff9bbfac 100644 --- a/tests/ui/crashes/ice-9041.stderr +++ b/tests/ui/crashes/ice-9041.stderr @@ -1,5 +1,5 @@ error: called `is_some()` after searching an `Iterator` with `find` - --> tests/ui/crashes/ice-9041.rs:6:19 + --> tests/ui/crashes/ice-9041.rs:8:19 | LL | things.iter().find(|p| is_thing_ready(p)).is_some() | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `any(|p| is_thing_ready(&p))` diff --git a/tests/ui/manual_memcpy/with_loop_counters.fixed b/tests/ui/manual_memcpy/with_loop_counters.fixed new file mode 100644 index 000000000000..8fd8b9cd0ffd --- /dev/null +++ b/tests/ui/manual_memcpy/with_loop_counters.fixed @@ -0,0 +1,55 @@ +#![warn(clippy::needless_range_loop, clippy::manual_memcpy)] +#![allow(clippy::redundant_slicing, clippy::identity_op)] + +pub fn manual_copy_with_counters(src: &[i32], dst: &mut [i32], dst2: &mut [i32]) { + let mut count = 0; + dst[3..src.len()].copy_from_slice(&src[..(src.len() - 3)]); + + let mut count = 0; + dst[..(src.len() - 3)].copy_from_slice(&src[3..]); + + let mut count = 3; + dst[3..(src.len() + 3)].copy_from_slice(&src[..]); + + let mut count = 3; + dst[..src.len()].copy_from_slice(&src[3..(src.len() + 3)]); + + let mut count = 0; + dst[3..(3 + src.len())].copy_from_slice(&src[..(3 + src.len() - 3)]); + + let mut count = 3; + dst[5..src.len()].copy_from_slice(&src[(3 - 2)..((src.len() - 2) + 3 - 5)]); + + let mut count = 2; + dst.copy_from_slice(&src[2..(dst.len() + 2)]); + + let mut count = 5; + dst[3..10].copy_from_slice(&src[5..(10 + 5 - 3)]); + + let mut count = 3; + let mut count2 = 30; + dst[3..(src.len() + 3)].copy_from_slice(&src[..]); + dst2[30..(src.len() + 30)].copy_from_slice(&src[..]); + + // make sure parentheses are added properly to bitwise operators, which have lower precedence than + // arithmetic ones + let mut count = 0 << 1; + dst[(0 << 1)..((1 << 1) + (0 << 1))].copy_from_slice(&src[2..((1 << 1) + 2)]); + + // make sure incrementing expressions without semicolons at the end of loops are handled correctly. + let mut count = 0; + dst[3..src.len()].copy_from_slice(&src[..(src.len() - 3)]); + + // make sure ones where the increment is not at the end of the loop. + // As a possible enhancement, one could adjust the offset in the suggestion according to + // the position. For example, if the increment is at the top of the loop; + // treating the loop counter as if it were initialized 1 greater than the original value. + let mut count = 0; + #[allow(clippy::needless_range_loop)] + for i in 0..src.len() { + count += 1; + dst[i] = src[count]; + } +} + +fn main() {} diff --git a/tests/ui/manual_memcpy/with_loop_counters.rs b/tests/ui/manual_memcpy/with_loop_counters.rs index c83a26cab21a..9296cefef4f0 100644 --- a/tests/ui/manual_memcpy/with_loop_counters.rs +++ b/tests/ui/manual_memcpy/with_loop_counters.rs @@ -1,5 +1,6 @@ #![warn(clippy::needless_range_loop, clippy::manual_memcpy)] -//@no-rustfix +#![allow(clippy::redundant_slicing, clippy::identity_op)] + pub fn manual_copy_with_counters(src: &[i32], dst: &mut [i32], dst2: &mut [i32]) { let mut count = 0; for i in 3..src.len() { diff --git a/tests/ui/manual_memcpy/with_loop_counters.stderr b/tests/ui/manual_memcpy/with_loop_counters.stderr index 70da8309f398..fafa855bad79 100644 --- a/tests/ui/manual_memcpy/with_loop_counters.stderr +++ b/tests/ui/manual_memcpy/with_loop_counters.stderr @@ -1,5 +1,5 @@ error: it looks like you're manually copying between slices - --> tests/ui/manual_memcpy/with_loop_counters.rs:5:5 + --> tests/ui/manual_memcpy/with_loop_counters.rs:6:5 | LL | / for i in 3..src.len() { LL | | @@ -13,7 +13,7 @@ LL | | } = help: to override `-D warnings` add `#[allow(clippy::manual_memcpy)]` error: it looks like you're manually copying between slices - --> tests/ui/manual_memcpy/with_loop_counters.rs:13:5 + --> tests/ui/manual_memcpy/with_loop_counters.rs:14:5 | LL | / for i in 3..src.len() { LL | | @@ -24,7 +24,7 @@ LL | | } | |_____^ help: try replacing the loop by: `dst[..(src.len() - 3)].copy_from_slice(&src[3..]);` error: it looks like you're manually copying between slices - --> tests/ui/manual_memcpy/with_loop_counters.rs:21:5 + --> tests/ui/manual_memcpy/with_loop_counters.rs:22:5 | LL | / for i in 0..src.len() { LL | | @@ -35,7 +35,7 @@ LL | | } | |_____^ help: try replacing the loop by: `dst[3..(src.len() + 3)].copy_from_slice(&src[..]);` error: it looks like you're manually copying between slices - --> tests/ui/manual_memcpy/with_loop_counters.rs:29:5 + --> tests/ui/manual_memcpy/with_loop_counters.rs:30:5 | LL | / for i in 0..src.len() { LL | | @@ -46,7 +46,7 @@ LL | | } | |_____^ help: try replacing the loop by: `dst[..src.len()].copy_from_slice(&src[3..(src.len() + 3)]);` error: it looks like you're manually copying between slices - --> tests/ui/manual_memcpy/with_loop_counters.rs:37:5 + --> tests/ui/manual_memcpy/with_loop_counters.rs:38:5 | LL | / for i in 3..(3 + src.len()) { LL | | @@ -57,7 +57,7 @@ LL | | } | |_____^ help: try replacing the loop by: `dst[3..(3 + src.len())].copy_from_slice(&src[..(3 + src.len() - 3)]);` error: it looks like you're manually copying between slices - --> tests/ui/manual_memcpy/with_loop_counters.rs:45:5 + --> tests/ui/manual_memcpy/with_loop_counters.rs:46:5 | LL | / for i in 5..src.len() { LL | | @@ -68,7 +68,7 @@ LL | | } | |_____^ help: try replacing the loop by: `dst[5..src.len()].copy_from_slice(&src[(3 - 2)..((src.len() - 2) + 3 - 5)]);` error: it looks like you're manually copying between slices - --> tests/ui/manual_memcpy/with_loop_counters.rs:53:5 + --> tests/ui/manual_memcpy/with_loop_counters.rs:54:5 | LL | / for i in 0..dst.len() { LL | | @@ -79,7 +79,7 @@ LL | | } | |_____^ help: try replacing the loop by: `dst.copy_from_slice(&src[2..(dst.len() + 2)]);` error: it looks like you're manually copying between slices - --> tests/ui/manual_memcpy/with_loop_counters.rs:61:5 + --> tests/ui/manual_memcpy/with_loop_counters.rs:62:5 | LL | / for i in 3..10 { LL | | @@ -90,7 +90,7 @@ LL | | } | |_____^ help: try replacing the loop by: `dst[3..10].copy_from_slice(&src[5..(10 + 5 - 3)]);` error: it looks like you're manually copying between slices - --> tests/ui/manual_memcpy/with_loop_counters.rs:70:5 + --> tests/ui/manual_memcpy/with_loop_counters.rs:71:5 | LL | / for i in 0..src.len() { LL | | @@ -108,7 +108,7 @@ LL + dst2[30..(src.len() + 30)].copy_from_slice(&src[..]); | error: it looks like you're manually copying between slices - --> tests/ui/manual_memcpy/with_loop_counters.rs:82:5 + --> tests/ui/manual_memcpy/with_loop_counters.rs:83:5 | LL | / for i in 0..1 << 1 { LL | | @@ -119,7 +119,7 @@ LL | | } | |_____^ help: try replacing the loop by: `dst[(0 << 1)..((1 << 1) + (0 << 1))].copy_from_slice(&src[2..((1 << 1) + 2)]);` error: it looks like you're manually copying between slices - --> tests/ui/manual_memcpy/with_loop_counters.rs:91:5 + --> tests/ui/manual_memcpy/with_loop_counters.rs:92:5 | LL | / for i in 3..src.len() { LL | | diff --git a/tests/ui/manual_memcpy/without_loop_counters.fixed b/tests/ui/manual_memcpy/without_loop_counters.fixed new file mode 100644 index 000000000000..8502c740b712 --- /dev/null +++ b/tests/ui/manual_memcpy/without_loop_counters.fixed @@ -0,0 +1,175 @@ +#![warn(clippy::manual_memcpy)] +#![allow( + clippy::assigning_clones, + clippy::useless_vec, + clippy::needless_range_loop, + clippy::manual_slice_fill, + clippy::redundant_slicing +)] + +const LOOP_OFFSET: usize = 5000; + +pub fn manual_copy(src: &[i32], dst: &mut [i32], dst2: &mut [i32]) { + // plain manual memcpy + dst[..src.len()].copy_from_slice(&src[..]); + + // dst offset memcpy + dst[10..(src.len() + 10)].copy_from_slice(&src[..]); + + // src offset memcpy + dst[..src.len()].copy_from_slice(&src[10..(src.len() + 10)]); + + // src offset memcpy + dst[11..src.len()].copy_from_slice(&src[(11 - 10)..(src.len() - 10)]); + + // overwrite entire dst + dst.copy_from_slice(&src[..dst.len()]); + + // manual copy with branch - can't easily convert to memcpy! + for i in 0..src.len() { + dst[i] = src[i]; + if dst[i] > 5 { + break; + } + } + + // multiple copies - suggest two memcpy statements + dst[10..256].copy_from_slice(&src[(10 - 5)..(256 - 5)]); + dst2[(10 + 500)..(256 + 500)].copy_from_slice(&src[10..256]); + + // this is a reversal - the copy lint shouldn't be triggered + for i in 10..LOOP_OFFSET { + dst[i + LOOP_OFFSET] = src[LOOP_OFFSET - i]; + } + + let some_var = 5; + // Offset in variable + dst[(10 + LOOP_OFFSET)..(LOOP_OFFSET + LOOP_OFFSET)].copy_from_slice(&src[(10 - some_var)..(LOOP_OFFSET - some_var)]); + + // Non continuous copy - don't trigger lint + for i in 0..10 { + dst[i + i] = src[i]; + } + + let src_vec = vec![1, 2, 3, 4, 5]; + let mut dst_vec = vec![0, 0, 0, 0, 0]; + + // make sure vectors are supported + dst_vec[..src_vec.len()].copy_from_slice(&src_vec[..]); + + // lint should not trigger when either + // source or destination type is not + // slice-like, like DummyStruct + struct DummyStruct(i32); + + impl ::std::ops::Index for DummyStruct { + type Output = i32; + + fn index(&self, _: usize) -> &i32 { + &self.0 + } + } + + let src = DummyStruct(5); + let mut dst_vec = vec![0; 10]; + + for i in 0..10 { + dst_vec[i] = src[i]; + } + + // Simplify suggestion (issue #3004) + let src = [0, 1, 2, 3, 4]; + let mut dst = [0, 0, 0, 0, 0, 0]; + let from = 1; + + dst[from..(from + src.len())].copy_from_slice(&src[..(from + src.len() - from)]); + + dst[from..(from + 3)].copy_from_slice(&src[..(from + 3 - from)]); + + #[allow(clippy::identity_op)] + dst[..5].copy_from_slice(&src); + + #[allow(clippy::reversed_empty_ranges)] + dst[..0].copy_from_slice(&src[..0]); + + // `RangeTo` `for` loop - don't trigger lint + for i in 0.. { + dst[i] = src[i]; + } + + // VecDeque - ideally this would work, but would require something like `range_as_slices` + let mut dst = std::collections::VecDeque::from_iter([0; 5]); + let src = std::collections::VecDeque::from_iter([0, 1, 2, 3, 4]); + for i in 0..dst.len() { + dst[i] = src[i]; + } + let src = vec![0, 1, 2, 3, 4]; + for i in 0..dst.len() { + dst[i] = src[i]; + } + + // Range is equal to array length + let src = [0, 1, 2, 3, 4]; + let mut dst = [0; 4]; + dst.copy_from_slice(&src[..4]); + + let mut dst = [0; 6]; + dst[..5].copy_from_slice(&src); + + let mut dst = [0; 5]; + dst.copy_from_slice(&src); + + // Don't trigger lint for following multi-dimensional arrays + let src = [[0; 5]; 5]; + for i in 0..4 { + dst[i] = src[i + 1][i]; + } + for i in 0..5 { + dst[i] = src[i][i]; + } + for i in 0..5 { + dst[i] = src[i][3]; + } + + let src = [0; 5]; + let mut dst = [[0; 5]; 5]; + for i in 0..5 { + dst[i][i] = src[i]; + } + + let src = [[[0; 5]; 5]; 5]; + let mut dst = [0; 5]; + for i in 0..5 { + dst[i] = src[i][i][i]; + } + for i in 0..5 { + dst[i] = src[i][i][0]; + } + for i in 0..5 { + dst[i] = src[i][0][i]; + } + for i in 0..5 { + dst[i] = src[0][i][i]; + } + for i in 0..5 { + dst[i] = src[0][i][1]; + } + for i in 0..5 { + dst[i] = src[i][0][1]; + } + + // Trigger lint + let src = [[0; 5]; 5]; + let mut dst = [0; 5]; + dst.copy_from_slice(&src[0]); + + let src = [[[0; 5]; 5]; 5]; + dst.copy_from_slice(&src[0][1]); +} + +#[warn(clippy::needless_range_loop, clippy::manual_memcpy)] +pub fn manual_clone(src: &[String], dst: &mut [String]) { + dst[..src.len()].clone_from_slice(&src[..]); +} + +fn main() {} diff --git a/tests/ui/manual_memcpy/without_loop_counters.rs b/tests/ui/manual_memcpy/without_loop_counters.rs index a3b8763812d7..fc55102fca45 100644 --- a/tests/ui/manual_memcpy/without_loop_counters.rs +++ b/tests/ui/manual_memcpy/without_loop_counters.rs @@ -3,10 +3,10 @@ clippy::assigning_clones, clippy::useless_vec, clippy::needless_range_loop, - clippy::manual_slice_fill + clippy::manual_slice_fill, + clippy::redundant_slicing )] -//@no-rustfix const LOOP_OFFSET: usize = 5000; pub fn manual_copy(src: &[i32], dst: &mut [i32], dst2: &mut [i32]) { diff --git a/tests/ui/map_flatten.fixed b/tests/ui/map_flatten.fixed new file mode 100644 index 000000000000..168db8dd6291 --- /dev/null +++ b/tests/ui/map_flatten.fixed @@ -0,0 +1,69 @@ +#![warn(clippy::map_flatten)] +#![allow(clippy::unnecessary_filter_map)] + +// issue #8506, multi-line +#[rustfmt::skip] +fn long_span() { + let _: Option = Some(1) + .and_then(|x| { + //~^ map_flatten + + + if x <= 5 { + Some(x) + } else { + None + } + }); + + let _: Result = Ok(1) + .and_then(|x| { + //~^ map_flatten + + if x == 1 { + Ok(x) + } else { + Err(0) + } + }); + + let result: Result = Ok(2); + fn do_something() { } + let _: Result = result + .and_then(|res| { + //~^ map_flatten + + if res > 0 { + do_something(); + Ok(res) + } else { + Err(0) + } + }); + + let _: Vec<_> = vec![5_i8; 6] + .into_iter() + .filter_map(|some_value| { + //~^ map_flatten + + if some_value > 3 { + Some(some_value) + } else { + None + } + }) + .collect(); +} + +#[allow(clippy::useless_vec)] +fn no_suggestion_if_comments_present() { + let vec = vec![vec![1, 2, 3]]; + let _ = vec + .iter() + // a lovely comment explaining the code in very detail + .flat_map(|x| x.iter()); +} + +fn main() { + long_span(); +} diff --git a/tests/ui/map_flatten.rs b/tests/ui/map_flatten.rs index 0970da8039a4..df4edd8f16ee 100644 --- a/tests/ui/map_flatten.rs +++ b/tests/ui/map_flatten.rs @@ -1,6 +1,6 @@ #![warn(clippy::map_flatten)] +#![allow(clippy::unnecessary_filter_map)] -//@no-rustfix // issue #8506, multi-line #[rustfmt::skip] fn long_span() { @@ -43,7 +43,7 @@ fn do_something() { } } }) .flatten(); - + let _: Vec<_> = vec![5_i8; 6] .into_iter() .map(|some_value| { diff --git a/tests/ui/needless_collect_indirect.fixed b/tests/ui/needless_collect_indirect.fixed new file mode 100644 index 000000000000..22b9bb6f6a20 --- /dev/null +++ b/tests/ui/needless_collect_indirect.fixed @@ -0,0 +1,344 @@ +#![allow( + clippy::uninlined_format_args, + clippy::useless_vec, + clippy::needless_ifs, + clippy::iter_next_slice, + clippy::iter_count +)] +#![warn(clippy::needless_collect)] + +use std::collections::{BinaryHeap, HashMap, HashSet, LinkedList, VecDeque}; + +fn main() { + let sample = [1; 5]; + + //~^ needless_collect + + sample.iter().map(|x| (x, x + 1)).collect::>(); + + //~^ needless_collect + + sample.iter().count(); + + //~^ needless_collect + + sample.iter().next().is_none(); + + //~^ needless_collect + + sample.iter().any(|x| x == &5); + let indirect_negative = sample.iter().collect::>(); + indirect_negative.len(); + indirect_negative + .into_iter() + .map(|x| (*x, *x + 1)) + .collect::>(); + + // #6202 + let a = "a".to_string(); + let sample = vec![a.clone(), "b".to_string(), "c".to_string()]; + + //~^ needless_collect + + sample.into_iter().any(|x| x == a); + + // Fix #5991 + let vec_a = vec![1, 2, 3, 4, 5, 6, 7, 8, 9, 10]; + let vec_b = vec_a.iter().collect::>(); + if vec_b.len() > 3 {} + let other_vec = vec![1, 3, 12, 4, 16, 2]; + let we_got_the_same_numbers = other_vec.iter().filter(|item| vec_b.contains(item)).collect::>(); + + // Fix #6297 + let sample = [1; 5]; + let multiple_indirect = sample.iter().collect::>(); + let sample2 = vec![2, 3]; + if multiple_indirect.is_empty() { + // do something + } else { + let found = sample2 + .iter() + .filter(|i| multiple_indirect.iter().any(|s| **s % **i == 0)) + .collect::>(); + } +} + +mod issue7110 { + // #7110 - lint for type annotation cases + use super::*; + + fn lint_vec(string: &str) -> usize { + + //~^ needless_collect + + string.split('/').count() + } + fn lint_vec_deque() -> usize { + let sample = [1; 5]; + + //~^ needless_collect + + sample.iter().count() + } + fn lint_linked_list() -> usize { + let sample = [1; 5]; + + //~^ needless_collect + + sample.iter().count() + } + fn lint_binary_heap() -> usize { + let sample = [1; 5]; + + //~^ needless_collect + + sample.iter().count() + } + fn dont_lint(string: &str) -> usize { + let buffer: Vec<&str> = string.split('/').collect(); + for buff in &buffer { + println!("{}", buff); + } + buffer.len() + } +} + +mod issue7975 { + use super::*; + + fn direct_mapping_with_used_mutable_reference() -> Vec<()> { + let test_vec: Vec<()> = vec![]; + let mut vec_2: Vec<()> = vec![]; + let mut_ref = &mut vec_2; + let collected_vec: Vec<_> = test_vec.into_iter().map(|_| mut_ref.push(())).collect(); + collected_vec.into_iter().map(|_| mut_ref.push(())).collect() + } + + fn indirectly_mapping_with_used_mutable_reference() -> Vec<()> { + let test_vec: Vec<()> = vec![]; + let mut vec_2: Vec<()> = vec![]; + let mut_ref = &mut vec_2; + let collected_vec: Vec<_> = test_vec.into_iter().map(|_| mut_ref.push(())).collect(); + let iter = collected_vec.into_iter(); + iter.map(|_| mut_ref.push(())).collect() + } + + fn indirect_collect_after_indirect_mapping_with_used_mutable_reference() -> Vec<()> { + let test_vec: Vec<()> = vec![]; + let mut vec_2: Vec<()> = vec![]; + let mut_ref = &mut vec_2; + let collected_vec: Vec<_> = test_vec.into_iter().map(|_| mut_ref.push(())).collect(); + let iter = collected_vec.into_iter(); + let mapped_iter = iter.map(|_| mut_ref.push(())); + mapped_iter.collect() + } +} + +fn allow_test() { + #[allow(clippy::needless_collect)] + let v = [1].iter().collect::>(); + v.into_iter().collect::>(); +} + +mod issue_8553 { + fn test_for() { + let vec = vec![1, 2]; + let w: Vec = vec.iter().map(|i| i * i).collect(); + + for i in 0..2 { + // Do not lint, because this method call is in the loop + w.contains(&i); + } + + for i in 0..2 { + + //~^ needless_collect + + let z: Vec = vec.iter().map(|k| k * k).collect(); + // Do lint + vec.iter().map(|k| k * k).any(|x| x == i); + for j in 0..2 { + // Do not lint, because this method call is in the loop + z.contains(&j); + } + } + + // Do not lint, because this variable is used. + w.contains(&0); + } + + fn test_while() { + let vec = vec![1, 2]; + let x: Vec = vec.iter().map(|i| i * i).collect(); + let mut n = 0; + while n > 1 { + // Do not lint, because this method call is in the loop + x.contains(&n); + n += 1; + } + + while n > 2 { + + //~^ needless_collect + + let z: Vec = vec.iter().map(|k| k * k).collect(); + // Do lint + vec.iter().map(|k| k * k).any(|x| x == n); + n += 1; + while n > 4 { + // Do not lint, because this method call is in the loop + z.contains(&n); + n += 1; + } + } + } + + fn test_loop() { + let vec = vec![1, 2]; + let x: Vec = vec.iter().map(|i| i * i).collect(); + let mut n = 0; + loop { + if n < 1 { + // Do not lint, because this method call is in the loop + x.contains(&n); + n += 1; + } else { + break; + } + } + + loop { + if n < 2 { + + //~^ needless_collect + + let z: Vec = vec.iter().map(|k| k * k).collect(); + // Do lint + vec.iter().map(|k| k * k).any(|x| x == n); + n += 1; + loop { + if n < 4 { + // Do not lint, because this method call is in the loop + z.contains(&n); + n += 1; + } else { + break; + } + } + } else { + break; + } + } + } + + fn test_while_let() { + let vec = vec![1, 2]; + let x: Vec = vec.iter().map(|i| i * i).collect(); + let optional = Some(0); + let mut n = 0; + while let Some(value) = optional { + if n < 1 { + // Do not lint, because this method call is in the loop + x.contains(&n); + n += 1; + } else { + break; + } + } + + while let Some(value) = optional { + + //~^ needless_collect + + let z: Vec = vec.iter().map(|k| k * k).collect(); + if n < 2 { + // Do lint + vec.iter().map(|k| k * k).any(|x| x == n); + n += 1; + } else { + break; + } + + while let Some(value) = optional { + if n < 4 { + // Do not lint, because this method call is in the loop + z.contains(&n); + n += 1; + } else { + break; + } + } + } + } + + fn test_if_cond() { + let vec = vec![1, 2]; + let v: Vec = vec.iter().map(|i| i * i).collect(); + + //~^ needless_collect + + // Do lint + for _ in 0..v.iter().count() { + todo!(); + } + } + + fn test_if_cond_false_case() { + let vec = vec![1, 2]; + let v: Vec = vec.iter().map(|i| i * i).collect(); + let w = v.iter().collect::>(); + // Do not lint, because w is used. + for _ in 0..w.len() { + todo!(); + } + + w.len(); + } + + fn test_while_cond() { + let mut vec = vec![1, 2]; + let mut v: Vec = vec.iter().map(|i| i * i).collect(); + + //~^ needless_collect + + // Do lint + while 1 == v.iter().count() { + todo!(); + } + } + + fn test_while_cond_false_case() { + let mut vec = vec![1, 2]; + let mut v: Vec = vec.iter().map(|i| i * i).collect(); + let mut w = v.iter().collect::>(); + // Do not lint, because w is used. + while 1 == w.len() { + todo!(); + } + + w.len(); + } + + fn test_while_let_cond() { + let mut vec = vec![1, 2]; + let mut v: Vec = vec.iter().map(|i| i * i).collect(); + + //~^ needless_collect + + // Do lint + while let Some(i) = Some(v.iter().count()) { + todo!(); + } + } + + fn test_while_let_cond_false_case() { + let mut vec = vec![1, 2]; + let mut v: Vec = vec.iter().map(|i| i * i).collect(); + let mut w = v.iter().collect::>(); + // Do not lint, because w is used. + while let Some(i) = Some(w.len()) { + todo!(); + } + w.len(); + } +} diff --git a/tests/ui/needless_collect_indirect.rs b/tests/ui/needless_collect_indirect.rs index 69764becfe66..20b7ae91a6b8 100644 --- a/tests/ui/needless_collect_indirect.rs +++ b/tests/ui/needless_collect_indirect.rs @@ -1,6 +1,12 @@ -#![allow(clippy::uninlined_format_args, clippy::useless_vec, clippy::needless_ifs)] +#![allow( + clippy::uninlined_format_args, + clippy::useless_vec, + clippy::needless_ifs, + clippy::iter_next_slice, + clippy::iter_count +)] #![warn(clippy::needless_collect)] -//@no-rustfix + use std::collections::{BinaryHeap, HashMap, HashSet, LinkedList, VecDeque}; fn main() { diff --git a/tests/ui/needless_collect_indirect.stderr b/tests/ui/needless_collect_indirect.stderr index 24523c9f97b0..d34f1c37558d 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 - --> tests/ui/needless_collect_indirect.rs:8:39 + --> tests/ui/needless_collect_indirect.rs:14:39 | LL | let indirect_iter = sample.iter().collect::>(); | ^^^^^^^ @@ -18,7 +18,7 @@ LL ~ sample.iter().map(|x| (x, x + 1)).collect::>(); | error: avoid using `collect()` when not needed - --> tests/ui/needless_collect_indirect.rs:12:38 + --> tests/ui/needless_collect_indirect.rs:18:38 | LL | let indirect_len = sample.iter().collect::>(); | ^^^^^^^ @@ -35,7 +35,7 @@ LL ~ sample.iter().count(); | error: avoid using `collect()` when not needed - --> tests/ui/needless_collect_indirect.rs:16:40 + --> tests/ui/needless_collect_indirect.rs:22:40 | LL | let indirect_empty = sample.iter().collect::>(); | ^^^^^^^ @@ -52,7 +52,7 @@ LL ~ sample.iter().next().is_none(); | error: avoid using `collect()` when not needed - --> tests/ui/needless_collect_indirect.rs:20:43 + --> tests/ui/needless_collect_indirect.rs:26:43 | LL | let indirect_contains = sample.iter().collect::>(); | ^^^^^^^ @@ -69,7 +69,7 @@ LL ~ sample.iter().any(|x| x == &5); | error: avoid using `collect()` when not needed - --> tests/ui/needless_collect_indirect.rs:34:48 + --> tests/ui/needless_collect_indirect.rs:40:48 | LL | let non_copy_contains = sample.into_iter().collect::>(); | ^^^^^^^ @@ -86,7 +86,7 @@ LL ~ sample.into_iter().any(|x| x == a); | error: avoid using `collect()` when not needed - --> tests/ui/needless_collect_indirect.rs:65:51 + --> tests/ui/needless_collect_indirect.rs:71:51 | LL | let buffer: Vec<&str> = string.split('/').collect(); | ^^^^^^^ @@ -103,7 +103,7 @@ LL ~ string.split('/').count() | error: avoid using `collect()` when not needed - --> tests/ui/needless_collect_indirect.rs:72:55 + --> tests/ui/needless_collect_indirect.rs:78:55 | LL | let indirect_len: VecDeque<_> = sample.iter().collect(); | ^^^^^^^ @@ -120,7 +120,7 @@ LL ~ sample.iter().count() | error: avoid using `collect()` when not needed - --> tests/ui/needless_collect_indirect.rs:79:57 + --> tests/ui/needless_collect_indirect.rs:85:57 | LL | let indirect_len: LinkedList<_> = sample.iter().collect(); | ^^^^^^^ @@ -137,7 +137,7 @@ LL ~ sample.iter().count() | error: avoid using `collect()` when not needed - --> tests/ui/needless_collect_indirect.rs:86:57 + --> tests/ui/needless_collect_indirect.rs:92:57 | LL | let indirect_len: BinaryHeap<_> = sample.iter().collect(); | ^^^^^^^ @@ -154,7 +154,7 @@ LL ~ sample.iter().count() | error: avoid using `collect()` when not needed - --> tests/ui/needless_collect_indirect.rs:148:59 + --> tests/ui/needless_collect_indirect.rs:154:59 | LL | let y: Vec = vec.iter().map(|k| k * k).collect(); | ^^^^^^^ @@ -172,7 +172,7 @@ LL ~ vec.iter().map(|k| k * k).any(|x| x == i); | error: avoid using `collect()` when not needed - --> tests/ui/needless_collect_indirect.rs:175:59 + --> tests/ui/needless_collect_indirect.rs:181:59 | LL | let y: Vec = vec.iter().map(|k| k * k).collect(); | ^^^^^^^ @@ -190,7 +190,7 @@ LL ~ vec.iter().map(|k| k * k).any(|x| x == n); | error: avoid using `collect()` when not needed - --> tests/ui/needless_collect_indirect.rs:206:63 + --> tests/ui/needless_collect_indirect.rs:212:63 | LL | let y: Vec = vec.iter().map(|k| k * k).collect(); | ^^^^^^^ @@ -208,7 +208,7 @@ LL ~ vec.iter().map(|k| k * k).any(|x| x == n); | error: avoid using `collect()` when not needed - --> tests/ui/needless_collect_indirect.rs:244:59 + --> tests/ui/needless_collect_indirect.rs:250:59 | LL | let y: Vec = vec.iter().map(|k| k * k).collect(); | ^^^^^^^ @@ -226,7 +226,7 @@ LL ~ vec.iter().map(|k| k * k).any(|x| x == n); | error: avoid using `collect()` when not needed - --> tests/ui/needless_collect_indirect.rs:271:26 + --> tests/ui/needless_collect_indirect.rs:277:26 | LL | let w = v.iter().collect::>(); | ^^^^^^^ @@ -244,7 +244,7 @@ LL ~ for _ in 0..v.iter().count() { | error: avoid using `collect()` when not needed - --> tests/ui/needless_collect_indirect.rs:295:30 + --> tests/ui/needless_collect_indirect.rs:301:30 | LL | let mut w = v.iter().collect::>(); | ^^^^^^^ @@ -262,7 +262,7 @@ LL ~ while 1 == v.iter().count() { | error: avoid using `collect()` when not needed - --> tests/ui/needless_collect_indirect.rs:319:30 + --> tests/ui/needless_collect_indirect.rs:325:30 | LL | let mut w = v.iter().collect::>(); | ^^^^^^^ diff --git a/tests/ui/track-diagnostics-clippy.fixed b/tests/ui/track-diagnostics-clippy.fixed new file mode 100644 index 000000000000..f25ffa7e9afd --- /dev/null +++ b/tests/ui/track-diagnostics-clippy.fixed @@ -0,0 +1,22 @@ +//@compile-flags: -Z track-diagnostics + +// Normalize the emitted location so this doesn't need +// updating everytime someone adds or removes a line. +//@normalize-stderr-test: ".rs:\d+:\d+" -> ".rs:LL:CC" +//@normalize-stderr-test: "src/tools/clippy/" -> "" + +#![warn(clippy::let_and_return, clippy::unnecessary_cast)] + +fn main() { + // Check the provenance of a lint sent through `LintContext::span_lint()` + let a = 3u32; + let b = a; + //~^ unnecessary_cast + + // Check the provenance of a lint sent through `TyCtxt::node_span_lint()` + let c = { + + 42 + //~^ let_and_return + }; +} diff --git a/tests/ui/track-diagnostics-clippy.rs b/tests/ui/track-diagnostics-clippy.rs index 3bae23f19849..8fc1d996c002 100644 --- a/tests/ui/track-diagnostics-clippy.rs +++ b/tests/ui/track-diagnostics-clippy.rs @@ -1,5 +1,4 @@ //@compile-flags: -Z track-diagnostics -//@no-rustfix // Normalize the emitted location so this doesn't need // updating everytime someone adds or removes a line. diff --git a/tests/ui/transmute_ref_to_ref.fixed b/tests/ui/transmute_ref_to_ref.fixed new file mode 100644 index 000000000000..0ec59ea810ae --- /dev/null +++ b/tests/ui/transmute_ref_to_ref.fixed @@ -0,0 +1,38 @@ +#![deny(clippy::transmute_ptr_to_ptr)] +#![allow(dead_code, clippy::missing_transmute_annotations, clippy::cast_slice_different_sizes)] + +fn main() { + unsafe { + let single_u64: &[u64] = &[0xDEAD_BEEF_DEAD_BEEF]; + let bools: &[bool] = unsafe { &*(single_u64 as *const [u64] as *const [bool]) }; + //~^ transmute_ptr_to_ptr + + let a: &[u32] = &[0x12345678, 0x90ABCDEF, 0xFEDCBA09, 0x87654321]; + let b: &[u8] = unsafe { &*(a as *const [u32] as *const [u8]) }; + //~^ transmute_ptr_to_ptr + + let bytes = &[1u8, 2u8, 3u8, 4u8] as &[u8]; + let alt_slice: &[u32] = unsafe { &*(bytes as *const [u8] as *const [u32]) }; + //~^ transmute_ptr_to_ptr + } +} + +fn issue16104(make_ptr: fn() -> *const u32) { + macro_rules! call { + ($x:expr) => { + $x() + }; + } + macro_rules! take_ref { + ($x:expr) => { + &$x + }; + } + + unsafe { + let _: *const f32 = call!(make_ptr).cast::(); + //~^ transmute_ptr_to_ptr + let _: &f32 = &*(take_ref!(1u32) as *const u32 as *const f32); + //~^ transmute_ptr_to_ptr + } +} diff --git a/tests/ui/transmute_ref_to_ref.rs b/tests/ui/transmute_ref_to_ref.rs index ed8fb8083291..78f3d1fe0bb2 100644 --- a/tests/ui/transmute_ref_to_ref.rs +++ b/tests/ui/transmute_ref_to_ref.rs @@ -1,7 +1,5 @@ -//@no-rustfix - #![deny(clippy::transmute_ptr_to_ptr)] -#![allow(dead_code, clippy::missing_transmute_annotations)] +#![allow(dead_code, clippy::missing_transmute_annotations, clippy::cast_slice_different_sizes)] fn main() { unsafe { diff --git a/tests/ui/transmute_ref_to_ref.stderr b/tests/ui/transmute_ref_to_ref.stderr index 1b845ef859d8..13ee64574f7b 100644 --- a/tests/ui/transmute_ref_to_ref.stderr +++ b/tests/ui/transmute_ref_to_ref.stderr @@ -1,29 +1,29 @@ error: transmute from a reference to a reference - --> tests/ui/transmute_ref_to_ref.rs:9:39 + --> tests/ui/transmute_ref_to_ref.rs:7:39 | LL | let bools: &[bool] = unsafe { std::mem::transmute(single_u64) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `&*(single_u64 as *const [u64] as *const [bool])` | note: the lint level is defined here - --> tests/ui/transmute_ref_to_ref.rs:3:9 + --> tests/ui/transmute_ref_to_ref.rs:1:9 | LL | #![deny(clippy::transmute_ptr_to_ptr)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: transmute from a reference to a reference - --> tests/ui/transmute_ref_to_ref.rs:13:33 + --> tests/ui/transmute_ref_to_ref.rs:11:33 | LL | let b: &[u8] = unsafe { std::mem::transmute(a) }; | ^^^^^^^^^^^^^^^^^^^^^^ help: try: `&*(a as *const [u32] as *const [u8])` error: transmute from a reference to a reference - --> tests/ui/transmute_ref_to_ref.rs:17:42 + --> tests/ui/transmute_ref_to_ref.rs:15:42 | LL | let alt_slice: &[u32] = unsafe { std::mem::transmute(bytes) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `&*(bytes as *const [u8] as *const [u32])` error: transmute from a pointer to a pointer - --> tests/ui/transmute_ref_to_ref.rs:35:29 + --> tests/ui/transmute_ref_to_ref.rs:33:29 | LL | let _: *const f32 = std::mem::transmute(call!(make_ptr)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -35,7 +35,7 @@ LL + let _: *const f32 = call!(make_ptr).cast::(); | error: transmute from a reference to a reference - --> tests/ui/transmute_ref_to_ref.rs:37:23 + --> tests/ui/transmute_ref_to_ref.rs:35:23 | LL | let _: &f32 = std::mem::transmute(take_ref!(1u32)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `&*(take_ref!(1u32) as *const u32 as *const f32)` diff --git a/tests/ui/transmute_ref_to_ref_no_std.fixed b/tests/ui/transmute_ref_to_ref_no_std.fixed new file mode 100644 index 000000000000..3a1c75f16854 --- /dev/null +++ b/tests/ui/transmute_ref_to_ref_no_std.fixed @@ -0,0 +1,30 @@ +#![deny(clippy::transmute_ptr_to_ptr)] +#![allow(dead_code, clippy::missing_transmute_annotations, clippy::cast_slice_different_sizes)] +#![feature(lang_items)] +#![no_std] + +use core::panic::PanicInfo; + +#[lang = "eh_personality"] +extern "C" fn eh_personality() {} + +#[panic_handler] +fn panic(info: &PanicInfo) -> ! { + loop {} +} + +fn main() { + unsafe { + let single_u64: &[u64] = &[0xDEAD_BEEF_DEAD_BEEF]; + let bools: &[bool] = unsafe { &*(single_u64 as *const [u64] as *const [bool]) }; + //~^ transmute_ptr_to_ptr + + let a: &[u32] = &[0x12345678, 0x90ABCDEF, 0xFEDCBA09, 0x87654321]; + let b: &[u8] = unsafe { &*(a as *const [u32] as *const [u8]) }; + //~^ transmute_ptr_to_ptr + + let bytes = &[1u8, 2u8, 3u8, 4u8] as &[u8]; + let alt_slice: &[u32] = unsafe { &*(bytes as *const [u8] as *const [u32]) }; + //~^ transmute_ptr_to_ptr + } +} diff --git a/tests/ui/transmute_ref_to_ref_no_std.rs b/tests/ui/transmute_ref_to_ref_no_std.rs index faa776f2afce..7ed885bbbb07 100644 --- a/tests/ui/transmute_ref_to_ref_no_std.rs +++ b/tests/ui/transmute_ref_to_ref_no_std.rs @@ -1,7 +1,5 @@ -//@no-rustfix - #![deny(clippy::transmute_ptr_to_ptr)] -#![allow(dead_code, clippy::missing_transmute_annotations)] +#![allow(dead_code, clippy::missing_transmute_annotations, clippy::cast_slice_different_sizes)] #![feature(lang_items)] #![no_std] diff --git a/tests/ui/transmute_ref_to_ref_no_std.stderr b/tests/ui/transmute_ref_to_ref_no_std.stderr index 9aa9ed928a4d..136a9b21fb9e 100644 --- a/tests/ui/transmute_ref_to_ref_no_std.stderr +++ b/tests/ui/transmute_ref_to_ref_no_std.stderr @@ -1,23 +1,23 @@ error: transmute from a reference to a reference - --> tests/ui/transmute_ref_to_ref_no_std.rs:21:39 + --> tests/ui/transmute_ref_to_ref_no_std.rs:19:39 | LL | let bools: &[bool] = unsafe { core::mem::transmute(single_u64) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `&*(single_u64 as *const [u64] as *const [bool])` | note: the lint level is defined here - --> tests/ui/transmute_ref_to_ref_no_std.rs:3:9 + --> tests/ui/transmute_ref_to_ref_no_std.rs:1:9 | LL | #![deny(clippy::transmute_ptr_to_ptr)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: transmute from a reference to a reference - --> tests/ui/transmute_ref_to_ref_no_std.rs:25:33 + --> tests/ui/transmute_ref_to_ref_no_std.rs:23:33 | LL | let b: &[u8] = unsafe { core::mem::transmute(a) }; | ^^^^^^^^^^^^^^^^^^^^^^^ help: try: `&*(a as *const [u32] as *const [u8])` error: transmute from a reference to a reference - --> tests/ui/transmute_ref_to_ref_no_std.rs:29:42 + --> tests/ui/transmute_ref_to_ref_no_std.rs:27:42 | LL | let alt_slice: &[u32] = unsafe { core::mem::transmute(bytes) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `&*(bytes as *const [u8] as *const [u32])`