Sharing a struct with trait objects as properties across threads

I find the error message pretty straightforward:

  • the trait std::marker::Send is not implemented for Expr + 'static
  • required because of the requirements on the impl of std::marker::Send for std::sync::Arc<Expr + 'static>
  • required because it appears within the type Container
  • required because of the requirements on the impl of std::marker::Send for std::sync::Arc<Container>
  • required because it appears within the type [closure@src/main.rs:64:33: 67:6 container1:std::sync::Arc<Container>]
  • required by std::thread::spawn

You are trying to move your Arc<Container> to another thread, but it contains an Arc<Expr + 'static>, which cannot be guaranteed to be safely sent (Send) or shared (Sync) across threads.

Either add Send and Sync as supertraits to Expr:

pub trait Expr: Send + Sync { /* ... */ }

Or add them as trait bounds to your trait objects:

pub struct AddExpr {
    expr1: Box<Expr + Send + Sync>,
    expr2: Box<Expr + Send + Sync>,
}

impl AddExpr {
    pub fn new(expr1: Box<Expr + Send + Sync>, expr2: Box<Expr + Send + Sync>) -> Self {
        Self { expr1, expr2 }
    }
}

struct Container {
    x: i32,
    cached_expr: Arc<Expr + Send + Sync>,
}

See also:

Leave a Comment