What allows a function to implicitly dereference a

2019-02-27 13:52发布

问题:

While reading How can I reborrow a mutable reference without passing it to a function?, the OP had a function like:

fn deref<'a, 'b: 'a, T>(t: &'a mut &'b mut T) -> &'a mut T {
    *t
}

This makes sense to me. However, they also pointed out that the explicit dereference in the body * wasn't required:

fn deref<'a, 'b: 'a, T>(t: &'a mut &'b mut T) -> &'a mut T {
    t
}

This compiles, and I don't know why. I'm familiar with automatic dereferencing, but I was under the impression that only came into play with function arguments, not return values.

回答1:

Reading the relevant docs, it seems that the Deref conversion always happens as many times as it needs to - wherever it needs to. The only really funky additional trick that Deref pulls is that it also works magic on self arguments.

The following snippets both work - and the expressions here are definitely not constrained to be arguments or return values.

// &&&&1 gets dereferenced to &i32 from &&&&i32
let x: &i32 = &&&&1;
let x: (&i32,) = (&&&&1,);

The only gotcha with this sort of thing that remains is that Deref only applies to types of the form &U, so something like &1 can never be coerced to &i32 from i32, even if &&1 can be coerced from &&i32 to &i32.


As a side note, I realize that type ascriptions are a bit special, but it seems Deref doesn't do conversions there. I'm not sure if it is by design or not, or if I'm just misunderstanding something. The following doesn't work.

#![feature(type_ascription)]

// ....

let x = &&1i32: &i32;

Based on this comment (and the very relevant thread from which it originates), it looks like this is just a type ascription issue. It appears that for now, type ascription is implemented without coercions, but almost everyone agrees that that should not be the case (in fact, one of the good use cases of type ascriptions would be to hint to the compiler which coercions to apply).