#![feature(generators)] #![feature(min_type_alias_impl_trait)] use enso_shapely::*; // ============= // === Utils === // ============= /// To fail compilation if `T` is not `IntoIterator`. fn is_into_iterator(){} fn to_vector(t: T) -> Vec where T : IntoIterator, T::Item: Copy { t.into_iter().collect() } // ===================================== // === Struct with single type param === // ===================================== #[derive(Iterator, IteratorMut, Eq, PartialEq, Debug)] pub struct PairTT(T, T); #[test] fn derive_iterator_single_t() { is_into_iterator::<& PairTT>(); is_into_iterator::<&mut PairTT>(); let get_pair = || PairTT(4, 49); // just collect values let pair = get_pair(); let collected = pair.iter().copied().collect::>(); assert_eq!(collected, vec![4, 49]); // IntoIterator for &mut Val let mut pair = get_pair(); for i in &mut pair { *i += 1 } assert_eq!(pair, PairTT(5, 50)); // iter_mut for i in pair.iter_mut() { *i += 1 } assert_eq!(pair, PairTT(6, 51)); // IntoIterator for & Val let pair = get_pair(); // not mut anymore let mut sum = 0; for i in &pair { sum += i; } assert_eq!(sum, pair.0 + pair.1) } // =================================== // === Struct with two type params === // =================================== #[derive(Iterator, IteratorMut, Eq, PartialEq, Debug)] pub struct PairUV(U,V); #[test] fn two_params() { // verify that iter uses only the last type param field let pair = PairUV(5, 10); assert_eq!(to_vector(pair.iter().copied()), vec![10]); } // ====================================== // === Struct without any type params === // ====================================== #[derive(Iterator, Eq, PartialEq, Debug)] pub struct Monomorphic(i32); #[test] fn no_params() { // `derive(Iterator)` is no-op for structures with no type parameters. // We just make sure that it does not cause compilation error. } // ======================== // === Enumeration Type === // ======================== #[derive(Iterator)] #[warn(dead_code)] // value is never read and shouldn't be pub struct Unrecognized{ pub value : String } #[derive(Iterator)] pub enum Foo { Con1(PairUV), Con2(PairTT), Con3(Unrecognized) } #[test] fn enum_is_into_iterator() { is_into_iterator::<&Foo>(); } #[test] fn enum_iter1() { let v = Foo::Con1(PairUV(4, 50)); let mut v_iter = v.into_iter(); assert_eq!(*v_iter.next().unwrap(),50); assert!(v_iter.next().is_none()); } #[test] fn enum_iter2() { let v: Foo = Foo::Con2(PairTT(6,60)); let mut v_iter = v.into_iter(); assert_eq!(*v_iter.next().unwrap(),6); assert_eq!(*v_iter.next().unwrap(),60); assert!(v_iter.next().is_none()); } #[test] fn enum_iter3() { let v: Foo = Foo::Con3(Unrecognized{value:"foo".into()}); let mut v_iter = v.into_iter(); assert!(v_iter.next().is_none()); } // ======================= // === Dependent Types === // ======================= #[derive(Iterator)] #[derive(IteratorMut)] pub struct DependentTest { a:T, b:(T,U,PairUV), // is never used, as it doesn't depend on `T` (last param) #[allow(dead_code)] c:PairTT, d:(i32, Option>), } #[test] fn dependent_test_iter() { let val = DependentTest{ a : 1, b : (2,3,PairUV(4,5)), c : PairTT(6,6), d : (7, Some(vec![8,9])), }; let mut v_iter = val.into_iter(); assert_eq!(*v_iter.next().unwrap(), 1); assert_eq!(*v_iter.next().unwrap(), 2); // 3 is `U` in tuple // 4 is `U` in pair assert_eq!(*v_iter.next().unwrap(), 5); // 7 is `i32` in tuple assert_eq!(*v_iter.next().unwrap(), 8); assert_eq!(*v_iter.next().unwrap(), 9); assert!(v_iter.next().is_none()); }