You can certainly do it with unsafe
, for example by sending a pointer to the threads:
// thin wrapper over pointer to make it Send/Sync
#[derive(Copy, Clone)]
struct Pointer(*mut u32);
unsafe impl Send for Pointer {}
unsafe impl Sync for Pointer {}
let indices = [1, 4, 7, 8];
let mut arr = [1u32, 2, 3, 4, 5, 6, 7, 8, 9, 10];
let arr_ptr = Pointer(arr.as_mut_ptr());
indices.into_par_iter().for_each(move |x| {
// safety:
// * `indices` must be unique and point inside `arr`
// * `place` must not leak outside the closure
// * no element of `array` that is in `indices` may be accessed by
// some other thread while this is running
let place = unsafe { &mut *{arr_ptr}.0.add(x) };
*place = some_function(x);
});
But I'd reserve that kind of thing to use only as last resort. Once you introduce ad-hoc unsafe
like this in your code base, you never know when you'll make a misstep and make your program vulnerable to random crashes and corruptions.