1

I have some confusion about Deref coercion. I read that Deref coercion is used implicitly when there is a type mismatch.

consider following code:

fn main() {
    let x = X;
    let r = &x;
    r.show(); // prints referenced
}

trait Tr {
    fn show(&self);
}

struct X;

impl Tr for &X {
    fn show(&self) {
        println!("referenced");
    }
}

the above code prints referenced.

now add new trait implementation on owned type:

fn main() {
    let x = X;
    let r = &x;
    r.show(); // prints owned
}

trait Tr {
    fn show(&self);
}

struct X;

impl Tr for &X {
    fn show(&self) {
        println!("referenced");
    }
}

impl Tr for X {
    fn show(&self) {
        println!("owned");
    }
}

now it prints owned but I am expecting it to print referenced.

since &X implements trait Tr, there is no type mismatch. so it should not be derefed implicitly.

is there some thing wrong in my understanding. I also found no way to get it printing referenced after adding new Tr implementation other than using generics with trait bounds.

Santhosh Kumar Tekuri
  • 3,012
  • 22
  • 22
  • looks like I have look at the show method signature rather than impl line. after some fiddling found that `(&r).show();` prints `referenced` – Santhosh Kumar Tekuri Jan 04 '23 at 07:20
  • @FZs actually, the doc you linked states that the compiler will try `T` first, then `&T` and `&mut T` before going to `*T`, `&*T` and `&mut*T` (see the `Box<[i32;2]>` example), so here it should try `&X` first… – Jmb Jan 04 '23 at 08:05

1 Answers1

1

Keep in mind that Tr::show takes a &self. This means that <&X as Tr>::show: Fn(&&X), whereas <X as Tr>::show: Fn(&X). There is actually no deref coertion involved at all. Basically, by adding a borrow yourself, you are doing what deref coertion would do.

jthulhu
  • 7,223
  • 2
  • 16
  • 33