No way to get mutable reference to Vec member without expressing uniqueness over the full Vec
Nobody has claimed this yet.
- Dominant language
- Rust
- Stars
- 119k
- Forks
- 16.1k
- PR merge metrics
- PR metrics pending
Description
I've ran into the following standard library defect. There appears to be no possible sound way to go from a Vec<T> to a &mut T without expressing uniqueness over the full Vec. Vec::as_mut_ptr does not suffice because it takes a &mut self which expresses unique access over the full vec. A function which goes from *mut Vec<T> -> *mut T is necessary, but missing. The same is true for *mut [T] -> *mut T.
Consider the following example, where I have a v: Vec<Vec<u32>> where m.len() == n and m[i].len() == t for all i. I have t threads and I now want to process this array mutably in parallel, transposed. For example suppose I want to do the following in-place cumulative sum:
(0..t).into_par_iter().map(|thread_idx| {
let mut cumsum = 0;
for i in 0..n {
// This obviously doesn't work, but you can't write this soundly with pointers either.
let x: &mut u32 = &mut v[i][thread_idx];
cumsum += *x;
*x = cumsum;
}
})
As far as I can tell, there is no way to write this soundly without introducing (potentially significant) overhead at all. The only way to write this soundly is to first create a temporary array of pointers and to modify the inner loop to use those pointers:
let ptrs: Vec<*mut u32> = v.iter_mut().map(|vi| vi.as_mut_ptr()).collect();
// ...
let x: &mut u32 = unsafe { &mut *ptrs[i].add(thread_idx) };
}
I really think the standard library should offer some kind of way to write this loop soundly without the unnecessary overhead of creating a pointer array. The simplest solution I think is to add functions which go from *mut Vec<T> -> *mut T and *mut [T] -> *mut T without creating an intermediate unique reference to the entire Vec or slice.
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start by reviewing Vec::as_mut_ptr and the raw-pointer conversions proposed for Vec and [T]. Evaluate whether these APIs can provide sound mutable element access without creating a unique reference to the whole collection, using the transposed parallel cumulative-sum example as the acceptance case. Done means a safe, justified standard-library API design or a documented reason the request cannot be supported.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- rust
- Domain
- backend-api-design
- Issue type
- Feature
- Difficulty
- 5/5
- Estimated time
- Over a week
- Activity status
- Stale
- Clarity
- Mostly clear
- Newbie friendliness
- 22/100