[Solved] Field init shorthand syntax in match on slice of vec

I have the following code:

enum Number {
    I(i32),
    F(f32),
}

#[allow(dead_code)]
struct Foo {i: i32, f: f32}

fn main() {
    use Number::*;
    let vec = vec!(I(42), F(3.14));
    
    let _foo = match vec.as_slice() {
        // this both works:
        [I(i), F(f)] => Foo{i: *i, f: *f},
        [F(f), I(i)] => {
            let (i, f) = (*i, *f);
            Foo{i, f}
        },
        // for code readablity i want to use the
        // field init shorthand syntax directly:
        [I(i), F(f), _] => Foo{i, f},
        _ => Foo{i:23, f:2.72},
    };
}

(Playground)

Errors:

   Compiling playground v0.0.1 (/playground)
error[E0308]: mismatched types
  --> src/main.rs:22:32
   |
22 |         [I(i), F(f), _] => Foo{i, f},
   |                                ^
   |                                |
   |                                expected i32, found &i32
   |                                help: consider dereferencing the borrow: `*i`
   |
   = note: expected type `i32`
              found type `&i32`

[...]

Is there some way to use field init shorthand syntax in this situation?

You are matching on a reference, &[Number], but you didn’t put & in your patterns. This is allowed by match-ergonomics since Rust 1.26, with the effect of implying ref on every variable bound within. This is why your i has the type &i32 as the error reports.

If you write your pattern as &[I(i), F(f), _], then i and f will be copied values instead, which will work to initialize Foo as you desire.

3 Likes

This makes totally sense and everything works now as I want it to!
Thank you very much :slight_smile:

This topic was automatically closed 90 days after the last reply. New replies are no longer allowed.