Why does this deref coercion fail when the expression is wrapped in a block?

Viewed 196

String implements Deref<Target = str>, which means that the following code compiles:

fn save(who: &str) {
    println!("I'll save you, {}!", who);
}

save(&String::from("Madoka"));

If I create a custom type that also implements Deref<Target = str>, then that works too:

struct Madoka;

impl Deref for Madoka {
    type Target = str;
    fn deref(&self) -> &Self::Target {
        "Madoka"
    }
}

save(&Madoka);

Now, let's try coercing to another type -- say, u32. It seems to work as well:

fn reset(how: &u32) {
    println!("Reset {} times", how);
}

struct Homura;

impl Deref for Homura {
    type Target = u32;
    fn deref(&self) -> &Self::Target {
        &42
    }
}

reset(&Homura);

But when I wrap the expression in a block, it no longer compiles:

reset(&{ Homura });
error[E0308]: mismatched types
  --> src/main.rs:17:14
   |
17 |     reset(&{ Homura });
   |              ^^^^^^ expected u32, found struct `main::Homura`
   |
   = note: expected type `u32`
              found type `main::Homura`

The weird thing is that the equivalent expression with &str compiles just fine:

save(&{ Madoka });  // OK

Why does the first expression fail to compile, but the second succeed?

Playground

0 Answers
Related