Par_iter_mut problem

The following code doesn't compile while the same code with iter_mut instead of par_iter_mut compiles. Why do I need to implement the IntoParallelIterator trait, and how can I do that?
Thanks

use rayon::prelude::*;
trait E {fn eval(&self) -> f64;}
struct C<T:E> {
    d : T,
    v : f64}
type P<T> = Vec<C<T>>;
fn eval_test<T:E>(mut p:P<T>) -> P<T>{
    //p.iter_mut().for_each(|v| v.v=v.d.eval());
    p.par_iter_mut().for_each(|v| v.v= v.d.eval());
    return p;
}

The compiler tells you exactly what the problem is: &mut Vec<T> / &mut [T] doesn't implement that trait. If you go look up that impl in the docs, you can see it requires that the element type T be thread-safe (T: Send). So you have to specify that bound on your function.

You can't. You can't implement a foreign (non-crate-local) trait for a foreign (non-crate-local) type.

Thanks for the answer.
I am not yet absolutely comfortable with the use of traits. So

trait E : Send {
    fn eval(&self) -> f64;
}

is a way of solving the problem.
Thanks again.

FYI, The solution that @H2CO3 was suggesting AFAICT would be to put the bound onto the eval_test function, like fn eval_test<T:E+Send> (or alternatively separately as T: Send in a where clause.)

4 Likes

The difference is that trait E: Send means all E types must be thread-safe, whereas putting it on the function means it's only required if you're going to call that function.

Another consideration is that your function is only using the immutable &self, at least in this reduced example, so it could call par_iter() instead. That would shift your requirement to Sync, which could be easier to satisfy.

2 Likes

As far as I understand, when you declare a trait with a supertrait (like trait X: Y), then all where T: X clauses effectively become where T: X + Y automatically.

use rayon::prelude::*;

trait E {
    fn eval(&self) -> f64;
}

struct C<T: E> {
    d: T,
    v: f64,
}

type P<T> = Vec<C<T>>;

fn eval_test<T>(mut p: P<T>) -> P<T>
where
    T: E + Send, // if you had declared `trait E: Send`, then the `+ Send` would be implied here
{
    p.par_iter_mut().for_each(|v| v.v = v.d.eval());
    return p;
}

(Playground)

Interestingly, this only works with Supertraits (or where Self: Y bounds in the trait definition, which are just another syntax for supertraits), and not with any other bounds in the trait definition.

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.