1

I'm trying to make a program in Rust where I have a function that returns a trait object reference (&T), where T has std::any::Any as a supertrait (T is defined as trait T: std::any::Any). Since every value that implements T also has to implement std::any::Any, I would expect to be able to do:

fn give_T_ref() -> &'static T {
    ...
}

let y: &std::any::Any = give_T_ref();

But this gives a compiler error, saying expected trait `std::any::Any`, found trait `T`.

Is this a bug/problem in the compiler, or am I missing something? Is there currently any way to work around this?

Here is a minimal runnable example of my problem (link to play.rust-lang.org):

use std::any::Any;

trait T: Any {}

struct Implementor {}

impl T for Implementor {}

fn give_T_ref() -> &'static T {
    &Implementor {}
}

fn main() {
    let y: &Any = give_T_ref();
    //  ^ expected trait `std::any::Any`, found trait `T`
}
trent
  • 25,033
  • 7
  • 51
  • 90
Loovjo
  • 534
  • 8
  • 23

1 Answers1

3

While for now Rust does not natively support upcasting trait objects to a supertrait, usually you can work around it by exposing a trait method to perform the concrete upcast that you care about.

In your case that could consist of an as_any_ref method as follows.

use std::any::Any;

trait T: Any {
    fn as_any_ref(&self) -> &Any;
}

struct Implementor {}

impl T for Implementor {
    fn as_any_ref(&self) -> &Any {
        self
    }
}

fn give_T_ref() -> &'static T {
    &Implementor {}
}

fn main() {
    let y: &Any = give_T_ref().as_any_ref();
}
dtolnay
  • 9,621
  • 5
  • 41
  • 62