#![allow(unstable_name_collisions)] use itertools::Itertools; #[derive(Debug, Clone)] #[must_use = "iterators are lazy and do nothing unless consumed"] struct Panicking; impl Iterator for Panicking { type Item = u8; fn next(&mut self) -> Option { panic!("iterator adaptor is not lazy") } fn size_hint(&self) -> (usize, Option) { (0, Some(0)) } } impl ExactSizeIterator for Panicking {} /// ## Usage example /// ```compile_fail /// must_use_tests! { /// name { /// Panicking.name(); // Add `let _ =` only if required (encountered error). /// } /// // ... /// } /// ``` /// /// **TODO:** test missing `must_use` attributes better, maybe with a new lint. macro_rules! must_use_tests { ($($(#[$attr:meta])* $name:ident $body:block)*) => { $( /// `#[deny(unused_must_use)]` should force us to ignore the resulting iterators /// by adding `let _ = ...;` on every iterator. /// If it does not, then a `must_use` attribute is missing on the associated struct. /// /// However, it's only helpful if we don't add `let _ =` before seeing if there is an error or not. /// And it does not protect us against removed `must_use` attributes. /// There is no simple way to test this yet. #[deny(unused_must_use)] #[test] $(#[$attr])* fn $name() $body )* }; } must_use_tests! { // Itertools trait: interleave { let _ = Panicking.interleave(Panicking); } interleave_shortest { let _ = Panicking.interleave_shortest(Panicking); } intersperse { let _ = Panicking.intersperse(0); } intersperse_with { let _ = Panicking.intersperse_with(|| 0); } get { let _ = Panicking.get(1..4); let _ = Panicking.get(1..=4); let _ = Panicking.get(1..); let _ = Panicking.get(..4); let _ = Panicking.get(..=4); let _ = Panicking.get(..); } zip_longest { let _ = Panicking.zip_longest(Panicking); } zip_eq { let _ = Panicking.zip_eq(Panicking); } batching { let _ = Panicking.batching(Iterator::next); } chunk_by { // ChunkBy let _ = Panicking.chunk_by(|x| *x); // Groups let _ = Panicking.chunk_by(|x| *x).into_iter(); } chunks { // IntoChunks let _ = Panicking.chunks(1); let _ = Panicking.chunks(2); // Chunks let _ = Panicking.chunks(1).into_iter(); let _ = Panicking.chunks(2).into_iter(); } tuple_windows { let _ = Panicking.tuple_windows::<(_,)>(); let _ = Panicking.tuple_windows::<(_, _)>(); let _ = Panicking.tuple_windows::<(_, _, _)>(); } circular_tuple_windows { let _ = Panicking.circular_tuple_windows::<(_,)>(); let _ = Panicking.circular_tuple_windows::<(_, _)>(); let _ = Panicking.circular_tuple_windows::<(_, _, _)>(); } tuples { let _ = Panicking.tuples::<(_,)>(); let _ = Panicking.tuples::<(_, _)>(); let _ = Panicking.tuples::<(_, _, _)>(); } tee { let _ = Panicking.tee(); } map_into { let _ = Panicking.map_into::(); } map_ok { let _ = Panicking.map(Ok::).map_ok(|x| x + 1); } filter_ok { let _ = Panicking.map(Ok::).filter_ok(|x| x % 2 == 0); } filter_map_ok { let _ = Panicking.map(Ok::).filter_map_ok(|x| { if x % 2 == 0 { Some(x + 1) } else { None } }); } flatten_ok { let _ = Panicking.map(|x| Ok::<_, ()>([x])).flatten_ok(); } merge { let _ = Panicking.merge(Panicking); } merge_by { let _ = Panicking.merge_by(Panicking, |_, _| true); } merge_join_by { let _ = Panicking.merge_join_by(Panicking, |_, _| true); let _ = Panicking.merge_join_by(Panicking, Ord::cmp); } #[should_panic] kmerge { let _ = Panicking.map(|_| Panicking).kmerge(); } #[should_panic] kmerge_by { let _ = Panicking.map(|_| Panicking).kmerge_by(|_, _| true); } cartesian_product { let _ = Panicking.cartesian_product(Panicking); } multi_cartesian_product { let _ = vec![Panicking, Panicking, Panicking].into_iter().multi_cartesian_product(); } coalesce { let _ = Panicking.coalesce(|x, y| if x == y { Ok(x) } else { Err((x, y)) }); } dedup { let _ = Panicking.dedup(); } dedup_by { let _ = Panicking.dedup_by(|_, _| true); } dedup_with_count { let _ = Panicking.dedup_with_count(); } dedup_by_with_count { let _ = Panicking.dedup_by_with_count(|_, _| true); } duplicates { let _ = Panicking.duplicates(); } duplicates_by { let _ = Panicking.duplicates_by(|x| *x); } unique { let _ = Panicking.unique(); } unique_by { let _ = Panicking.unique_by(|x| *x); } peeking_take_while { let _ = Panicking.peekable().peeking_take_while(|x| x % 2 == 0); } take_while_ref { let _ = Panicking.take_while_ref(|x| x % 2 == 0); } take_while_inclusive { let _ = Panicking.take_while_inclusive(|x| x % 2 == 0); } while_some { let _ = Panicking.map(Some).while_some(); } tuple_combinations1 { let _ = Panicking.tuple_combinations::<(_,)>(); } #[should_panic] tuple_combinations2 { let _ = Panicking.tuple_combinations::<(_, _)>(); } #[should_panic] tuple_combinations3 { let _ = Panicking.tuple_combinations::<(_, _, _)>(); } combinations { let _ = Panicking.combinations(0); let _ = Panicking.combinations(1); let _ = Panicking.combinations(2); } combinations_with_replacement { let _ = Panicking.combinations_with_replacement(0); let _ = Panicking.combinations_with_replacement(1); let _ = Panicking.combinations_with_replacement(2); } permutations { let _ = Panicking.permutations(0); let _ = Panicking.permutations(1); let _ = Panicking.permutations(2); } powerset { let _ = Panicking.powerset(); } pad_using { let _ = Panicking.pad_using(25, |_| 10); } with_position { let _ = Panicking.with_position(); } positions { let _ = Panicking.positions(|v| v % 2 == 0); } update { let _ = Panicking.update(|n| *n += 1); } multipeek { let _ = Panicking.multipeek(); } // Not iterator themselves but still lazy. into_grouping_map { let _ = Panicking.map(|x| (x, x + 1)).into_grouping_map(); } into_grouping_map_by { let _ = Panicking.into_grouping_map_by(|x| *x); } // Macros: iproduct { let _ = itertools::iproduct!(Panicking); let _ = itertools::iproduct!(Panicking, Panicking); let _ = itertools::iproduct!(Panicking, Panicking, Panicking); } izip { let _ = itertools::izip!(Panicking); let _ = itertools::izip!(Panicking, Panicking); let _ = itertools::izip!(Panicking, Panicking, Panicking); } chain { let _ = itertools::chain!(Panicking); let _ = itertools::chain!(Panicking, Panicking); let _ = itertools::chain!(Panicking, Panicking, Panicking); } // Free functions: multizip { let _ = itertools::multizip((Panicking, Panicking)); } put_back { let _ = itertools::put_back(Panicking); let _ = itertools::put_back(Panicking).with_value(15); } peek_nth { let _ = itertools::peek_nth(Panicking); } put_back_n { let _ = itertools::put_back_n(Panicking); } rciter { let _ = itertools::rciter(Panicking); } }