I'm pretty new to Rust, but the other day I was trying to paralellize my code with Rayon. Here's a simplified version of it (assumes rayon 1.5.0 is in deps):
use rayon::prelude::*;
trait MyTrait {
fn foo(&self) -> i32;
}
struct MyStruct {
number: i32,
}
impl MyTrait for MyStruct {
fn foo(&self) -> i32 {
self.number
}
}
fn new_struct(number: i32) -> Box<dyn MyTrait> {
Box::new(MyStruct { number }) as Box<dyn MyTrait>
}
fn main() {
let vec: Vec<Box<dyn MyTrait>> = vec![new_struct(1), new_struct(2), new_struct(3)];
let result = vec.into_par_iter().map(|item| item.foo()).sum();
assert_eq!(6, result);
}
It fails with the folowing message:
error[E0599]: no method named `par_iter` found for struct `Vec<Box<dyn MyTrait>>` in the current scope
--> src/main.rs:23:22
|
23 | let result = vec.par_iter().map(|item| item.foo()).sum();
| ^^^^^^^^ method not found in `Vec<Box<dyn MyTrait>>`
|
= note: the method `par_iter` exists but the following trait bounds were not satisfied:
`&Vec<Box<dyn MyTrait>>: IntoParallelIterator`
which is required by `Vec<Box<dyn MyTrait>>: rayon::iter::IntoParallelRefIterator`
`&[Box<dyn MyTrait>]: IntoParallelIterator`
which is required by `[Box<dyn MyTrait>]: rayon::iter::IntoParallelRefIterator`
Ultimately after searching Rayon's issues for "trait bounds were not satisfied" and some googling, I found a post on SO called Sending trait objects between threads in Rust.
The fix is to replace all instances of Box<dyn MyTrait>
with Box<dyn MyTrait + Send>
. After that the code seems to work just fine.
It took me way too long to figure that out, so I'm posting it here in case it helps others. The compiler message was a bit unclear, but if I looked at the docs for rayon::iter::ParallelIterator
, then I'd discover sooner that the associated type for the iterator must be type Item: Send
.