Auto_enums - Allow multiple return types by automatically generated enum

auto_enums is a library for to allow multiple return types by automatically generated enum.

This is an implementation by procedural macros of automatically generated anonymous enum like discussed in RFCs#2414.

See the repository for details and generated code.

Example

#[auto_enum]'s basic feature is to wrap the value returned by the if or match expression by an enum that implemented the specified traits.

#[macro_use] extern crate auto_enums;

#[auto_enum(Iterator)] // generats an enum with two variants
fn foo(x: i32) -> impl Iterator<Item = i32> {
    match x {
        0 => 1..10,
        _ => vec![5, 10].into_iter(),
    }
}

You can also use #[auto_enum] for expressions and statements.

use std::{fs, io, path::Path};

#[auto_enum]
fn output_stream(file: Option<&Path>) -> io::Result<impl io::Write> {
    #[auto_enum(io::Write)]
    let writer = match file {
        Some(f) => fs::File::create(f)?,
        None => io::stdout(),
    };

    Ok(writer)
}

Edit

crate renamed from auto_enumerate to auto_enums.

1 Like

Could you show the generate code for the first example?

Code like this will be generated:

#[macro_use] extern crate auto_enumerate;

fn foo(x: i32) -> impl Iterator<Item = i32> {
    enum __Enum1<__T1, __T2> {
        __T1(__T1),
        __T2(__T2),
    }

    impl<__T1, __T2> ::std::iter::Iterator for __Enum1<__T1, __T2>
    where
        __T1: ::std::iter::Iterator,
        __T2: ::std::iter::Iterator<Item = <__T1 as ::std::iter::Iterator>::Item>,
    {
        type Item = <__T1 as ::std::iter::Iterator>::Item;
        #[inline]
        fn next(&mut self) -> ::std::option::Option<Self::Item> {
            match self {
                __Enum1::__T1(x) => x.next(),
                __Enum1::__T2(x) => x.next(),
            }
        }
        #[inline]
        fn size_hint(&self) -> (usize, ::std::option::Option<usize>) {
            match self {
                __Enum1::__T1(x) => x.size_hint(),
                __Enum1::__T2(x) => x.size_hint(),
            }
        }
    }

    match x {
        0 => __Enum1::__T1(1..10),
        _ => __Enum1::__T2(vec![5, 10].into_iter()),
    }
}
1 Like

I like the feature, and since you have to write custom code for each supported trait, it looks like quite a lot of work!

I'm just not very likely to remember the name of the crate should I need it at some point. "Enumerate" isn't really describing what it does. auto_impl_enum or somesuch would be more logical.

1 Like

Thanks!

I renamed this crate to auto_enums.