I'm trying to create a function that returns an instance of the Shader
trait. Here is my drastically simplified code:
trait Shader {}
struct MyShader;
impl Shader for MyShader {}
struct GraphicsContext;
impl GraphicsContext {
fn create_shader(&self) -> Shader {
let shader = MyShader;
shader
}
}
fn main() {}
However I receive the following error:
error[E0277]: the trait bound `Shader + 'static: std::marker::Sized` is not satisfied
--> src/main.rs:10:32
|
10 | fn create_shader(&self) -> Shader {
| ^^^^^^ `Shader + 'static` does not have a constant size known at compile-time
|
= help: the trait `std::marker::Sized` is not implemented for `Shader + 'static`
= note: the return type of a function must have a statically known size
This makes sense as the compiler doesn't know the size of the trait, but nowhere can I find the recommended way of fixing this.
Passing back a reference with &
wouldn't work as far as I know because the reference would outlive the lifetime of its creator.
Perhaps I need to use Box<T>
?
I think you can use generics and static dispatch (I have no idea if those are the right terms, I just saw someone else use them) to create something like this.
This isn't exactly "returning as a trait", but it is letting functions use traits generically. The syntax is a little obscure, in my opinion, so it's easy to miss.
I asked Using generic iterators instead of specific list types about returning the
Iterator
trait. It gets ugly.In the playground:
Rust 1.26 and up
impl Trait
now exists:It does have limitations, such as not being able to be used in a trait method and it cannot be used when the concrete return type is conditional. In those cases, you need to use the trait object answer below.
Rust 1.0 and up
You need to return a trait object of some kind, such as
&T
orBox<T>
, and you're right that&T
is impossible in this instance:See also:
I think this is what you were searching for; a simple factory implemented in Rust: