The original proposal was essentially just that if you have an argument
&T, and pass a type
U: AsRef<T>, the compiler will accept it and insert an as_ref coercion. The justification was that:
- It would let you pass a
T to an
&T argument, but you would lose ownership, in other words ‘both sides get what they want.’
- The APIs that take e.g.
P: AsRef<Path> become cluttered and difficult to understand, but are very popular. Let’s just build that into the language so its not distracting in the API surface.
- AsRef coercions are necessarily cheap (unless doing some pathological side effect) because they have to return a reference (this is unlke
We could also consider the same thing with
&mut T but I’m concerned with how that would essentially create a C++ call-by-reference situation for
let mut x = 0;
let mut y = 1;
//x is now 1 and y is now 0, because swap takes &mut T, &mut T
@shepmaster’s idea actually fits into this in a sort of interesting way: we could define some analog to
AsRef for function types so that essentially
fn(&T): AsRef<fn(T)>. In other words, its not that the coercion happens at the level of the type but still just when passing the argument (so an
fn(&T) is not coercible to
fn(T) in general).
(Its also interesting that this ownership coercion is essentially contravariant for higher order functions, just like subtyping.)
EDIT: I also remember that we probably want to apply any AsRef coercions to binary operators as well, isislovecruft posted an RFC issue which this would be a solution for: https://github.com/rust-lang/rfcs/issues/1936