// SPDX-License-Identifier: Apache-2.0 OR MIT #![cfg_attr( feature = "fn_traits", feature(proc_macro_hygiene, stmt_expr_attributes, type_ascription) )] #![cfg_attr(feature = "coroutine_trait", feature(coroutine_trait))] #![cfg_attr(feature = "fn_traits", feature(fn_traits, unboxed_closures))] #![cfg_attr(feature = "trusted_len", feature(trusted_len))] #![cfg_attr(not(feature = "std"), no_std)] #![allow( dead_code, clippy::cast_possible_truncation, clippy::cast_possible_wrap, clippy::items_after_statements, clippy::let_and_return, clippy::needless_return, clippy::never_loop, clippy::no_effect_underscore_binding, clippy::undocumented_unsafe_blocks, clippy::unnecessary_wraps )] use core::iter; use auto_enums::auto_enum; #[test] fn stable() { const ANS: &[i32] = &[28, 3]; #[auto_enum(Iterator)] fn match_(x: usize) -> impl Iterator { match x { 0 => 1..8, n if n > 3 => 2..=10, _ => (0..2).map(|x| x + 1), } } for (i, x) in ANS.iter().enumerate() { assert_eq!(match_(i).sum::(), *x); } // block + unsafe block + parentheses #[rustfmt::skip] #[allow(unused_parens, unused_braces, unused_unsafe)] #[auto_enum(Iterator)] fn block(x: usize) -> impl Iterator { {{({ unsafe {{({ unsafe { unsafe {{ match x { 0 => 1..8, n if n > 3 => 2..=10, _ => (0..2).map(|x| x + 1), } }}}})}}})}} } for (i, x) in ANS.iter().enumerate() { assert_eq!(block(i).sum::(), *x); } #[auto_enum(Iterator)] fn if_(x: usize) -> impl Iterator { if x == 0 { 1..8 } else if x > 3 { 2..=10 } else { (0..2).map(|x| x + 1) } } for (i, x) in ANS.iter().enumerate() { assert_eq!(if_(i).sum::(), *x); } #[auto_enum(Iterator)] fn method_call(x: usize) -> impl Iterator { if x == 0 { 1..8 } else if x > 3 { 2..=10 } else { (0..2).map(|x| x + 1) } .map(|x| x + 1) .map(|x| x - 1) } for (i, x) in ANS.iter().enumerate() { assert_eq!(method_call(i).sum::(), *x); } #[auto_enum(Iterator)] fn no_return(x: usize) -> impl Iterator { match x { 0 => 1..8, 3 => panic!(), _ => (0..2).map(|x| x + 1), } } for (i, x) in ANS.iter().enumerate() { assert_eq!(no_return(i).sum::(), *x); } #[auto_enum(Iterator)] fn no_return2(x: usize) -> impl Iterator { match x { 0 => 1..8, 3 => match x { 0 => panic!(), 1..=3 => panic!(), _ => unreachable!(), }, _ => (0..2).map(|x| x + 1), } } for (i, x) in ANS.iter().enumerate() { assert_eq!(no_return2(i).sum::(), *x); } #[auto_enum(Iterator)] fn no_return3(x: usize) -> impl Iterator { match x { 0 => 1..8, 3 => match x { 0 => panic!(), 1..=3 => (1..4).map(|x| x + 1), _ => unreachable!(), }, _ => (0..2).map(|x| x + 1), } } for (i, x) in ANS.iter().enumerate() { assert_eq!(no_return3(i).sum::(), *x); } #[auto_enum(Iterator)] fn no_return4(i: usize) -> impl Iterator { if i == 0 { 1..8 } else if i > 6 { panic!(); } else if i > 5 { std::panic!("5"); } else if i > 4 { core::panic!("4"); } else if i > 3 { unreachable!("3"); } else if i > 2 { std::unreachable!("2"); } else if i > 1 { core::unreachable!(); } else { (0..2).map(|x| x + 1) } } for (i, x) in ANS.iter().enumerate() { assert_eq!(no_return4(i).sum::(), *x); } #[auto_enum(fmt::Debug)] fn no_return5(x: usize) -> impl core::fmt::Debug { match x { 0 => 1..8, 3 => {} _ => 0..=2, } } #[auto_enum(Iterator)] fn return1(x: usize) -> impl Iterator { if x > 10 { return (0..x as i32).map(|x| x - 1); } if x == 0 { 1..8 } else if x > 3 { 2..=10 } else { (0..2).map(|x| x + 1) } } for (i, x) in ANS.iter().enumerate() { assert_eq!(return1(i).sum::(), *x); } #[auto_enum(Iterator)] fn break_in_loop(mut x: i32) -> impl Iterator { loop { if x < 0 { break x..0; } else if x % 5 == 0 { break 0..=x; } x -= 1; } } assert_eq!(break_in_loop(14).sum::(), 55); assert_eq!(break_in_loop(-5).sum::(), -15); #[auto_enum(Iterator)] fn break2(mut x: i32) -> impl Iterator { 'a: loop { if x < 0 { break 'a x..0; } else if x % 5 == 0 { break 0..=x; } x -= 1; } } assert_eq!(break2(14).sum::(), 55); assert_eq!(break2(-5).sum::(), -15); #[auto_enum(Iterator)] fn break3(mut x: i32) -> impl Iterator { 'a: loop { if x < 0 { loop { break 'a x..0; } } else if x % 5 == 0 { return loop { break 0..=x; }; } x -= 1; } } assert_eq!(break3(14).sum::(), 55); assert_eq!(break3(-5).sum::(), -15); #[auto_enum(Iterator)] fn return_in_loop(mut x: i32) -> impl Iterator { loop { if x < 0 { return x..0; } else if x % 5 == 0 { return 0..=x; } x -= 1; } } assert_eq!(return_in_loop(14).sum::(), 55); assert_eq!(return_in_loop(-5).sum::(), -15); #[auto_enum(Iterator)] fn return2(x: i32, y: i32) -> impl Iterator { #[auto_enum(Iterator)] let iter = match x { 0 => 2..8, _ if y < 0 => return y..=0, _ => 2..=10, }; match y { 0 => iter.flat_map(|x| 0..x), _ => iter.map(|x| x + 1), } } assert_eq!(return2(10, 10).sum::(), 63); #[auto_enum] fn return3(x: i32) -> Option> { if x < 0 { return None; } #[auto_enum(Iterator)] let iter = match x { 0 => 2..8, 1 => None?, 2 => std::option::Option::None?, 3 => core::option::Option::None?, 4 => None::<_>?, _ => 2..=10, }; Some(iter) } assert_eq!(return3(10).unwrap().sum::(), 54); #[auto_enum] fn return4(x: i32) -> Result, ()> { if x < 0 { return Err(()); } #[auto_enum(Iterator)] let iter = match x { 0 => 2..8, 1 => Err(())?, 2 => std::result::Result::Err(())?, 3 => core::result::Result::Err(())?, 4 => Err::<_, ()>(())?, _ => 2..=10, }; Ok(iter) } assert_eq!(return4(10).unwrap().sum::(), 54); #[auto_enum(Debug, Display)] fn try_operator1(x: i32) -> Result, impl core::fmt::Debug> { if x < 0 { Err(1_i32)?; } let iter = match x { 0 => Err(())?, _ => 2..=10, }; Ok(iter) } assert_eq!(try_operator1(10).unwrap().sum::(), 54); #[auto_enum(Debug)] fn try_operator2( x: i32, ) -> std::result::Result, impl core::fmt::Debug> { if x < 0 { Err(1_i32)?; } match x { 0 => Err(())?, _ => Ok(2..=10), } } assert_eq!(try_operator2(10).unwrap().sum::(), 54); #[auto_enum(Debug)] fn try_operator3( x: i32, ) -> core::result::Result, impl core::fmt::Debug> { if x < 0 { Err(1_i32)?; } match x { 0 => Err(())?, _ => Ok(2..=10), } } assert_eq!(try_operator3(10).unwrap().sum::(), 54); #[auto_enum] fn closure() { #[auto_enum(Iterator)] let f = |x| { if x > 10 { return (0..x as i32).map(|x| x - 1); } if x == 0 { 1..8 } else if x > 3 { 2..=10 } else { (0..2).map(|x| x + 1) } }; for (i, x) in ANS.iter().enumerate() { assert_eq!(f(i).sum::(), *x); } let f = { #[auto_enum(Iterator)] |x| { if x > 10 { return (0..x as i32).map(|x| x - 1); } if x == 0 { 1..8 } else if x > 3 { 2..=10 } else { (0..2).map(|x| { return x + 1; }) } } }; for (i, x) in ANS.iter().enumerate() { assert_eq!(f(i).sum::(), *x); } } closure(); #[cfg(feature = "transpose_methods")] #[auto_enum(Transpose, Iterator, Clone)] fn transpose(x: isize) -> Option + Clone> { match x { 0 => Some(1..8), _ if x < 0 => return None, _ => Some(0..=10), } .transpose() .map(|i| i.map(|x| x + 1).map(|x| x - 1)) } #[cfg(feature = "transpose_methods")] assert_eq!(transpose(0).unwrap().sum::(), 28); } #[test] fn marker() { #[auto_enum(Iterator)] fn marker3(x: i32, y: i32) -> impl Iterator { let iter; // if #[auto_enum] is used on Stmt::Semi, #[auto_enum] does not visit last expr #[auto_enum(Iterator)] match x { 0 => iter = marker!(2..8), _ => iter = marker!(2..=10), }; if y < 0 { return y..=0; } match y { 0 => iter.flat_map(|x| 0..x), _ => iter.map(|x| { if x < 0 { return x - 1; } x + 1 }), } } assert_eq!(marker3(10, 10).sum::(), 63); #[auto_enum(marker = marker_a, Iterator)] fn marker4(x: i32, y: i32) -> impl Iterator { let iter; #[auto_enum(Iterator)] match x { 0 => iter = marker!(2..8), _ if y < 0 => return y..=0, _ => iter = marker!(2..=10), }; match y { 0 => iter.flat_map(|x| 0..x), _ => iter.map(|x| x + 1), } } assert_eq!(marker4(10, 10).sum::(), 63); #[auto_enum(Iterator)] fn marker5(x: i32, y: i32) -> impl Iterator { let iter; #[auto_enum(marker = marker_a, Iterator)] match x { 0 => iter = marker_a!(2..8), _ if y < 0 => return y..=0, _ => iter = marker_a!(2..=10), }; match y { 0 => iter.flat_map(|x| 0..x), _ => iter.map(|x| x + 1), } } assert_eq!(marker5(10, 10).sum::(), 63); #[auto_enum(Iterator, marker = foo)] fn marker6(x: usize) -> impl Iterator { #[auto_enum(Iterator)] let _iter = match x { 0 => 1..8, _ => (0..2).map(|x| x + 1), }; #[auto_enum(Iterator, marker = bar)] let _iter = match x { 0 => 1..8, 1 => return foo!(1..9), n if n > 3 => { #[auto_enum(Iterator, marker = baz)] match x { 0 => 1..8, 1 => return foo!(1..9), 2 => baz!(1..9), n if n > 3 => 2..=10, _ => (0..2).map(|x| x + 1), } } _ => (0..2).map(|x| x + 1), }; match x { 0 => 1..8, _ => (0..2).map(|x| x + 1), } } assert_eq!(marker6(10).sum::(), 3); } #[cfg(feature = "transpose_methods")] #[cfg(feature = "std")] #[test] fn stable_std() { use std::{error::Error, fs::File, io, path::Path}; use auto_enums::enum_derive; #[auto_enum(Transpose, Write)] fn transpose_ok(file: Option<&Path>) -> io::Result { if let Some(file) = file { File::create(file) } else { Ok(io::stdout()) }.transpose_ok() } assert!(transpose_ok(None).is_ok()); #[auto_enum(Transpose, Write)] fn transpose_option(file: Option<&Path>) -> Option { if let Some(file) = file { File::create(file).ok() } else { Some(io::stdout()) }.transpose() } assert!(transpose_option(None).is_some()); #[enum_derive(Debug, Display, Error)] enum IoError { Io(io::Error), Io2(io::Error), } #[auto_enum(Transpose, Write, Debug, Display, Error)] fn transpose_result(file: Option<&Path>) -> Result { if let Some(file) = file { File::create(file).map_err(IoError::Io) } else { let out: Result = Ok(io::stdout()); out } .transpose() } assert!(transpose_result(None).is_ok()); #[auto_enum(Transpose, Debug, Display, Error)] fn transpose_err(file: Option<&Path>) -> Result<(), impl Error> { if let Some(_f) = file { Err(IoError::Io2(io::Error::from(io::ErrorKind::NotFound))) } else { Err(io::Error::from(io::ErrorKind::NotFound)) } .transpose_err() } assert!(transpose_err(None).unwrap_err().source().is_some()); #[auto_enum(Debug, Display, Error)] fn try_operator(file: Option<&Path>) -> Result<(), impl Error> { if let Some(_f) = file { Err(IoError::Io2(io::Error::from(io::ErrorKind::NotFound)))?; } else { Err(io::Error::from(io::ErrorKind::NotFound))?; } Ok(()) } assert!(try_operator(None).unwrap_err().source().is_some()); } #[auto_enum] fn if_attr(x: bool) -> impl Iterator { let res = { #[auto_enum(Iterator)] if x { iter::once(0) } else { iter::repeat(1) } }; res } #[auto_enum(Iterator)] fn if_attr_in_if(x: usize) -> impl Iterator { if x == 0 { 1..8 } else if x > 3 { #[nested] if x > 4 { 2..=10 } else { (11..20).map(|x| x - 1) } } else { (0..2).map(|x| x + 1) } } #[auto_enum] fn non_stmt_expr_match1(x: bool) -> Option> { Some( #[auto_enum(Iterator)] match x { true => iter::once(0), _ => iter::repeat(1), }, ) } #[auto_enum] fn non_stmt_expr_match2(x: bool) -> Option> { Some({ #[auto_enum(Iterator)] match x { true => iter::once(0), _ => iter::repeat(1), } }) } #[auto_enum] fn non_stmt_expr_match3(x: bool) { loop { let _ = { #[auto_enum(Iterator)] match x { true => iter::once(0), _ => iter::repeat(1), } }; break; } } #[auto_enum] fn non_stmt_expr_if(x: bool) -> Option> { Some( #[auto_enum(Iterator)] if x { iter::once(0) } else { iter::repeat(1) }, ) } #[test] fn nested() { #[auto_enum(Iterator)] fn match_in_match(x: usize) -> impl Iterator { match x { 0 => 1..8, #[nested] n if n > 3 => match x { 2..=10 => (1..x as i32).map(|x| x - 1), _ => 2..=10, }, _ => (0..2).map(|x| x + 1), } } for (i, x) in [28, 3].iter().enumerate() { assert_eq!(match_in_match(i).sum::(), *x); } #[auto_enum(Iterator)] fn match_in_match_nested(x: usize) -> impl Iterator { match x { 0 => 1..8, #[nested] n if n > 3 => match x { 2..=10 => { #[nested] match n { 4 => (1..x as i32).map(|x| x - 1), _ => (1..x as i32).map(|x| x + 1), } } _ => 2..=10, }, _ => (0..2).map(|x| x + 1), } } #[rustfmt::skip] #[allow(unused_braces, unused_unsafe)] #[auto_enum(Iterator)] fn in_block(x: usize) -> impl Iterator { {{{ unsafe {{{ unsafe { unsafe {{ match x { 0 => 1..8, #[nested] n if n > 3 => {{{ unsafe {{ if x > 10 { (-10..=x as i32).map(|x| x - 4) } else { (1..=4).map(|x| x - 4) } }}}}} _ => (0..2).map(|x| x + 1), } }}}}}}}}} } for (i, x) in [28, 3].iter().enumerate() { assert_eq!(in_block(i).sum::(), *x); } #[auto_enum(Iterator)] fn match_in_if(x: usize) -> impl Iterator { if x == 0 { 1..8 } else if x > 3 { #[nested] match x { 1..=4 => 2..=10, _ => (11..20).map(|x| x - 1), } } else { (0..2).map(|x| x + 1) } } for (i, x) in [28, 3].iter().enumerate() { assert_eq!(match_in_if(i).sum::(), *x); } #[auto_enum(Iterator)] fn if_in_block_if(x: usize) -> impl Iterator { if x == 0 { 1..8 } else if x > 3 { #[nested] { if x > 4 { 2..=10 } else { (11..20).map(|x| x - 1) } } } else { (0..2).map(|x| x + 1) } } for (i, x) in [28, 3].iter().enumerate() { assert_eq!(if_in_block_if(i).sum::(), *x); } #[auto_enum(Iterator)] fn match_in_let_match(x: usize) -> impl Iterator { match x { 0 => 1..8, 3 => { #[nested] let x = match x { 4..=10 => 2..=10, _ => (11..20).map(|x| x - 1), }; x } _ => (0..2).map(|x| x + 1), } } for (i, x) in [28, 3].iter().enumerate() { assert_eq!(match_in_let_match(i).sum::(), *x); } #[auto_enum(Iterator)] fn match_in_let_if(x: usize) -> impl Iterator { match x { 0 => 1..8, 3 => { #[nested] let x = if x > 4 { 2..=10 } else { (11..20).map(|x| x - 1) }; x } _ => (0..2).map(|x| x + 1), } } for (i, x) in [28, 3].iter().enumerate() { assert_eq!(match_in_let_if(i).sum::(), *x); } #[auto_enum(Iterator)] fn match_in_let_if_2(x: usize) -> impl Iterator { match x { 0 => 1..8, 3 => { #[nested] let x = if x > 4 { 2..=10 } else { #[nested] let x = match x { 4..=10 => 2..10, _ => (11..20).map(|x| x - 1), }; x }; x } _ => (0..2).map(|x| x + 1), } } #[auto_enum(Iterator)] fn if_in_let_if(x: usize) -> impl Iterator { if x == 0 { 1..8 } else if x > 3 { #[nested] let x = if x > 4 { 2..=10 } else { (11..20).map(|x| x - 1) }; x } else { (0..2).map(|x| x + 1) } } for (i, x) in [28, 3].iter().enumerate() { assert_eq!(if_in_let_if(i).sum::(), *x); } #[auto_enum(Iterator)] fn if_in_let_if_nested(x: usize) -> impl Iterator { if x == 0 { 1..8 } else if x > 3 { #[nested] let x = if x > 4 { #[nested] let x = if x > 4 { (2..=10).flat_map(|x| 1..x) } else { core::iter::empty() }; x } else { (11..20).map(|x| x - 1) }; x } else { (0..2).map(|x| x + 1) } } #[auto_enum(Iterator)] fn if_in_let_if_nested_nested(x: usize) -> impl Iterator { // 1 enum with 9 variants is generated. if x == 0 { 1..8 } else if x != 1 { #[nested] let x = if x > 5 { #[nested] let x = if x > 10 { #[nested] let x = if x > 11 { (2..=10).flat_map(|x| 1..x) } else { (11..20).map(|x| x - 1) }; x } else { #[nested] let x = if x > 9 { (2..=10).flat_map(|x| 1..x) } else { #[nested] let x = if x > 6 { #[nested] let x = if x > 7 { (2..=10).flat_map(|x| 1..x) } else { (11..20).map(|x| x - 1) }; x } else { (11..20).map(|x| x - 1) }; x }; x }; x } else { (11..20).map(|x| x - 1) }; x } else { (0..2).map(|x| x + 1) } } #[auto_enum(Iterator)] fn if_in_let_if_2(x: usize) -> impl Iterator { if x == 0 { 1..8 } else if x > 3 { #[nested] let y = if x > 4 { 2..=10 } else { (11..20).map(|x| x - 1) }; #[nested] let z = if x < 4 { 2..10 } else { (11..20).map(|x| x - 1) }; if x > 5 { y } else { z } } else { (0..2).map(|x| x + 1) } } #[auto_enum(Iterator)] fn match_in_let_if_nop(x: usize) -> impl Iterator { match x { 0 => 1..8, 3 => { #[nested] let x = if x > 4 { 2..=10 } else { (11..20).map(|x| x - 1) }; #[nested] // no-op let _y = 111..120; x } _ => (0..2).map(|x| x + 1), } } #[auto_enum(Iterator)] fn if_in_let_if_nop(x: usize) -> impl Iterator { if x == 0 { 1..8 } else if x > 3 { #[nested] let x = if x > 4 { 2..=10 } else { (11..20).map(|x| x - 1) }; #[nested] // no-op x } else { (0..2).map(|x| x + 1) } } #[auto_enum(Iterator)] fn match_nop(x: usize) -> impl Iterator { match x { 0 => 1..8, 3 => 2..=10, _ => (0..2).map(|x| x + 1), } } #[auto_enum(Iterator)] fn if_nop(x: usize) -> impl Iterator { if x == 0 { 1..8 } else if x > 3 { 2..=10 } else { (0..2).map(|x| x + 1) } } #[auto_enum(Iterator)] fn no_return(x: usize) -> impl Iterator { match x { 0 => 1..8, #[nested] 3 => panic!(), _ => (0..2).map(|x| x + 1), } } } // nightly #[cfg(feature = "fn_traits")] mod nightly { use auto_enums::auto_enum; const ANS: &[i32] = &[28, 3]; #[test] fn nightly() { // let match for (i, x) in ANS.iter().enumerate() { #[auto_enum(Iterator)] let iter = match i { 0 => 1..8, _ => vec![1, 2, 0].into_iter(), }; assert_eq!(iter.sum::(), *x); } // let if for (i, x) in ANS.iter().enumerate() { #[auto_enum(Iterator)] let iter = if i == 0 { 1..8 } else if i > 3 { 1..=10 } else { vec![1, 2, 0].into_iter() }; assert_eq!(iter.sum::(), *x); } // no return for (i, x) in ANS.iter().enumerate() { #[auto_enum(Iterator)] let iter = match i { 0 => 1..8, #[never] 5..=10 => loop { panic!(); }, _ => vec![1, 2, 0].into_iter(), }; assert_eq!(iter.sum::(), *x); } for (i, x) in ANS.iter().enumerate() { #[auto_enum(Iterator)] let iter = match i { 0 => 1..8, 5..=10 => panic!(), 11..=20 => unreachable!(), 21..=30 => break, 31..=40 => continue, 41..=50 => return, _ => vec![1, 2, 0].into_iter(), }; assert_eq!(iter.sum::(), *x); } for (i, x) in ANS.iter().enumerate() { #[auto_enum(Iterator)] let iter = if i > 3 { #[never] loop { panic!(); } } else if i == 0 { 1..8 } else { vec![1, 2, 0].into_iter() }; assert_eq!(iter.sum::(), *x); } #[allow(clippy::needless_late_init)] fn assign(x: usize) -> impl Iterator + Clone { let a; a = #[auto_enum(Iterator, Clone)] match x { 0 => 2..8, _ if x < 2 => vec![2, 0].into_iter(), _ => 2..=10, }; a } for (i, x) in ANS.iter().enumerate() { assert_eq!(assign(i).sum::(), *x - 1); } /* This can not be supported. It is parsed as follows. expected: ExprAssign { left: ExprPath, right: ExprMatch, .. } found: ExprPath fn assign2(x: usize) -> impl Iterator + Clone { let a; #[auto_enum(Iterator, Clone)] a = match x { 0 => 2..8, _ if x < 2 => vec![2, 0].into_iter(), _ => 2..=10, }; a } */ #[auto_enum(Fn)] fn fn_traits1(option: bool) -> impl Fn(i32) -> i32 { if option { |x| x + 1 } else { |y| y - 1 } } assert_eq!(fn_traits1(true)(1), 2); #[auto_enum(Iterator, Clone)] let _y = match 0 { 0 => 2..8, _ => 2..=10, }; #[auto_enum(Iterator, Clone)] let _x = match 0 { 0 => 2..8, _ => 2..=10, }; } #[test] fn never() { // never attr for (i, x) in ANS.iter().enumerate() { #[auto_enum(Iterator)] let iter = match i { 0 => 1..8, #[never] 5..=10 => loop { panic!(); }, _ => match i { #[never] 5..=10 => loop { panic!(); }, #[never] 11..=20 => loop { panic!(); }, _ => vec![1, 2, 0].into_iter(), }, }; assert_eq!(iter.sum::(), *x); } for (i, x) in ANS.iter().enumerate() { #[rustfmt::skip] #[auto_enum(Iterator)] let iter = match i { 0 => 1..8, #[never] 5..=10 => loop { panic!(); }, 1..=4 => vec![1, 2, 0].into_iter(), _ => { match i { #[never] 5..=10 => loop { panic!(); }, #[never] 11..=20 => loop { panic!(); }, _ => panic!(), } } }; assert_eq!(iter.sum::(), *x); } } #[test] fn marker() { fn marker1(x: usize) -> impl Iterator + Clone { #[auto_enum(Iterator, Clone)] (0..x as i32).map(|x| x + 1).flat_map(|x| { if x > 10 { marker!(0..x) } else { marker!(-100..=0) } }) } for (i, _x) in ANS.iter().enumerate() { let _ = marker1(i).clone().sum::(); } fn marker2(x: usize) -> impl Iterator + Clone { let a; #[auto_enum(Iterator, Clone)] match x { 0 => a = marker!(2..8), _ if x < 2 => a = marker!(vec![2, 0].into_iter()), _ => a = marker!(2..=10), }; a } for (i, x) in ANS.iter().enumerate() { assert_eq!(marker2(i).clone().sum::(), *x - 1); } } #[test] fn non_stmt_expr() { // TODO: workaround rustc bug in the same way as https://github.com/taiki-e/futures-async-stream/pull/94. // use std::iter; // // fn match_(x: bool) -> Option> { // Some( // #[auto_enum(Iterator)] // match x { // true => iter::once(0), // _ => iter::repeat(1), // }, // ) // } // // fn if_(x: bool) -> Option> { // Some( // #[auto_enum(Iterator)] // if x { iter::once(0) } else { iter::repeat(1) }, // ) // } } }