reference
reference copied to clipboard
Missing precedence when several coercions are possible
~~As transitive coercions are at least partially supported,~~ it currently doesn't seem to be clear which coercion(s) will be performed when there are several possibilities.
Consider the following code:
use std::ops::Deref;
struct A;
struct B;
impl Deref for A {
type Target = B;
fn deref(&self) -> &B {
&B
}
}
trait Trt {
fn name(&self) -> &'static str;
}
impl Trt for A {
fn name(&self) -> &'static str {
"A"
}
}
impl Trt for B {
fn name(&self) -> &'static str {
"B"
}
}
impl dyn Trt {
fn foo(&self) {
println!("dyn {}", self.name());
}
}
fn main() {
let a = A;
<dyn Trt>::foo(&a); // prints `dyn A`
// but how can we deduce from the documentation that this doesn't happen internally?
<dyn Trt>::foo(&a as &B as &dyn Trt);
}
See also this thread on URLO.
Note that this isn't just an issue with transitive coercions; consider this example where two direct coercions are possible.
fn foo(value: &Arc<dyn Any>) {
// Unsized coercion and deref coercion are both possible to go from
// `&Arc<dyn Any>` to `&dyn Any`, but the results differ.
assert!(<dyn Any>::is::<Arc<dyn Any>>( value as &dyn Any ));
assert!(<dyn Any>::is::<i32>( <Arc<dyn Any> as Deref>::deref(value) ));
// There's no documented precedence or other rules that I'm aware of to
// indicate which actually occurs.
if <dyn Any>::is::<Arc<dyn Any>>(value) {
println!("Arc");
}
if <dyn Any>::is::<i32>(value) {
println!("i32");
}
}