My motivation: I want to test a lexer I wrote, but I only want to test that it spits out the right token kinds, their byte offsets or slices into the input notwithstanding. So, imagine,
enum Tok<'scx> {
Int(&'scx str),
Id(&'scx str),
..
}
It would be great if I could write down a static array of the enum variants I expect and then compare that with a .collect() of the lexer. Unfortunately, the Discriminant of an enum erases type information, and can’t be constructed statically from a variant name.
Given an enum E, I propose introducing an enum tag!(E) (placeholder syntax), which encompasses all discriminant values of E, constructible either by explicit cast (e as tag!(_)) or by static access: tag!(E)::Variant. Thus, my test looks something like:
#[test]
fn test_lexer() {
let lex = Lexer::new("let x = 0;");
// Intentionally verbose; I imagine you would be able
// do some syntatically-valid form of `use tag!(Tok<'static>)::*;`
// or whatever.
assert_eq!(lex.collect::<Vec<_>>(),
&[tag!(Tok<'static>)::Let,
tag!(Tok<'static>)::Id,
tag!(Tok<'static>)::Eq, ..])
}
FAQ:
- For
K not an enum, tag!(K) has a single unnameable variant.
-
tag!(tag!(E)) should maybe be tag!(E)? Not sure how to feel about idempotence.
discriminant(E::Foo(..)) == discriminant(tag!(E)::Foo)
Thoughts?