Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Assert an enum variant exists #11

Open
nvzqz opened this issue Feb 23, 2019 · 1 comment
Open

Assert an enum variant exists #11

nvzqz opened this issue Feb 23, 2019 · 1 comment

Comments

@nvzqz
Copy link
Owner

nvzqz commented Feb 23, 2019

As per @robinkrahl's request (#2 (comment)), I made an attempt at this but it doesn't necessarily work. The only limited working form is if $v is an ident or $(tt)+ where only assert_variant!(Thing, A); works and neither of the others does. And even then, it still requires the #![feature(type_alias_enum_variants)] attribute for some reason on nightly.

Below is my current (failing) attempt at a solution:

#![feature(underscore_const_names)]
#![feature(type_alias_enum_variants)]

enum Thing {
    A,
    B { x: () },
    C(()),
}

macro_rules! assert_variant {
    ($e:ty, $v:pat) => {
        const _: fn($e) -> () = |e| match e {
            <$e>::$v => {},
            _ => {},
        };
    }
}

assert_variant!(Thing, A);
assert_variant!(Thing, B { .. });
assert_variant!(Thing, C(_));

fn main() {}

Ideally, the best solution would allow for:

assert_variant!(Thing, A);
assert_variant!(Thing, B);
assert_variant!(Thing, C);

assert_variant!(Thing, A, B, C);
@Lej77
Copy link

Lej77 commented Oct 2, 2019

I made an attempt at implementing this:

macro_rules! assert_variant {
    ($e:ty: $($v:ident),+ $(,)?) => {
        const _: fn($e) = |e| {
            type AnEnum = $e;
            $(
                if let AnEnum::$v { .. } = e {}
            )+
        };
    };
}

#[allow(dead_code)]
pub enum Thing {
    A,
    B { x: () },
    C(()),
    AnEnum,
}

fn main() {
    assert_variant!(Thing: A);
    assert_variant!(Thing: B);
    assert_variant!(Thing: C);
    
    assert_variant!(self::Thing: AnEnum, A, B, C);
}

old playground link (used re-exports via use but required $e:path instead of $e:ty in macro) (includes some tests)

playground link (includes some tests)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants