| #![warn(clippy::unnecessary_fold)] | |
| fn is_any(acc: bool, x: usize) -> bool { | |
| acc || x > 2 | |
| } | |
| /// Calls which should trigger the `UNNECESSARY_FOLD` lint | |
| fn unnecessary_fold() { | |
| use std::ops::{Add, Mul}; | |
| // Can be replaced by .any | |
| let _ = (0..3).any(|x| x > 2); | |
| //~^ unnecessary_fold | |
| // Can be replaced by .any (checking suggestion) | |
| let _ = (0..3).fold(false, is_any); | |
| //~^ redundant_closure | |
| // Can be replaced by .all | |
| let _ = (0..3).all(|x| x > 2); | |
| //~^ unnecessary_fold | |
| // Can be replaced by .sum | |
| let _: i32 = (0..3).sum(); | |
| //~^ unnecessary_fold | |
| let _: i32 = (0..3).sum(); | |
| //~^ unnecessary_fold | |
| let _: i32 = (0..3).sum(); | |
| //~^ unnecessary_fold | |
| // Can be replaced by .product | |
| let _: i32 = (0..3).product(); | |
| //~^ unnecessary_fold | |
| let _: i32 = (0..3).product(); | |
| //~^ unnecessary_fold | |
| let _: i32 = (0..3).product(); | |
| //~^ unnecessary_fold | |
| } | |
| /// Should trigger the `UNNECESSARY_FOLD` lint, with an error span including exactly `.fold(...)` | |
| fn unnecessary_fold_span_for_multi_element_chain() { | |
| let _: bool = (0..3).map(|x| 2 * x).any(|x| x > 2); | |
| //~^ unnecessary_fold | |
| } | |
| /// Calls which should not trigger the `UNNECESSARY_FOLD` lint | |
| fn unnecessary_fold_should_ignore() { | |
| let _ = (0..3).fold(true, |acc, x| acc || x > 2); | |
| let _ = (0..3).fold(false, |acc, x| acc && x > 2); | |
| let _ = (0..3).fold(1, |acc, x| acc + x); | |
| let _ = (0..3).fold(0, |acc, x| acc * x); | |
| let _ = (0..3).fold(0, |acc, x| 1 + acc + x); | |
| struct Adder; | |
| impl Adder { | |
| fn add(lhs: i32, rhs: i32) -> i32 { | |
| unimplemented!() | |
| } | |
| fn mul(lhs: i32, rhs: i32) -> i32 { | |
| unimplemented!() | |
| } | |
| } | |
| // `add`/`mul` are inherent methods | |
| let _: i32 = (0..3).fold(0, Adder::add); | |
| let _: i32 = (0..3).fold(1, Adder::mul); | |
| trait FakeAdd<Rhs = Self> { | |
| type Output; | |
| fn add(self, other: Rhs) -> Self::Output; | |
| } | |
| impl FakeAdd for i32 { | |
| type Output = Self; | |
| fn add(self, other: i32) -> Self::Output { | |
| self + other | |
| } | |
| } | |
| trait FakeMul<Rhs = Self> { | |
| type Output; | |
| fn mul(self, other: Rhs) -> Self::Output; | |
| } | |
| impl FakeMul for i32 { | |
| type Output = Self; | |
| fn mul(self, other: i32) -> Self::Output { | |
| self * other | |
| } | |
| } | |
| // `add`/`mul` come from an unrelated trait | |
| let _: i32 = (0..3).fold(0, FakeAdd::add); | |
| let _: i32 = (0..3).fold(1, FakeMul::mul); | |
| let _ = [(0..2), (0..3)].iter().fold(0, |a, b| a + b.len()); | |
| let _ = [(0..2), (0..3)].iter().fold(1, |a, b| a * b.len()); | |
| } | |
| /// Should lint only the line containing the fold | |
| fn unnecessary_fold_over_multiple_lines() { | |
| let _ = (0..3) | |
| .map(|x| x + 1) | |
| .filter(|x| x % 2 == 0) | |
| .any(|x| x > 2); | |
| //~^ unnecessary_fold | |
| } | |
| fn issue10000() { | |
| use std::collections::HashMap; | |
| use std::hash::BuildHasher; | |
| use std::ops::{Add, Mul}; | |
| fn anything<T>(_: T) {} | |
| fn num(_: i32) {} | |
| fn smoketest_map<S: BuildHasher>(mut map: HashMap<i32, i32, S>) { | |
| map.insert(0, 0); | |
| assert_eq!(map.values().sum::<i32>(), 0); | |
| //~^ unnecessary_fold | |
| // more cases: | |
| let _ = map.values().sum::<i32>(); | |
| //~^ unnecessary_fold | |
| let _ = map.values().sum::<i32>(); | |
| //~^ unnecessary_fold | |
| let _ = map.values().product::<i32>(); | |
| //~^ unnecessary_fold | |
| let _ = map.values().product::<i32>(); | |
| //~^ unnecessary_fold | |
| let _: i32 = map.values().sum(); | |
| //~^ unnecessary_fold | |
| let _: i32 = map.values().sum(); | |
| //~^ unnecessary_fold | |
| let _: i32 = map.values().product(); | |
| //~^ unnecessary_fold | |
| let _: i32 = map.values().product(); | |
| //~^ unnecessary_fold | |
| anything(map.values().sum::<i32>()); | |
| //~^ unnecessary_fold | |
| anything(map.values().sum::<i32>()); | |
| //~^ unnecessary_fold | |
| anything(map.values().product::<i32>()); | |
| //~^ unnecessary_fold | |
| anything(map.values().product::<i32>()); | |
| //~^ unnecessary_fold | |
| num(map.values().sum()); | |
| //~^ unnecessary_fold | |
| num(map.values().sum()); | |
| //~^ unnecessary_fold | |
| num(map.values().product()); | |
| //~^ unnecessary_fold | |
| num(map.values().product()); | |
| //~^ unnecessary_fold | |
| } | |
| smoketest_map(HashMap::new()); | |
| fn add_turbofish_not_necessary() -> i32 { | |
| (0..3).sum() | |
| //~^ unnecessary_fold | |
| } | |
| fn mul_turbofish_not_necessary() -> i32 { | |
| (0..3).product() | |
| //~^ unnecessary_fold | |
| } | |
| fn add_turbofish_necessary() -> impl Add { | |
| (0..3).sum::<i32>() | |
| //~^ unnecessary_fold | |
| } | |
| fn mul_turbofish_necessary() -> impl Mul { | |
| (0..3).product::<i32>() | |
| //~^ unnecessary_fold | |
| } | |
| } | |
| fn issue16581() { | |
| let _ = (2..=3).product::<i32>(); | |
| //~^ unnecessary_fold | |
| let _ = (1..=3).sum::<i32>(); | |
| //~^ unnecessary_fold | |
| let _ = (2..=3).product::<i32>(); | |
| //~^ unnecessary_fold | |
| let _ = (1..=3).sum::<i32>(); | |
| //~^ unnecessary_fold | |
| let _ = (0..3).any(|x| x > 2); | |
| //~^ unnecessary_fold | |
| let _ = (0..3).all(|x| x > 2); | |
| //~^ unnecessary_fold | |
| let _ = (0..3).sum::<i32>(); | |
| //~^ unnecessary_fold | |
| let _ = (0..3).product::<i32>(); | |
| //~^ unnecessary_fold | |
| } | |
| fn wrongly_unmangled_macros() { | |
| macro_rules! test_expr { | |
| ($e:expr) => { | |
| ($e + 1) > 2 | |
| }; | |
| } | |
| let _ = (0..3).any(|x| test_expr!(x)); | |
| //~^ unnecessary_fold | |
| } | |
| fn main() {} |