Rust errors / Types and traits
Rust compiler error · checked with rustc 1.99.0
Rust error E0746: return type cannot have an unboxed trait object
What it meansA function returns dyn Trait directly. Its size is unknown, so return impl Trait (one concrete type) or Box<dyn Trait> (any type).
What rustc prints
error[E0746]: return type cannot be a trait object without pointer indirection --> main.rs:11:13 | 11 | fn foo() -> dyn T { // error! | ^^^^^ doesn't have a size known at compile-time | help: consider returning an `impl Trait` instead of a `dyn Trait` | 11 - fn foo() -> dyn T { // error! 11 + fn foo() -> impl T { // error! | help: alternatively, box the return type, and wrap all of the returned values in `Box::new` | 11 ~ fn foo() -> Box<dyn T> { // error! 12 ~ Box::new(S(42)) |
Real output of rustc 1.99.0 compiling the official example below (2021 edition). Your names and line numbers will differ; the first line is the part to match.
Why it happens
fn make() -> dyn Fn()or-> dyn Iterator<Item = u32>.
How to fix it
1. Return impl Trait
When every path returns the same concrete type.
fn evens() -> impl Iterator<Item = u32> {
(0..).step_by(2)
}2. Return Box<dyn Trait>
When different paths return different types.
fn shape(round: bool) -> Box<dyn Shape> {
if round { Box::new(Circle) } else { Box::new(Square) }
}Other wordings of this error
return type cannot have an unboxed trait object, return type cannot be a trait object without pointer indirection, doesn't have a size known at compile-time
The compiler team's explanation
An unboxed trait object was used as a return value.
Erroneous code example:
trait T {
fn bar(&self);
}
struct S(usize);
impl T for S {
fn bar(&self) {}
}
// Having the trait `T` as return type is invalid because
// unboxed trait objects do not have a statically known size:
fn foo() -> dyn T { // error!
S(42)
}
Return types cannot be dyn Traits as they must be Sized.
To avoid the error there are a couple of options.
If there is a single type involved, you can use impl Trait:
// The compiler will select `S(usize)` as the materialized return type of this
// function, but callers will only know that the return type implements `T`.
fn foo() -> impl T { // ok!
S(42)
}
If there are multiple types involved, the only way you care to interact with them is through the trait's interface, and having to rely on dynamic dispatch is acceptable, then you can use trait objects with Box, or other container types like Rc or Arc:
struct O(&'static str);
impl T for O {
fn bar(&self) {}
}
// This now returns a "trait object" and callers are only be able to access
// associated items from `T`.
fn foo(x: bool) -> Box<dyn T> { // ok!
if x {
Box::new(S(42))
} else {
Box::new(O("val"))
}
}
Finally, if you wish to still be able to access the original type, you can create a new enum with a variant for each type:
enum E {
S(S),
O(O),
}
// The caller can access the original types directly, but it needs to match on
// the returned `enum E`.
fn foo(x: bool) -> E {
if x {
E::S(S(42))
} else {
E::O(O("val"))
}
}
You can even implement the trait on the returned enum so the callers *don't* have to match on the returned value to invoke the associated items:
impl T for E {
fn bar(&self) {
match self {
E::S(s) => s.bar(),
E::O(o) => o.bar(),
}
}
}
If you decide to use trait objects, be aware that these rely on dynamic dispatch, which has performance implications, as the compiler needs to emit code that will figure out which method to call *at runtime* instead of during compilation. Using trait objects we are trading flexibility for performance.
From rustc --explain E0746 (1.99.0), part of the Rust project, MIT or Apache-2.0. Official page.
Related errors
- E0308mismatched types
- E0277the trait bound is not satisfied
- E0599no method named X found in the current scope
- E0433failed to resolve
- E0741`A` must implement `ConstParamTy` to be used as the type of a const generic parameter
- E0743C-variadic type `...` may not be nested inside another type
- E0749negative impls cannot have any items
- E0750negative impls cannot be default impls
Up next
Often hit nextE0308: mismatched typesA related error from the same family.Read it next →Did this answer your question?