How do I return an instance of a trait from a method?
rust, traits
Solution
Rust 1.26 and up
`impl Trait` now exists:
fn create_shader(&self) -> impl Shader {
let shader = MyShader;
shader
}
It does have limitations, it cannot be used when the concrete return type is dynamic and could not be used in trait functions until Rust 1.75. 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 (keyword `dyn`), such as `&dyn T` or `Box<dyn T>`, and you're right that `&dyn T` is impossible in this instance:
fn create_shader(&self) -> Box<dyn Shader> {
let shader = MyShader;
Box::new(shader)
}
See also:
- What is the correct way to return an Iterator (or any other trait)?
- Conditionally iterate over one of several possible iterators
Problem
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 ``` Newer versions of the compiler have this error: ``` error[E0277]: the size for values of type `(dyn Shader + 'static)` cannot be known at compilation time --> src/main.rs:9:32 | 9 | fn create_shader(&self) -> Shader { | ^^^^^^ doesn't have a size known at compile-time | = help: the trait `std::marker::Sized` is not implemented for `(dyn Shader + 'static)` = note: to learn more, visit <https://doc.rust-lang.org/book/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait> = 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>`?