lotsoftools

Understanding Rust Error E0009: Binding by-move and by-ref

Rust Error E0009 Explained

Rust error E0009 occurs when a pattern binding attempts to mix by-move and by-ref bindings in the same pattern. Since values that do not implement the Copy trait cannot be bound both by-move and by-ref, this error will occur.

Example: Triggering E0009 in Rust

#![allow(unused)]
#![feature(move_ref_pattern)]

fn main() {
struct X { x: (), }

let x = Some((X { x: () }, X { x: () }));
match x {
    Some((y, ref z)) => {}, // error: cannot bind by-move and by-ref in the
                            //        same pattern
    None => panic!()
}
}

In this example, struct X does not implement the Copy trait, and the match expression tries to bind both by-move (y) and by-ref (ref z). This results in error E0009.

Solution 1: Consistent binding

One solution is to bind the pattern's values the same way, either by-ref or by-move.

By-ref example:

#![allow(unused)]
fn main() {
struct X { x: (), }

let x = Some((X { x: () }, X { x: () }));
match x {
    Some((ref y, ref z)) => {},
    None => panic!()
}
}

By-move example:

#![allow(unused)]
fn main() {
struct X { x: (), }

let x = Some((X { x: () }, X { x: () }));
match x {
    Some((y, z)) => {},
    None => panic!()
}
}

Solution 2: Implement the Copy trait

Another solution is implementing the Copy trait for the X structure. Note that the first solution is usually preferred.

#![allow(unused)]
fn main() {
#[derive(Clone, Copy)]
struct X { x: (), }

let x = Some((X { x: () }, X { x: () }));
match x {
    Some((y, ref z)) => {},
    None => panic!()
}
}