It looks like Rust does not allow using a reference to an instance of a trait to be used where a reference to an instance of the supertrait was expected:
trait Animal{}
trait Dog: Animal{}
fn convert(dog: &Dog) -> &Animal {
dog // Error: trait upcasting coercion is experimental, see issue #65991 ...
}
But there's a workaround, used often in the Rust-Analyzer codebase. How does the workaround work?
Here's the workaround, which enables us to write a convert that rustc will accept:
trait Animal{}
trait Dog: Animal{
fn upcast(&self) -> &Animal; // added line
}
fn convert(dog: &Dog) -> &Animal {
dog.upcast() // changed line
}
And here's an implementation of upcast:
struct Foo {}
impl Animal for Foo {}
impl Dog for Foo {
fn upcast(&self) -> &Animal {
self
}
}
Comparing the upcast and the original convert: they have the same signature and same implementation (modulo renaming). So it looks like something is allowed for methods that is not allowed for functions. What happened?