diff --git a/clippy_lints/src/assign_ops.rs b/clippy_lints/src/assign_ops.rs index ec4c8f5faa3f..a56d751b22d2 100644 --- a/clippy_lints/src/assign_ops.rs +++ b/clippy_lints/src/assign_ops.rs @@ -216,13 +216,13 @@ fn lint_misrefactored_assign_op( long ), format!("{} {}= {}", snip_a, op.node.as_str(), snip_r), - Applicability::MachineApplicable, + Applicability::MaybeIncorrect, ); db.span_suggestion( expr.span, "or", long, - Applicability::MachineApplicable, // snippet + Applicability::MaybeIncorrect, // snippet ); } }, diff --git a/clippy_lints/src/loops.rs b/clippy_lints/src/loops.rs index 2db8acc4b95e..0032cfd1985b 100644 --- a/clippy_lints/src/loops.rs +++ b/clippy_lints/src/loops.rs @@ -1272,7 +1272,7 @@ fn check_for_loop_reverse_range<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, arg: &'tcx let start_snippet = snippet(cx, start.span, "_"); let end_snippet = snippet(cx, end.span, "_"); let dots = if limits == ast::RangeLimits::Closed { - "..." + "..=" } else { ".." }; diff --git a/tests/ui/deref_addrof_double_trigger.rs b/tests/ui/deref_addrof_double_trigger.rs index e19af5b9087f..4531943299cd 100644 --- a/tests/ui/deref_addrof_double_trigger.rs +++ b/tests/ui/deref_addrof_double_trigger.rs @@ -1,5 +1,7 @@ +// This test can't work with run-rustfix because it needs two passes of test+fix + #[warn(clippy::deref_addrof)] -#[allow(unused_variables)] +#[allow(unused_variables, unused_mut)] fn main() { let a = 10; diff --git a/tests/ui/deref_addrof_double_trigger.stderr b/tests/ui/deref_addrof_double_trigger.stderr index 89284e1a8ed6..2c55a4ed6acd 100644 --- a/tests/ui/deref_addrof_double_trigger.stderr +++ b/tests/ui/deref_addrof_double_trigger.stderr @@ -1,5 +1,5 @@ error: immediately dereferencing a reference - --> $DIR/deref_addrof_double_trigger.rs:8:14 + --> $DIR/deref_addrof_double_trigger.rs:10:14 | LL | let b = **&&a; | ^^^^ help: try this: `&a` @@ -7,13 +7,13 @@ LL | let b = **&&a; = note: `-D clippy::deref-addrof` implied by `-D warnings` error: immediately dereferencing a reference - --> $DIR/deref_addrof_double_trigger.rs:12:17 + --> $DIR/deref_addrof_double_trigger.rs:14:17 | LL | let y = *&mut x; | ^^^^^^^ help: try this: `x` error: immediately dereferencing a reference - --> $DIR/deref_addrof_double_trigger.rs:19:18 + --> $DIR/deref_addrof_double_trigger.rs:21:18 | LL | let y = **&mut &mut x; | ^^^^^^^^^^^^ help: try this: `&mut x` diff --git a/tests/ui/eq_op.rs b/tests/ui/eq_op.rs index cc0935ddb799..c93f520bee24 100644 --- a/tests/ui/eq_op.rs +++ b/tests/ui/eq_op.rs @@ -2,7 +2,8 @@ #[warn(clippy::eq_op)] #[allow(clippy::identity_op, clippy::double_parens, clippy::many_single_char_names)] #[allow(clippy::no_effect, unused_variables, clippy::unnecessary_operation, clippy::short_circuit_statement)] -#[warn(clippy::nonminimal_bool)] +#[allow(clippy::nonminimal_bool)] +#[allow(unused)] fn main() { // simple values and comparisons 1 == 1; @@ -50,42 +51,6 @@ fn main() { 2*a.len() == 2*a.len(); // ok, functions a.pop() == a.pop(); // ok, functions - use std::ops::BitAnd; - struct X(i32); - impl BitAnd for X { - type Output = X; - fn bitand(self, rhs: X) -> X { - X(self.0 & rhs.0) - } - } - impl<'a> BitAnd<&'a X> for X { - type Output = X; - fn bitand(self, rhs: &'a X) -> X { - X(self.0 & rhs.0) - } - } - let x = X(1); - let y = X(2); - let z = x & &y; - - #[derive(Copy, Clone)] - struct Y(i32); - impl BitAnd for Y { - type Output = Y; - fn bitand(self, rhs: Y) -> Y { - Y(self.0 & rhs.0) - } - } - impl<'a> BitAnd<&'a Y> for Y { - type Output = Y; - fn bitand(self, rhs: &'a Y) -> Y { - Y(self.0 & rhs.0) - } - } - let x = Y(1); - let y = Y(2); - let z = x & &y; - check_ignore_macro(); // named constants diff --git a/tests/ui/eq_op.stderr b/tests/ui/eq_op.stderr index 2dabaf0d4db9..e37c0c22907e 100644 --- a/tests/ui/eq_op.stderr +++ b/tests/ui/eq_op.stderr @@ -1,43 +1,5 @@ -error: this boolean expression can be simplified - --> $DIR/eq_op.rs:35:5 - | -LL | true && true; - | ^^^^^^^^^^^^ help: try: `true` - | - = note: `-D clippy::nonminimal-bool` implied by `-D warnings` - -error: this boolean expression can be simplified - --> $DIR/eq_op.rs:37:5 - | -LL | true || true; - | ^^^^^^^^^^^^ help: try: `true` - -error: this boolean expression can be simplified - --> $DIR/eq_op.rs:43:5 - | -LL | a == b && b == a; - | ^^^^^^^^^^^^^^^^ help: try: `a == b` - -error: this boolean expression can be simplified - --> $DIR/eq_op.rs:44:5 - | -LL | a != b && b != a; - | ^^^^^^^^^^^^^^^^ help: try: `a != b` - -error: this boolean expression can be simplified - --> $DIR/eq_op.rs:45:5 - | -LL | a < b && b > a; - | ^^^^^^^^^^^^^^ help: try: `a < b` - -error: this boolean expression can be simplified - --> $DIR/eq_op.rs:46:5 - | -LL | a <= b && b >= a; - | ^^^^^^^^^^^^^^^^ help: try: `a <= b` - error: equal expressions as operands to `==` - --> $DIR/eq_op.rs:8:5 + --> $DIR/eq_op.rs:9:5 | LL | 1 == 1; | ^^^^^^ @@ -45,170 +7,160 @@ LL | 1 == 1; = note: `-D clippy::eq-op` implied by `-D warnings` error: equal expressions as operands to `==` - --> $DIR/eq_op.rs:9:5 + --> $DIR/eq_op.rs:10:5 | LL | "no" == "no"; | ^^^^^^^^^^^^ error: equal expressions as operands to `!=` - --> $DIR/eq_op.rs:11:5 + --> $DIR/eq_op.rs:12:5 | LL | false != false; | ^^^^^^^^^^^^^^ error: equal expressions as operands to `<` - --> $DIR/eq_op.rs:12:5 + --> $DIR/eq_op.rs:13:5 | LL | 1.5 < 1.5; | ^^^^^^^^^ error: equal expressions as operands to `>=` - --> $DIR/eq_op.rs:13:5 + --> $DIR/eq_op.rs:14:5 | LL | 1u64 >= 1u64; | ^^^^^^^^^^^^ error: equal expressions as operands to `&` - --> $DIR/eq_op.rs:16:5 + --> $DIR/eq_op.rs:17:5 | LL | (1 as u64) & (1 as u64); | ^^^^^^^^^^^^^^^^^^^^^^^ error: equal expressions as operands to `^` - --> $DIR/eq_op.rs:17:5 + --> $DIR/eq_op.rs:18:5 | LL | 1 ^ ((((((1)))))); | ^^^^^^^^^^^^^^^^^ error: equal expressions as operands to `<` - --> $DIR/eq_op.rs:20:5 + --> $DIR/eq_op.rs:21:5 | LL | (-(2) < -(2)); | ^^^^^^^^^^^^^ error: equal expressions as operands to `==` - --> $DIR/eq_op.rs:21:5 + --> $DIR/eq_op.rs:22:5 | LL | ((1 + 1) & (1 + 1) == (1 + 1) & (1 + 1)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: equal expressions as operands to `&` - --> $DIR/eq_op.rs:21:6 + --> $DIR/eq_op.rs:22:6 | LL | ((1 + 1) & (1 + 1) == (1 + 1) & (1 + 1)); | ^^^^^^^^^^^^^^^^^ error: equal expressions as operands to `&` - --> $DIR/eq_op.rs:21:27 + --> $DIR/eq_op.rs:22:27 | LL | ((1 + 1) & (1 + 1) == (1 + 1) & (1 + 1)); | ^^^^^^^^^^^^^^^^^ error: equal expressions as operands to `==` - --> $DIR/eq_op.rs:22:5 + --> $DIR/eq_op.rs:23:5 | LL | (1 * 2) + (3 * 4) == 1 * 2 + 3 * 4; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: equal expressions as operands to `!=` - --> $DIR/eq_op.rs:25:5 + --> $DIR/eq_op.rs:26:5 | LL | ([1] != [1]); | ^^^^^^^^^^^^ error: equal expressions as operands to `!=` - --> $DIR/eq_op.rs:26:5 + --> $DIR/eq_op.rs:27:5 | LL | ((1, 2) != (1, 2)); | ^^^^^^^^^^^^^^^^^^ error: equal expressions as operands to `==` - --> $DIR/eq_op.rs:30:5 + --> $DIR/eq_op.rs:31:5 | LL | 1 + 1 == 2; | ^^^^^^^^^^ error: equal expressions as operands to `==` - --> $DIR/eq_op.rs:31:5 + --> $DIR/eq_op.rs:32:5 | LL | 1 - 1 == 0; | ^^^^^^^^^^ error: equal expressions as operands to `-` - --> $DIR/eq_op.rs:31:5 + --> $DIR/eq_op.rs:32:5 | LL | 1 - 1 == 0; | ^^^^^ error: equal expressions as operands to `-` - --> $DIR/eq_op.rs:33:5 + --> $DIR/eq_op.rs:34:5 | LL | 1 - 1; | ^^^^^ error: equal expressions as operands to `/` - --> $DIR/eq_op.rs:34:5 + --> $DIR/eq_op.rs:35:5 | LL | 1 / 1; | ^^^^^ error: equal expressions as operands to `&&` - --> $DIR/eq_op.rs:35:5 + --> $DIR/eq_op.rs:36:5 | LL | true && true; | ^^^^^^^^^^^^ error: equal expressions as operands to `||` - --> $DIR/eq_op.rs:37:5 + --> $DIR/eq_op.rs:38:5 | LL | true || true; | ^^^^^^^^^^^^ error: equal expressions as operands to `&&` - --> $DIR/eq_op.rs:43:5 + --> $DIR/eq_op.rs:44:5 | LL | a == b && b == a; | ^^^^^^^^^^^^^^^^ error: equal expressions as operands to `&&` - --> $DIR/eq_op.rs:44:5 + --> $DIR/eq_op.rs:45:5 | LL | a != b && b != a; | ^^^^^^^^^^^^^^^^ error: equal expressions as operands to `&&` - --> $DIR/eq_op.rs:45:5 + --> $DIR/eq_op.rs:46:5 | LL | a < b && b > a; | ^^^^^^^^^^^^^^ error: equal expressions as operands to `&&` - --> $DIR/eq_op.rs:46:5 + --> $DIR/eq_op.rs:47:5 | LL | a <= b && b >= a; | ^^^^^^^^^^^^^^^^ error: equal expressions as operands to `==` - --> $DIR/eq_op.rs:49:5 + --> $DIR/eq_op.rs:50:5 | LL | a == a; | ^^^^^^ -error: taken reference of right operand - --> $DIR/eq_op.rs:87:13 - | -LL | let z = x & &y; - | ^^^^-- - | | - | help: use the right value directly: `y` - | - = note: `-D clippy::op-ref` implied by `-D warnings` - error: equal expressions as operands to `/` - --> $DIR/eq_op.rs:95:20 + --> $DIR/eq_op.rs:60:20 | LL | const D: u32 = A / A; | ^^^^^ -error: aborting due to 34 previous errors +error: aborting due to 27 previous errors diff --git a/tests/ui/for_loop_fixable.fixed b/tests/ui/for_loop_fixable.fixed new file mode 100644 index 000000000000..6f88224f8b6b --- /dev/null +++ b/tests/ui/for_loop_fixable.fixed @@ -0,0 +1,305 @@ +// run-rustfix + +#![allow(dead_code, unused)] + +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::reverse_range_loop, + clippy::for_kv_map +)] +#[allow( + clippy::linkedlist, + clippy::shadow_unrelated, + clippy::unnecessary_mut_passed, + clippy::cognitive_complexity, + clippy::similar_names, +)] +#[allow(clippy::many_single_char_names, unused_variables, clippy::into_iter_on_array)] +fn main() { + const MAX_LEN: usize = 42; + let mut vec = vec![1, 2, 3, 4]; + + for i in (0..10).rev() { + println!("{}", i); + } + + for i in (0..=10).rev() { + println!("{}", i); + } + + for i in (0..MAX_LEN).rev() { + println!("{}", i); + } + + for i in 5..=5 { + // not an error, this is the range with only one element “5” + println!("{}", i); + } + + for i in 0..10 { + // not an error, the start index is less than the end index + println!("{}", i); + } + + for i in -10..0 { + // not an error + println!("{}", i); + } + + for i in (10..0).map(|x| x * 2) { + // not an error, it can't be known what arbitrary methods do to a range + println!("{}", i); + } + + // testing that the empty range lint folds constants + for i in (5 + 4..10).rev() { + println!("{}", i); + } + + for i in ((3 - 1)..(5 + 2)).rev() { + println!("{}", i); + } + + + for i in (2 * 2)..(2 * 3) { + // no error, 4..6 is fine + println!("{}", i); + } + + let x = 42; + for i in x..10 { + // no error, not constant-foldable + println!("{}", i); + } + + // 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 {} + + let array = [1, 2, 3]; + for _v in &array {} + + 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]).iter() {} // no error + + for _v in &[0; 32] {} + + for _v in [0; 33].iter() {} // 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!() + } +} diff --git a/tests/ui/for_loop.rs b/tests/ui/for_loop_fixable.rs similarity index 93% rename from tests/ui/for_loop.rs rename to tests/ui/for_loop_fixable.rs index 5d367a62fc93..5287cababd99 100644 --- a/tests/ui/for_loop.rs +++ b/tests/ui/for_loop_fixable.rs @@ -1,8 +1,8 @@ -use std::collections::*; -use std::rc::Rc; +// run-rustfix + +#![allow(dead_code, unused)] -static STATIC: [usize; 4] = [0, 1, 8, 16]; -const CONST: [usize; 4] = [0, 1, 8, 16]; +use std::collections::*; #[warn(clippy::all)] struct Unrelated(Vec); @@ -29,7 +29,7 @@ impl Unrelated { clippy::shadow_unrelated, clippy::unnecessary_mut_passed, clippy::cognitive_complexity, - clippy::similar_names + clippy::similar_names, )] #[allow(clippy::many_single_char_names, unused_variables, clippy::into_iter_on_array)] fn main() { @@ -48,10 +48,6 @@ fn main() { println!("{}", i); } - for i in 5..5 { - println!("{}", i); - } - for i in 5..=5 { // not an error, this is the range with only one element “5” println!("{}", i); @@ -81,9 +77,6 @@ fn main() { println!("{}", i); } - for i in (5 + 2)..(8 - 1) { - println!("{}", i); - } for i in (2 * 2)..(2 * 3) { // no error, 4..6 is fine @@ -145,8 +138,6 @@ fn main() { let bs: BTreeSet<()> = BTreeSet::new(); for _v in bs.iter() {} - for _v in vec.iter().next() {} - let u = Unrelated(vec![]); for _v in u.next() {} // no error for _v in u.iter() {} // no error @@ -275,17 +266,8 @@ fn main() { for mid in 1..vec.len() { let (_, _) = vec.split_at(mid); } - - const ZERO: usize = 0; - - for i in ZERO..vec.len() { - if f(&vec[i], &vec[i]) { - panic!("at the disco"); - } - } } -#[allow(dead_code)] fn partition(v: &mut [T]) -> usize { let pivot = v.len() - 1; let mut i = 0; diff --git a/tests/ui/for_loop.stderr b/tests/ui/for_loop_fixable.stderr similarity index 74% rename from tests/ui/for_loop.stderr rename to tests/ui/for_loop_fixable.stderr index 0f84abf45ed7..251ccc76391a 100644 --- a/tests/ui/for_loop.stderr +++ b/tests/ui/for_loop_fixable.stderr @@ -1,5 +1,5 @@ error: this range is empty so this for loop will never run - --> $DIR/for_loop.rs:39:14 + --> $DIR/for_loop_fixable.rs:39:14 | LL | for i in 10..0 { | ^^^^^ @@ -11,17 +11,17 @@ LL | for i in (0..10).rev() { | ^^^^^^^^^^^^^ error: this range is empty so this for loop will never run - --> $DIR/for_loop.rs:43:14 + --> $DIR/for_loop_fixable.rs:43:14 | LL | for i in 10..=0 { | ^^^^^^ help: consider using the following if you are attempting to iterate over this range in reverse | -LL | for i in (0...10).rev() { +LL | for i in (0..=10).rev() { | ^^^^^^^^^^^^^^ error: this range is empty so this for loop will never run - --> $DIR/for_loop.rs:47:14 + --> $DIR/for_loop_fixable.rs:47:14 | LL | for i in MAX_LEN..0 { | ^^^^^^^^^^ @@ -31,13 +31,7 @@ LL | for i in (0..MAX_LEN).rev() { | ^^^^^^^^^^^^^^^^^^ error: this range is empty so this for loop will never run - --> $DIR/for_loop.rs:51:14 - | -LL | for i in 5..5 { - | ^^^^ - -error: this range is empty so this for loop will never run - --> $DIR/for_loop.rs:76:14 + --> $DIR/for_loop_fixable.rs:72:14 | LL | for i in 10..5 + 4 { | ^^^^^^^^^ @@ -47,7 +41,7 @@ LL | for i in (5 + 4..10).rev() { | ^^^^^^^^^^^^^^^^^ error: this range is empty so this for loop will never run - --> $DIR/for_loop.rs:80:14 + --> $DIR/for_loop_fixable.rs:76:14 | LL | for i in (5 + 2)..(3 - 1) { | ^^^^^^^^^^^^^^^^ @@ -56,14 +50,8 @@ help: consider using the following if you are attempting to iterate over this ra LL | for i in ((3 - 1)..(5 + 2)).rev() { | ^^^^^^^^^^^^^^^^^^^^^^^^ -error: this range is empty so this for loop will never run - --> $DIR/for_loop.rs:84:14 - | -LL | for i in (5 + 2)..(8 - 1) { - | ^^^^^^^^^^^^^^^^ - error: it is more concise to loop over references to containers instead of using explicit iteration methods - --> $DIR/for_loop.rs:106:15 + --> $DIR/for_loop_fixable.rs:99:15 | LL | for _v in vec.iter() {} | ^^^^^^^^^^ help: to write this more concisely, try: `&vec` @@ -71,13 +59,13 @@ LL | for _v in vec.iter() {} = 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.rs:108:15 + --> $DIR/for_loop_fixable.rs:101: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.rs:111:15 + --> $DIR/for_loop_fixable.rs:104:15 | LL | for _v in out_vec.into_iter() {} | ^^^^^^^^^^^^^^^^^^^ help: to write this more concisely, try: `out_vec` @@ -85,84 +73,64 @@ LL | for _v in out_vec.into_iter() {} = 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.rs:114:15 + --> $DIR/for_loop_fixable.rs:107:15 | LL | for _v in array.into_iter() {} | ^^^^^^^^^^^^^^^^^ help: to write this more concisely, try: `&array` error: it is more concise to loop over references to containers instead of using explicit iteration methods - --> $DIR/for_loop.rs:119:15 + --> $DIR/for_loop_fixable.rs:112: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.rs:123:15 + --> $DIR/for_loop_fixable.rs:116: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.rs:128:15 + --> $DIR/for_loop_fixable.rs:121: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.rs:131:15 + --> $DIR/for_loop_fixable.rs:124: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.rs:134:15 + --> $DIR/for_loop_fixable.rs:127: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.rs:137:15 + --> $DIR/for_loop_fixable.rs:130: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.rs:140:15 + --> $DIR/for_loop_fixable.rs:133: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.rs:143:15 + --> $DIR/for_loop_fixable.rs:136: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.rs:146:15 + --> $DIR/for_loop_fixable.rs:139:15 | LL | for _v in bs.iter() {} | ^^^^^^^^^ help: to write this more concisely, try: `&bs` -error: you are iterating over `Iterator::next()` which is an Option; this will compile but is probably not what you want - --> $DIR/for_loop.rs:148:15 - | -LL | for _v in vec.iter().next() {} - | ^^^^^^^^^^^^^^^^^ - | - = note: `-D clippy::iter-next-loop` implied by `-D warnings` - -error: the loop variable `i` is only used to index `vec`. - --> $DIR/for_loop.rs:281:14 - | -LL | for i in ZERO..vec.len() { - | ^^^^^^^^^^^^^^^ - | - = note: `-D clippy::needless-range-loop` implied by `-D warnings` -help: consider using an iterator - | -LL | for in &vec { - | ^^^^^^ ^^^^ - -error: aborting due to 22 previous errors +error: aborting due to 18 previous errors diff --git a/tests/ui/for_loop_unfixable.rs b/tests/ui/for_loop_unfixable.rs new file mode 100644 index 000000000000..07e5661f47ce --- /dev/null +++ b/tests/ui/for_loop_unfixable.rs @@ -0,0 +1,42 @@ + +// 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::reverse_range_loop, + clippy::for_kv_map +)] +#[allow( + clippy::linkedlist, + clippy::shadow_unrelated, + clippy::unnecessary_mut_passed, + clippy::cognitive_complexity, + clippy::similar_names, + unused, + dead_code +)] +#[allow(clippy::many_single_char_names, unused_variables, clippy::into_iter_on_array)] +fn main() { + for i in 5..5 { + println!("{}", i); + } + + let vec = vec![1, 2, 3, 4]; + + for _v in vec.iter().next() {} + + for i in (5 + 2)..(8 - 1) { + println!("{}", i); + } + + const ZERO: usize = 0; + + for i in ZERO..vec.len() { + if f(&vec[i], &vec[i]) { + panic!("at the disco"); + } + } +} \ No newline at end of file diff --git a/tests/ui/for_loop_unfixable.stderr b/tests/ui/for_loop_unfixable.stderr new file mode 100644 index 000000000000..3841599e38b0 --- /dev/null +++ b/tests/ui/for_loop_unfixable.stderr @@ -0,0 +1,9 @@ +error[E0425]: cannot find function `f` in this scope + --> $DIR/for_loop_unfixable.rs:38:12 + | +LL | if f(&vec[i], &vec[i]) { + | ^ help: a local variable with a similar name exists: `i` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0425`. diff --git a/tests/ui/identity_conversion.fixed b/tests/ui/identity_conversion.fixed new file mode 100644 index 000000000000..dd3fc56e98bc --- /dev/null +++ b/tests/ui/identity_conversion.fixed @@ -0,0 +1,58 @@ +// run-rustfix + +#![deny(clippy::identity_conversion)] + +fn test_generic(val: T) -> T { + let _ = val; + val +} + +fn test_generic2 + Into, U: From>(val: T) { + // ok + let _: i32 = val.into(); + let _: U = val.into(); + let _ = U::from(val); +} + +fn test_questionmark() -> Result<(), ()> { + { + let _: i32 = 0i32; + Ok(Ok(())) + }??; + Ok(()) +} + +fn test_issue_3913() -> Result<(), std::io::Error> { + use std::fs; + use std::path::Path; + + let path = Path::new("."); + for _ in fs::read_dir(path)? {} + + Ok(()) +} + +fn main() { + test_generic(10i32); + test_generic2::(10i32); + test_questionmark().unwrap(); + test_issue_3913().unwrap(); + + let _: String = "foo".into(); + let _: String = From::from("foo"); + let _ = String::from("foo"); + #[allow(clippy::identity_conversion)] + { + let _: String = "foo".into(); + let _ = String::from("foo"); + let _ = "".lines().into_iter(); + } + + let _: String = "foo".to_string(); + let _: String = "foo".to_string(); + let _ = "foo".to_string(); + let _ = format!("A: {:04}", 123); + let _ = "".lines(); + let _ = vec![1, 2, 3].into_iter(); + let _: String = format!("Hello {}", "world"); +} diff --git a/tests/ui/identity_conversion.rs b/tests/ui/identity_conversion.rs index 164f0a3d6e73..875ed7db373b 100644 --- a/tests/ui/identity_conversion.rs +++ b/tests/ui/identity_conversion.rs @@ -1,3 +1,5 @@ +// run-rustfix + #![deny(clippy::identity_conversion)] fn test_generic(val: T) -> T { diff --git a/tests/ui/identity_conversion.stderr b/tests/ui/identity_conversion.stderr index 663f00d22795..3cabe53bf2b7 100644 --- a/tests/ui/identity_conversion.stderr +++ b/tests/ui/identity_conversion.stderr @@ -1,65 +1,65 @@ error: identical conversion - --> $DIR/identity_conversion.rs:4:13 + --> $DIR/identity_conversion.rs:6:13 | LL | let _ = T::from(val); | ^^^^^^^^^^^^ help: consider removing `T::from()`: `val` | note: lint level defined here - --> $DIR/identity_conversion.rs:1:9 + --> $DIR/identity_conversion.rs:3:9 | LL | #![deny(clippy::identity_conversion)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: identical conversion - --> $DIR/identity_conversion.rs:5:5 + --> $DIR/identity_conversion.rs:7:5 | LL | val.into() | ^^^^^^^^^^ help: consider removing `.into()`: `val` error: identical conversion - --> $DIR/identity_conversion.rs:17:22 + --> $DIR/identity_conversion.rs:19:22 | LL | let _: i32 = 0i32.into(); | ^^^^^^^^^^^ help: consider removing `.into()`: `0i32` error: identical conversion - --> $DIR/identity_conversion.rs:49:21 + --> $DIR/identity_conversion.rs:51:21 | LL | let _: String = "foo".to_string().into(); | ^^^^^^^^^^^^^^^^^^^^^^^^ help: consider removing `.into()`: `"foo".to_string()` error: identical conversion - --> $DIR/identity_conversion.rs:50:21 + --> $DIR/identity_conversion.rs:52:21 | LL | let _: String = From::from("foo".to_string()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider removing `From::from()`: `"foo".to_string()` error: identical conversion - --> $DIR/identity_conversion.rs:51:13 + --> $DIR/identity_conversion.rs:53:13 | LL | let _ = String::from("foo".to_string()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider removing `String::from()`: `"foo".to_string()` error: identical conversion - --> $DIR/identity_conversion.rs:52:13 + --> $DIR/identity_conversion.rs:54:13 | LL | let _ = String::from(format!("A: {:04}", 123)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider removing `String::from()`: `format!("A: {:04}", 123)` error: identical conversion - --> $DIR/identity_conversion.rs:53:13 + --> $DIR/identity_conversion.rs:55:13 | LL | let _ = "".lines().into_iter(); | ^^^^^^^^^^^^^^^^^^^^^^ help: consider removing `.into_iter()`: `"".lines()` error: identical conversion - --> $DIR/identity_conversion.rs:54:13 + --> $DIR/identity_conversion.rs:56:13 | LL | let _ = vec![1, 2, 3].into_iter().into_iter(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider removing `.into_iter()`: `vec![1, 2, 3].into_iter()` error: identical conversion - --> $DIR/identity_conversion.rs:55:21 + --> $DIR/identity_conversion.rs:57:21 | LL | let _: String = format!("Hello {}", "world").into(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider removing `.into()`: `format!("Hello {}", "world")` diff --git a/tests/ui/implicit_return.fixed b/tests/ui/implicit_return.fixed new file mode 100644 index 000000000000..dd42f06664e1 --- /dev/null +++ b/tests/ui/implicit_return.fixed @@ -0,0 +1,102 @@ +// run-rustfix + +#![warn(clippy::implicit_return)] +#![allow(clippy::needless_return, unused)] + +fn test_end_of_fn() -> bool { + if true { + // no error! + return true; + } + + return true +} + +#[allow(clippy::needless_bool)] +fn test_if_block() -> bool { + if true { + return true + } else { + return false + } +} + +#[allow(clippy::match_bool)] +#[rustfmt::skip] +fn test_match(x: bool) -> bool { + match x { + true => return false, + false => { return true }, + } +} + +#[allow(clippy::match_bool, clippy::needless_return)] +fn test_match_with_unreachable(x: bool) -> bool { + match x { + true => return false, + false => unreachable!(), + } +} + +#[allow(clippy::never_loop)] +fn test_loop() -> bool { + loop { + return true; + } +} + +#[allow(clippy::never_loop)] +fn test_loop_with_block() -> bool { + loop { + { + return true; + } + } +} + +#[allow(clippy::never_loop)] +fn test_loop_with_nests() -> bool { + loop { + if true { + return true; + } else { + let _ = true; + } + } +} + +#[allow(clippy::redundant_pattern_matching)] +fn test_loop_with_if_let() -> bool { + loop { + if let Some(x) = Some(true) { + return x; + } + } +} + +fn test_closure() { + #[rustfmt::skip] + let _ = || { return true }; + let _ = || return true; +} + +fn test_panic() -> bool { + panic!() +} + +fn test_return_macro() -> String { + return format!("test {}", "test") +} + +fn main() { + let _ = test_end_of_fn(); + let _ = test_if_block(); + let _ = test_match(true); + let _ = test_match_with_unreachable(true); + let _ = test_loop(); + let _ = test_loop_with_block(); + let _ = test_loop_with_nests(); + let _ = test_loop_with_if_let(); + test_closure(); + let _ = test_return_macro(); +} diff --git a/tests/ui/implicit_return.rs b/tests/ui/implicit_return.rs index 47e0679c430d..5abbf6a5583e 100644 --- a/tests/ui/implicit_return.rs +++ b/tests/ui/implicit_return.rs @@ -1,4 +1,7 @@ +// run-rustfix + #![warn(clippy::implicit_return)] +#![allow(clippy::needless_return, unused)] fn test_end_of_fn() -> bool { if true { diff --git a/tests/ui/implicit_return.stderr b/tests/ui/implicit_return.stderr index 41b0873317e8..21822344437b 100644 --- a/tests/ui/implicit_return.stderr +++ b/tests/ui/implicit_return.stderr @@ -1,5 +1,5 @@ error: missing return statement - --> $DIR/implicit_return.rs:9:5 + --> $DIR/implicit_return.rs:12:5 | LL | true | ^^^^ help: add `return` as shown: `return true` @@ -7,61 +7,61 @@ LL | true = note: `-D clippy::implicit-return` implied by `-D warnings` error: missing return statement - --> $DIR/implicit_return.rs:15:9 + --> $DIR/implicit_return.rs:18:9 | LL | true | ^^^^ help: add `return` as shown: `return true` error: missing return statement - --> $DIR/implicit_return.rs:17:9 + --> $DIR/implicit_return.rs:20:9 | LL | false | ^^^^^ help: add `return` as shown: `return false` error: missing return statement - --> $DIR/implicit_return.rs:25:17 + --> $DIR/implicit_return.rs:28:17 | LL | true => false, | ^^^^^ help: add `return` as shown: `return false` error: missing return statement - --> $DIR/implicit_return.rs:26:20 + --> $DIR/implicit_return.rs:29:20 | LL | false => { true }, | ^^^^ help: add `return` as shown: `return true` error: missing return statement - --> $DIR/implicit_return.rs:41:9 + --> $DIR/implicit_return.rs:44:9 | LL | break true; | ^^^^^^^^^^ help: change `break` to `return` as shown: `return true` error: missing return statement - --> $DIR/implicit_return.rs:49:13 + --> $DIR/implicit_return.rs:52:13 | LL | break true; | ^^^^^^^^^^ help: change `break` to `return` as shown: `return true` error: missing return statement - --> $DIR/implicit_return.rs:58:13 + --> $DIR/implicit_return.rs:61:13 | LL | break true; | ^^^^^^^^^^ help: change `break` to `return` as shown: `return true` error: missing return statement - --> $DIR/implicit_return.rs:76:18 + --> $DIR/implicit_return.rs:79:18 | LL | let _ = || { true }; | ^^^^ help: add `return` as shown: `return true` error: missing return statement - --> $DIR/implicit_return.rs:77:16 + --> $DIR/implicit_return.rs:80:16 | LL | let _ = || true; | ^^^^ help: add `return` as shown: `return true` error: missing return statement - --> $DIR/implicit_return.rs:85:5 + --> $DIR/implicit_return.rs:88:5 | LL | format!("test {}", "test") | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: add `return` as shown: `return format!("test {}", "test")` diff --git a/tests/ui/inline_fn_without_body.fixed b/tests/ui/inline_fn_without_body.fixed new file mode 100644 index 000000000000..fe21a71a42c2 --- /dev/null +++ b/tests/ui/inline_fn_without_body.fixed @@ -0,0 +1,17 @@ +// run-rustfix + +#![warn(clippy::inline_fn_without_body)] +#![allow(clippy::inline_always)] + +trait Foo { + fn default_inline(); + + fn always_inline(); + + fn never_inline(); + + #[inline] + fn has_body() {} +} + +fn main() {} diff --git a/tests/ui/inline_fn_without_body.rs b/tests/ui/inline_fn_without_body.rs index af81feaa374a..507469894665 100644 --- a/tests/ui/inline_fn_without_body.rs +++ b/tests/ui/inline_fn_without_body.rs @@ -1,3 +1,5 @@ +// run-rustfix + #![warn(clippy::inline_fn_without_body)] #![allow(clippy::inline_always)] diff --git a/tests/ui/inline_fn_without_body.stderr b/tests/ui/inline_fn_without_body.stderr index 87d2da71280d..32d35e209b01 100644 --- a/tests/ui/inline_fn_without_body.stderr +++ b/tests/ui/inline_fn_without_body.stderr @@ -1,5 +1,5 @@ error: use of `#[inline]` on trait method `default_inline` which has no body - --> $DIR/inline_fn_without_body.rs:5:5 + --> $DIR/inline_fn_without_body.rs:7:5 | LL | #[inline] | _____-^^^^^^^^ @@ -9,7 +9,7 @@ LL | | fn default_inline(); = note: `-D clippy::inline-fn-without-body` implied by `-D warnings` error: use of `#[inline]` on trait method `always_inline` which has no body - --> $DIR/inline_fn_without_body.rs:8:5 + --> $DIR/inline_fn_without_body.rs:10:5 | LL | #[inline(always)] | _____-^^^^^^^^^^^^^^^^ @@ -17,7 +17,7 @@ LL | | fn always_inline(); | |____- help: remove error: use of `#[inline]` on trait method `never_inline` which has no body - --> $DIR/inline_fn_without_body.rs:11:5 + --> $DIR/inline_fn_without_body.rs:13:5 | LL | #[inline(never)] | _____-^^^^^^^^^^^^^^^ diff --git a/tests/ui/op_ref.rs b/tests/ui/op_ref.rs index bf43deca12c0..6605c967c8e7 100644 --- a/tests/ui/op_ref.rs +++ b/tests/ui/op_ref.rs @@ -1,6 +1,8 @@ #![allow(unused_variables, clippy::blacklisted_name)] - +#![warn(clippy::op_ref)] +#![allow(clippy::many_single_char_names)] use std::collections::HashSet; +use std::ops::BitAnd; fn main() { let tracked_fds: HashSet = HashSet::new(); @@ -18,4 +20,39 @@ fn main() { if b < &a { println!("OK"); } + + struct X(i32); + impl BitAnd for X { + type Output = X; + fn bitand(self, rhs: X) -> X { + X(self.0 & rhs.0) + } + } + impl<'a> BitAnd<&'a X> for X { + type Output = X; + fn bitand(self, rhs: &'a X) -> X { + X(self.0 & rhs.0) + } + } + let x = X(1); + let y = X(2); + let z = x & &y; + + #[derive(Copy, Clone)] + struct Y(i32); + impl BitAnd for Y { + type Output = Y; + fn bitand(self, rhs: Y) -> Y { + Y(self.0 & rhs.0) + } + } + impl<'a> BitAnd<&'a Y> for Y { + type Output = Y; + fn bitand(self, rhs: &'a Y) -> Y { + Y(self.0 & rhs.0) + } + } + let x = Y(1); + let y = Y(2); + let z = x & &y; } diff --git a/tests/ui/op_ref.stderr b/tests/ui/op_ref.stderr index f5c5b9702619..0f6a45f905c8 100644 --- a/tests/ui/op_ref.stderr +++ b/tests/ui/op_ref.stderr @@ -1,5 +1,5 @@ error: needlessly taken reference of both operands - --> $DIR/op_ref.rs:10:15 + --> $DIR/op_ref.rs:12:15 | LL | let foo = &5 - &6; | ^^^^^^^ @@ -11,12 +11,20 @@ LL | let foo = 5 - 6; | ^ ^ error: taken reference of right operand - --> $DIR/op_ref.rs:18:8 + --> $DIR/op_ref.rs:20:8 | LL | if b < &a { | ^^^^-- | | | help: use the right value directly: `a` -error: aborting due to 2 previous errors +error: taken reference of right operand + --> $DIR/op_ref.rs:57:13 + | +LL | let z = x & &y; + | ^^^^-- + | | + | help: use the right value directly: `y` + +error: aborting due to 3 previous errors