What I want is
enum Animal { Rabbit, Lizard }
fn do_rabbit(r: Animal::Rabbit) {}
fn do_lizard(l: Animal::Lizard) {}
Currently if you want to do such a thing, you have to use the following pattern
struct Rabbit;
struct Lizard;
enum Animal { Rabbit(Rabbit), Lizard(Lizard) }
fn do_rabbit(r: Rabbit) {}
fn do_lizard(l: Lizard) {}
In many cases where the latter pattern is needed,
creating an encapsulating enum (like Animal
) is just extra noise
that is better alleviated by an animal
namespace (mod
) or a trait.
It would be nice if variants could be referred to as types directly, but the project has previously mentioned that this kind of thing is "unbounded work", and my guy instinct is that implementation of this would be orthogonal to much of what is in rustc.
Sometimes i need to do something like
struct Input {
/* a bunch of fields */
}
struct SanitizedInput {
input: Input,
sanitized_brand: std::marker::PhantomData<SanitizedBrand>,
}
Which is... fine, because i can get around having to have an extra property access
for each instance of SanitizedInput
if i make Input
's fields visible on a trait
and implement that for SanitizedInput
, but obviously this is a lot of work for
something i don't want to be doing. Ideally SanitizedInput
could just be an opaque
header over an Input
.
So it would be nice if i could define SanitizedInput
as a composite type:
struct SanitizedInput: Input {
sanitized_brand: std::marker::PhantomData<SanitizedBrand>,
}
Sometimes I want to guard on an enum variant, and handle all other variants in a separate branch with knowledge that only those variants are applicable. For example consider the code
let conf = send(big_ol_response);
if let Some(Status::Ok) = conf {
return;
}
let response = recompute_super_expensive_response();
/* do some other stuff */
match conf {
Status::RateLimited => send_with_rl(response),
Status::Redirect => send_with_proxy(response),
Status::Ok => unreachable!(),
}
(okay yes i know this is contrived and doesn't make sense.. but it's ok)
That unreachable
branch is... suboptimal.
And yes, you could factor everything out into a separate method
and then have a match block where every variant takes at most one line.
But vertical<->horizontal shifting is unpleasant,
and I would like to keep vertical as much as possible.
Furthermore, a typechecker can definitely tell that Status::Ok
is never
possible inside the match block of the example above.