14

Consider following code

fn main() {
    let s = (&&0,);
    let (x,) = s; // &&i32
    let (&y,) = s; // &i32
    let (&&z,) = s; // i32

    let t = &(&0,);
    let (x,) = t; // &&i32
    let (&y,) = t; // i32

    let u = &&(0,);
    let (x,) = u; // &i32
    let (&y,) = u; // mismatched types expected type `{integer}` found reference `&_`
}

Could someone explain, why & pattern behaves differently in every case? I suppose it is tied somehow to match ergonomics, maybe some coercions come into play? But I can't wrap my head around it.

John Kugelman
  • 349,597
  • 67
  • 533
  • 578
ZeroXbot
  • 163
  • 1
  • 5

1 Answers1

10

You are correct, this is due to match ergonomics. The first case should hopefully be self explanatory, but the second and third cases can be a bit counter-intuitive.

In the second case:

  • (x,) is a non-reference pattern (see the second example in the RFC). The t tuple reference is dereferenced, and x is bound as a ref as it also is a non-reference pattern. Note that t.0 was a reference to begin with, thus resulting in x being a double reference.

  • (&y,) is also a non-reference pattern. The t tuple is dereferenced again to a (&i32,). However, &y is a reference pattern being matched to a &i32 reference. Hence y is bound with move mode and is an i32.

In the third case:

  • Using the same reasoning as the second case, u is dereferenced via Deref coercion to an (i32,), and x, a non-reference pattern, is bound in ref mode. Hence x is an &i32.

  • Again with the same reasoning as the second case, u is dereferenced to an (i32,). The &y reference pattern is then matched to an i32, a non-reference, which causes an error.

EvilTak
  • 7,091
  • 27
  • 36
  • Great explanation, thanks. Out of curiosity, is it possible then to write a pattern for the last scenario such that we bind `i32` type? – ZeroXbot Mar 04 '22 at 09:37
  • 1
    @ZeroXbot You should be able to explicitly dereference the tuple with a reference pattern to avoid match ergonomics kicking in: `let &(z,) = u;` – EvilTak Mar 04 '22 at 21:35