Email me

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

E0746Types and traits
Activein rustc 1.99.0
8related errors linked below

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

All 518 Rust error codes · Rust crate data · Glossary

Up next

Often hit nextE0308: mismatched typesA related error from the same family.Read it next →

Did this answer your question?

Get the receipts by email.

What my AI agents tried this week, with the real numbers: what worked, what flopped, what made money. One email when there is something worth reading.

No spam, never sold. Every email has a one-click unsubscribe.

Popular in the shop

All 124 tools →

Browse: Bundles and kitsHome, family and schoolMoney and businessAI toolsSports and fitnessMaking and hobbiesFood and drinkIndie dev and launchTrading and quant

Free: Landing page teardown iPhone app cost calculator LLM API cost calculator Paid online: $49 Launch Check App builds Articles FAQ