diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 8f265ae2b..10b9bb9d9 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -23,7 +23,9 @@ jobs: steps: - uses: actions/checkout@v4 - uses: dtolnay/rust-toolchain@stable - - run: RUSTFLAGS="--deny warnings" cargo check ${{ matrix.features }} + with: + components: clippy + - run: RUSTFLAGS="--deny warnings" cargo clippy ${{ matrix.features }} msrv: runs-on: ubuntu-latest diff --git a/Cargo.toml b/Cargo.toml index f1ffe19cd..9903ed4a9 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -15,6 +15,7 @@ categories = ["algorithms", "rust-patterns"] edition = "2018" +# When bumping, please resolve all `#[allow(clippy::*)]` that are newly resolvable. rust-version = "1.43.1" [lib] diff --git a/benches/bench1.rs b/benches/bench1.rs index b01b8f360..8d8881676 100644 --- a/benches/bench1.rs +++ b/benches/bench1.rs @@ -475,6 +475,8 @@ fn merge_default(c: &mut Criterion) { let mut data1 = vec![0; 1024]; let mut data2 = vec![0; 800]; let mut x = 0; + + #[allow(clippy::explicit_counter_loop, clippy::unused_enumerate_index)] for (_, elt) in data1.iter_mut().enumerate() { *elt = x; x += 1; @@ -501,6 +503,8 @@ fn merge_by_cmp(c: &mut Criterion) { let mut data1 = vec![0; 1024]; let mut data2 = vec![0; 800]; let mut x = 0; + + #[allow(clippy::explicit_counter_loop, clippy::unused_enumerate_index)] for (_, elt) in data1.iter_mut().enumerate() { *elt = x; x += 1; @@ -527,6 +531,8 @@ fn merge_by_lt(c: &mut Criterion) { let mut data1 = vec![0; 1024]; let mut data2 = vec![0; 800]; let mut x = 0; + + #[allow(clippy::explicit_counter_loop, clippy::unused_enumerate_index)] for (_, elt) in data1.iter_mut().enumerate() { *elt = x; x += 1; @@ -553,6 +559,8 @@ fn kmerge_default(c: &mut Criterion) { let mut data1 = vec![0; 1024]; let mut data2 = vec![0; 800]; let mut x = 0; + + #[allow(clippy::explicit_counter_loop, clippy::unused_enumerate_index)] for (_, elt) in data1.iter_mut().enumerate() { *elt = x; x += 1; @@ -592,7 +600,7 @@ fn kmerge_tenway(c: &mut Criterion) { let mut chunks = Vec::new(); let mut rest = &mut data[..]; - while rest.len() > 0 { + while !rest.is_empty() { let chunk_len = 1 + rng(&mut state) % 512; let chunk_len = cmp::min(rest.len(), chunk_len as usize); let (fst, tail) = { rest }.split_at_mut(chunk_len); diff --git a/benches/extra/zipslices.rs b/benches/extra/zipslices.rs index 5476c0cb8..a7120e168 100644 --- a/benches/extra/zipslices.rs +++ b/benches/extra/zipslices.rs @@ -138,6 +138,8 @@ where /// A helper trait to let `ZipSlices` accept both `&[T]` and `&mut [T]`. /// +/// # Safety +/// /// Unsafe trait because: /// /// - Implementors must guarantee that `get_unchecked` is valid for all indices `0..len()`. diff --git a/benches/fold_specialization.rs b/benches/fold_specialization.rs index 3a040305b..b44f34721 100644 --- a/benches/fold_specialization.rs +++ b/benches/fold_specialization.rs @@ -46,7 +46,10 @@ mod specialization { let arr = [1; 1024]; c.bench_function("internal specialized", move |b| { - b.iter(|| arr.iter().intersperse(&0).fold(0, |acc, x| acc + x)) + b.iter(|| { + #[allow(clippy::unnecessary_fold)] + arr.iter().intersperse(&0).fold(0, |acc, x| acc + x) + }) }); } @@ -54,7 +57,10 @@ mod specialization { let arr = [1; 1024]; c.bench_function("internal unspecialized", move |b| { - b.iter(|| Unspecialized(arr.iter().intersperse(&0)).fold(0, |acc, x| acc + x)) + b.iter(|| { + #[allow(clippy::unnecessary_fold)] + Unspecialized(arr.iter().intersperse(&0)).fold(0, |acc, x| acc + x) + }) }); } } diff --git a/examples/iris.rs b/examples/iris.rs index af64322d6..798fdb08e 100644 --- a/examples/iris.rs +++ b/examples/iris.rs @@ -9,7 +9,7 @@ use std::iter::repeat; use std::num::ParseFloatError; use std::str::FromStr; -static DATA: &'static str = include_str!("iris.data"); +static DATA: &str = include_str!("iris.data"); #[derive(Clone, Debug)] struct Iris { @@ -38,7 +38,7 @@ impl FromStr for Iris { name: "".into(), data: [0.; 4], }; - let mut parts = s.split(",").map(str::trim); + let mut parts = s.split(',').map(str::trim); // using Iterator::by_ref() for (index, part) in parts.by_ref().take(4).enumerate() { diff --git a/src/adaptors/mod.rs b/src/adaptors/mod.rs index f622bceda..a5b182d78 100644 --- a/src/adaptors/mod.rs +++ b/src/adaptors/mod.rs @@ -607,11 +607,11 @@ where Some(item) => Ok(f(acc, item)), None => Err(acc), }); - let res = match res { + + match res { Ok(val) => val, Err(val) => val, - }; - res + } } } diff --git a/src/adaptors/multi_product.rs b/src/adaptors/multi_product.rs index ef7fadba8..f02f8c740 100644 --- a/src/adaptors/multi_product.rs +++ b/src/adaptors/multi_product.rs @@ -220,9 +220,9 @@ where self.0.iter().fold( (0, Some(0)), |acc, - &MultiProductIter { - ref iter, - ref iter_orig, + MultiProductIter { + iter, + iter_orig, cur: _, }| { let cur_size = iter.size_hint(); diff --git a/src/either_or_both.rs b/src/either_or_both.rs index 9dbc880d3..2232cd68c 100644 --- a/src/either_or_both.rs +++ b/src/either_or_both.rs @@ -29,19 +29,13 @@ impl EitherOrBoth { /// If `Left`, return true. Otherwise, return false. /// Exclusive version of [`has_left`](EitherOrBoth::has_left). pub fn is_left(&self) -> bool { - match *self { - Left(_) => true, - _ => false, - } + matches!(self, Left(_)) } /// If `Right`, return true. Otherwise, return false. /// Exclusive version of [`has_right`](EitherOrBoth::has_right). pub fn is_right(&self) -> bool { - match *self { - Right(_) => true, - _ => false, - } + matches!(self, Right(_)) } /// If `Both`, return true. Otherwise, return false. @@ -500,6 +494,7 @@ impl EitherOrBoth { } } +#[allow(clippy::from_over_into)] impl Into>> for EitherOrBoth { fn into(self) -> Option> { match self { diff --git a/src/lib.rs b/src/lib.rs index f3b6e807d..211827ff2 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1008,7 +1008,7 @@ pub trait Itertools: Iterator { J: IntoIterator, F: FnMut(&Self::Item, &Self::Item) -> bool, { - merge_join::merge_by_new(self, other.into_iter(), is_first) + merge_join::merge_by_new(self, other, is_first) } /// Create an iterator that merges items from both this and the specified @@ -2047,6 +2047,7 @@ pub trait Itertools: Iterator { /// let data : Option = None; /// assert_eq!(data.into_iter().all_equal_value(), Err(None)); /// ``` + #[allow(clippy::type_complexity)] fn all_equal_value(&mut self) -> Result> where Self: Sized, @@ -4013,7 +4014,7 @@ where (None, None) => return, (a, b) => { let equal = match (&a, &b) { - (&Some(ref a), &Some(ref b)) => a == b, + (Some(a), Some(b)) => a == b, _ => false, }; assert!( diff --git a/src/multipeek_impl.rs b/src/multipeek_impl.rs index a78bc447b..6f800b6fb 100644 --- a/src/multipeek_impl.rs +++ b/src/multipeek_impl.rs @@ -79,7 +79,7 @@ where return None; } } - } else if let Some(r) = self.buf.get(0) { + } else if let Some(r) = self.buf.front() { if !accept(r) { return None; } diff --git a/src/tuple_impl.rs b/src/tuple_impl.rs index 9cfb484af..4a7cd4da8 100644 --- a/src/tuple_impl.rs +++ b/src/tuple_impl.rs @@ -62,7 +62,7 @@ where buffer .iter() .position(|x| x.is_none()) - .unwrap_or_else(|| buffer.len()) + .unwrap_or(buffer.len()) }; (len, Some(len)) } diff --git a/tests/quick.rs b/tests/quick.rs index 92d3f9f8e..0ca32f49a 100644 --- a/tests/quick.rs +++ b/tests/quick.rs @@ -779,11 +779,11 @@ quickcheck! { fn peek_nth_mut_replace(a: Vec, b: Vec) -> () { let mut it = peek_nth(a.iter()); - for i in 0..a.len().min(b.len()) { - *it.peek_nth_mut(i).unwrap() = &b[i]; + for (i, m) in b.iter().enumerate().take(a.len().min(b.len())) { + *it.peek_nth_mut(i).unwrap() = m; } - for i in 0..a.len() { - assert_eq!(it.next().unwrap(), b.get(i).unwrap_or(&a[i])); + for (i, m) in a.iter().enumerate() { + assert_eq!(it.next().unwrap(), b.get(i).unwrap_or(m)); } assert_eq!(it.next(), None); assert_eq!(it.next(), None); @@ -875,9 +875,8 @@ quickcheck! { quickcheck! { fn size_put_back(a: Vec, x: Option) -> bool { let mut it = put_back(a.into_iter()); - match x { - Some(t) => it.put_back(t), - None => {} + if let Some(t) = x { + it.put_back(t) } correct_size_hint(it) } @@ -999,7 +998,7 @@ quickcheck! { } } } - cmb.next() == None + cmb.next().is_none() } } @@ -1310,7 +1309,7 @@ struct Val(u32, u32); impl PartialOrd for Val { fn partial_cmp(&self, other: &Val) -> Option { - self.0.partial_cmp(&other.0) + Some(self.cmp(other)) } } @@ -1413,7 +1412,7 @@ quickcheck! { fn at_most_one_i32(a: Vec) -> TestResult { let ret = a.iter().cloned().at_most_one(); match a.len() { - 0 => TestResult::from_bool(ret.unwrap() == None), + 0 => TestResult::from_bool(ret.unwrap().is_none()), 1 => TestResult::from_bool(ret.unwrap() == Some(a[0])), _ => TestResult::from_bool(ret.unwrap_err().eq(a.iter().cloned())), } diff --git a/tests/test_core.rs b/tests/test_core.rs index c624a7e33..fc2c858a3 100644 --- a/tests/test_core.rs +++ b/tests/test_core.rs @@ -27,7 +27,7 @@ fn product2() { assert!(prod.next() == Some(('α', 1))); assert!(prod.next() == Some(('β', 0))); assert!(prod.next() == Some(('β', 1))); - assert!(prod.next() == None); + assert!(prod.next().is_none()); } #[test] diff --git a/tests/test_std.rs b/tests/test_std.rs index 732be7b7d..24429e919 100644 --- a/tests/test_std.rs +++ b/tests/test_std.rs @@ -40,19 +40,19 @@ fn product3() { fn interleave_shortest() { let v0: Vec = vec![0, 2, 4]; let v1: Vec = vec![1, 3, 5, 7]; - let it = v0.into_iter().interleave_shortest(v1.into_iter()); + let it = v0.into_iter().interleave_shortest(v1); assert_eq!(it.size_hint(), (6, Some(6))); assert_eq!(it.collect_vec(), vec![0, 1, 2, 3, 4, 5]); let v0: Vec = vec![0, 2, 4, 6, 8]; let v1: Vec = vec![1, 3, 5]; - let it = v0.into_iter().interleave_shortest(v1.into_iter()); + let it = v0.into_iter().interleave_shortest(v1); assert_eq!(it.size_hint(), (7, Some(7))); assert_eq!(it.collect_vec(), vec![0, 1, 2, 3, 4, 5, 6]); let i0 = ::std::iter::repeat(0); let v1: Vec<_> = vec![1, 3, 5]; - let it = i0.interleave_shortest(v1.into_iter()); + let it = i0.interleave_shortest(v1); assert_eq!(it.size_hint(), (7, Some(7))); let v0: Vec<_> = vec![0, 2, 4]; @@ -93,7 +93,7 @@ fn duplicates() { let ys_rev = [1, 0]; it::assert_equal(ys_rev.iter(), xs.iter().duplicates().rev()); - let xs = vec![0, 1, 2, 1, 2]; + let xs = [0, 1, 2, 1, 2]; let ys = vec![1, 2]; assert_eq!(ys, xs.iter().duplicates().cloned().collect_vec()); assert_eq!( @@ -146,7 +146,7 @@ fn intersperse() { let ys = [0, 1, 2, 3]; let mut it = ys[..0].iter().copied().intersperse(1); - assert!(it.next() == None); + assert!(it.next().is_none()); } #[test] @@ -167,7 +167,7 @@ fn dedup() { #[test] fn coalesce() { - let data = vec![-1., -2., -3., 3., 1., 0., -1.]; + let data = [-1., -2., -3., 3., 1., 0., -1.]; let it = data.iter().cloned().coalesce(|x, y| { if (x >= 0.) == (y >= 0.) { Ok(x + y) @@ -395,8 +395,8 @@ fn trait_pointers() { #[test] fn merge_by() { let odd: Vec<(u32, &str)> = vec![(1, "hello"), (3, "world"), (5, "!")]; - let even = vec![(2, "foo"), (4, "bar"), (6, "baz")]; - let expected = vec![ + let even = [(2, "foo"), (4, "bar"), (6, "baz")]; + let expected = [ (1, "hello"), (2, "foo"), (3, "world"), @@ -417,9 +417,9 @@ fn merge_by_btree() { let mut bt2 = BTreeMap::new(); bt2.insert("foo", 2); bt2.insert("bar", 4); - let results = bt1.into_iter().merge_by(bt2.into_iter(), |a, b| a.0 <= b.0); + let results = bt1.into_iter().merge_by(bt2, |a, b| a.0 <= b.0); let expected = vec![("bar", 4), ("foo", 2), ("hello", 1), ("world", 3)]; - it::assert_equal(results, expected.into_iter()); + it::assert_equal(results, expected); } #[allow(deprecated)] @@ -651,7 +651,7 @@ fn test_multipeek_reset() { #[test] fn test_multipeek_peeking_next() { use crate::it::PeekingNext; - let nums = vec![1u8, 2, 3, 4, 5, 6, 7]; + let nums = [1u8, 2, 3, 4, 5, 6, 7]; let mut mp = multipeek(nums.iter().copied()); assert_eq!(mp.peeking_next(|&x| x != 0), Some(1)); @@ -711,7 +711,7 @@ fn test_peek_nth() { #[test] fn test_peek_nth_peeking_next() { use it::PeekingNext; - let nums = vec![1u8, 2, 3, 4, 5, 6, 7]; + let nums = [1u8, 2, 3, 4, 5, 6, 7]; let mut iter = peek_nth(nums.iter().copied()); assert_eq!(iter.peeking_next(|&x| x != 0), Some(1)); @@ -740,7 +740,7 @@ fn test_peek_nth_peeking_next() { #[test] fn test_peek_nth_next_if() { - let nums = vec![1u8, 2, 3, 4, 5, 6, 7]; + let nums = [1u8, 2, 3, 4, 5, 6, 7]; let mut iter = peek_nth(nums.iter().copied()); assert_eq!(iter.next_if(|&x| x != 0), Some(1)); @@ -863,12 +863,12 @@ fn group_by() { #[test] fn group_by_lazy_2() { - let data = vec![0, 1]; + let data = [0, 1]; let groups = data.iter().group_by(|k| *k); let gs = groups.into_iter().collect_vec(); it::assert_equal(data.iter(), gs.into_iter().flat_map(|(_k, g)| g)); - let data = vec![0, 1, 1, 0, 0]; + let data = [0, 1, 1, 0, 0]; let groups = data.iter().group_by(|k| *k); let mut gs = groups.into_iter().collect_vec(); gs[1..].reverse(); @@ -883,7 +883,7 @@ fn group_by_lazy_2() { } it::assert_equal(&mut groups[0], &[1, 1]); - let data = vec![0, 0, 0, 1, 1, 0, 0, 2, 2, 3, 3]; + let data = [0, 0, 0, 1, 1, 0, 0, 2, 2, 3, 3]; let grouper = data.iter().group_by(|k| *k); let mut groups = Vec::new(); for (i, (_, group)) in grouper.into_iter().enumerate() { @@ -900,7 +900,7 @@ fn group_by_lazy_2() { it::assert_equal(&mut groups[2], &[3, 3]); // use groups as chunks - let data = vec![0, 0, 0, 1, 1, 0, 0, 2, 2, 3, 3]; + let data = [0, 0, 0, 1, 1, 0, 0, 2, 2, 3, 3]; let mut i = 0; let grouper = data.iter().group_by(move |_| { let k = i / 3; @@ -921,7 +921,7 @@ fn group_by_lazy_2() { #[test] fn group_by_lazy_3() { // test consuming each group on the lap after it was produced - let data = vec![0, 0, 0, 1, 1, 0, 0, 1, 1, 2, 2]; + let data = [0, 0, 0, 1, 1, 0, 0, 1, 1, 2, 2]; let grouper = data.iter().group_by(|elt| *elt); let mut last = None; for (key, group) in &grouper { @@ -936,7 +936,7 @@ fn group_by_lazy_3() { #[test] fn chunks() { - let data = vec![0, 0, 0, 1, 1, 0, 0, 2, 2, 3, 3]; + let data = [0, 0, 0, 1, 1, 0, 0, 2, 2, 3, 3]; let grouper = data.iter().chunks(3); for (i, chunk) in grouper.into_iter().enumerate() { match i { @@ -1216,7 +1216,7 @@ fn powerset() { #[test] fn diff_mismatch() { - let a = vec![1, 2, 3, 4]; + let a = [1, 2, 3, 4]; let b = vec![1.0, 5.0, 3.0, 4.0]; let b_map = b.into_iter().map(|f| f as i32); let diff = it::diff_with(a.iter(), b_map, |a, b| *a == b); @@ -1230,7 +1230,7 @@ fn diff_mismatch() { #[test] fn diff_longer() { - let a = vec![1, 2, 3, 4]; + let a = [1, 2, 3, 4]; let b = vec![1.0, 2.0, 3.0, 4.0, 5.0, 6.0]; let b_map = b.into_iter().map(|f| f as i32); let diff = it::diff_with(a.iter(), b_map, |a, b| *a == b); @@ -1243,7 +1243,7 @@ fn diff_longer() { #[test] fn diff_shorter() { - let a = vec![1, 2, 3, 4]; + let a = [1, 2, 3, 4]; let b = vec![1.0, 2.0]; let b_map = b.into_iter().map(|f| f as i32); let diff = it::diff_with(a.iter(), b_map, |a, b| *a == b); @@ -1265,7 +1265,7 @@ fn extrema_set() { impl PartialOrd for Val { fn partial_cmp(&self, other: &Val) -> Option { - self.0.partial_cmp(&other.0) + Some(self.cmp(other)) } } @@ -1314,7 +1314,7 @@ fn minmax() { impl PartialOrd for Val { fn partial_cmp(&self, other: &Val) -> Option { - self.0.partial_cmp(&other.0) + Some(self.cmp(other)) } } @@ -1446,6 +1446,7 @@ fn multiunzip() { .multiunzip(); assert_eq!((a, b, c), (vec![0, 3, 6], vec![1, 4, 7], vec![2, 5, 8])); let (): () = [(), (), ()].iter().cloned().multiunzip(); + #[allow(clippy::type_complexity)] let t: ( Vec<_>, Vec<_>,