Search code examples
rustreferencetype-coercion

Rust why does operator applied to a reference coerce, but let with an explicit type does not?


Consider the following code:

fn main() {
    let foo = 1;
    let bar: i32 = -&foo; //ok, -1
    let baz: i32 = &foo;  //error, expected `i32`, found `&{integer}`
    let bad: i32 = !&foo; //ok, -2
}

Playground

Reading through the Rust Reference I found that

Possible coercion sites are:

  • let statements where an explicit type is given.

[...]

  • Arguments for function calls

So let baz: i32 = &foo; should also work since it's a let statement with an explicit type given.

Why does it refuse to be compiled?


Solution

  • Cases 1 and 3 are not coercion but are just how those operators are defined. For instance,

    // https://doc.rust-lang.org/std/primitive.i32.html#impl-Neg-for-%26i32
    impl Neg for &i32
    type Output = <i32 as Neg>::Output  // this is i32
    

    And so -&foo has type i32. It's the same for !&foo. The type annotations on the bar and bad lines are doing nothing.

    Meanwhile, line 2 is not a permitted coercion: nowhere in the list of coercions you linked does it say that &T can be coerced to T; doing so requires copying (dereferencing) or cloning.