I wonder if there is a way to simplify the following pattern match arms when two or more different enum\'s types have the same data member or same function.
(if not
The working code de-sugars to:
let s = match v4_or_v6 {
IpAddr::V4(ip) => <Ipv4Addr as ToString>::to_string(&ip),
IpAddr::V6(ip) => <Ipv6Addr as ToString>::to_string(&ip),
};
Even though the statements look the same, they are different functions and in each branch it is known statically which to_string
is going to be used. To get this to work in a single match arm, you would have to somehow produce a trait object from the pattern match, so that each ip
has the same type (i.e. &dyn ToString
). Currently there isn't a way to do that and I haven't seen any proposal like it.
It's pretty common to see identical-looking match arms, where the same trait method is called on each, even in the rustc
project. This is just how it is, for now.
If you have an enum
where each variant holds types that implement the same traits, it might be convenient to implement the traits on the enum
and delegate to the inner types. If you don't have a trait but your types have common structure (as in the x
, y
fields in the struct of your updated post), then you can provide an accessor on the enum
:
impl Record {
fn x(&self) -> i32 {
match self {
Record::V4(Point { x, .. }) => *x,
Record::V6(Point { x, .. }) => *x,
}
}
}
While this is basically the same thing, it means you can write it once instead of everywhere that you need to access x
:
let rec = get_record();
let x = get_record().x();
Note that IpAddr
already does this so, in your original code, you could have avoided the match
altogether with:
let s = v4_or_v6.to_string();