Max Heiber
Max Heiber

Reputation: 15502

What does pattern-matching a non-reference against a reference do in Rust?

What happens when pattern-matching against a reference with a pattern that doesn't include a reference?

Here's an example using a struct pattern:

fn main() {
    struct S(u32);
    let S(x) = &S(2);
    // type of x is `&u32`
}

The behavior is surprising to me because the pattern on the left does not seem to match the data on the right, unlike let &S(x) = &S(2) where the &s line up.

It looks like what is happening is that when the RHS is a struct reference and the lhs is a struct pattern with field patterns, the type of the variable in the field pattern is &F where F is the type of the field.

What I am looking for is:

I couldn't find anything about this in the Rust Reference or the Rust Book, but I may have missed it.

Upvotes: 7

Views: 994

Answers (1)

user4815162342
user4815162342

Reputation: 154886

The behavior you encountered was introduced with "match ergonomics" in Rust 1.26 and is described in its own RFC. In short, when matching references against non-reference patterns, the binding mode is switched to use ref binding by default.

In your case, let S(x) = &S(2) desugars to let &S(ref x) = &S(2). The "legacy" status of ref is shortly discussed in the Rust book.

an explanation of what the behavior is that is general enough to explain what happens with tuples and enums in addition to structs. For example, in let (x,) = &(2,); the type of x is i32.

This is incorrect - if you ask Rust for the type of x, it will tell you it is &i32, as one would expect:

let (x,) = &(2i32,);
let () = x;
//       ^^   - this expression has type `&i32`

In other words, the same binding-mode rules that apply to structs and enums also apply to tuples.

Upvotes: 10

Related Questions