Rust: Matching on a struct variant enum

Created on 20 Mar 2017  路  4Comments  路  Source: rust-lang/rust

I have been playing with rust enums recently, but I found that I can't seem to make them work the way I expect.

I defined struct variants for an enum:

pub enum Entity {
    Character {
        money: f64,
        ....
    },
    ...
}

And I want to match on them. If I match on self, in the module, I get this:

match self {
    Entity::Character(entity) => {
        entity.money = ...

But I get the following error message:

error[E0532]: expected tuple struct/variant, found struct variant types::Entity::Character

What to do? Am I doing this wrong?

PS: I know I can destructure the content of the enum, but I want to use it as if it was defined locally with the correct variant.

Most helpful comment

I suspect that @nicolaction wants something like https://github.com/rust-lang/rfcs/pull/1450 and entity is expected to have such variant type, and money is not a field of Entity, but a field of Entity::Character variant type.

So this issue is an RFC material and kinda duplicate of https://github.com/rust-lang/rfcs/pull/1450, and not a bug, so it should probably be closed.

What to do? Am I doing this wrong?
PS: I know I can destructure the content of the enum, but I want to use it as if it was defined locally with the correct variant.

Destructuring is not a bad variant

match self {
    Entity::Character { money, .. } => { .... }
}

but if you don't want to use it, then you can define a separate new type for characters:

struct Character { money: f64, .... }

enum Entity {
    Character(Character),
    ....
}

match self {
    Entity::Character(ref mut ch) { ch.money = .... }
}

All 4 comments

The syntax you want would be very inconsistent with what Character(entity) means for tuple variants. Besides, this is already possible using @ (regardless of whether it's a tuple variant or struct variant):

match self {
    entity @ Entity::Character { .. } => {
        entity.money = ...

I suspect that @nicolaction wants something like https://github.com/rust-lang/rfcs/pull/1450 and entity is expected to have such variant type, and money is not a field of Entity, but a field of Entity::Character variant type.

So this issue is an RFC material and kinda duplicate of https://github.com/rust-lang/rfcs/pull/1450, and not a bug, so it should probably be closed.

What to do? Am I doing this wrong?
PS: I know I can destructure the content of the enum, but I want to use it as if it was defined locally with the correct variant.

Destructuring is not a bad variant

match self {
    Entity::Character { money, .. } => { .... }
}

but if you don't want to use it, then you can define a separate new type for characters:

struct Character { money: f64, .... }

enum Entity {
    Character(Character),
    ....
}

match self {
    Entity::Character(ref mut ch) { ch.money = .... }
}

Thank you, I didn't know about @ bindings.
I tried to use:

&mut entity @ Entity::Character{..} => {

But the binding seems to occur before the variant selection somehow, so entity is an Entity, not an Entity::Character.

I think I will have to use a dedicated struct for each struct variant.

This is an old issue, but I believe the match expression @nicolaction wanted was:

match self {
    Entity::Character { mut entity } => {
        entity.money = ...
Was this page helpful?
0 / 5 - 0 ratings

Related issues

Mark-Simulacrum picture Mark-Simulacrum  路  681Comments

cramertj picture cramertj  路  512Comments

nikomatsakis picture nikomatsakis  路  259Comments

Leo1003 picture Leo1003  路  898Comments

nikomatsakis picture nikomatsakis  路  331Comments