Finally blocks for safer, faster, and clearer unsafe code
Nobody has claimed this yet.
- Dominant language
- Markdown
- Stars
- 6.6k
- Forks
- 1.7k
- Avg merge
- 16h 14m
- Merged PRs (30d)
- 1
Description
BinaryHeap currently has the following impl of sift_up that relies on the drop flag and LLVM being smart to avoid some swaps while being panic-safe:
fn sift_up(&mut self, start: usize, mut pos: usize) {
unsafe {
let new = replace(&mut self.data[pos], zeroed());
while pos > start {
let parent = (pos - 1) >> 1;
if new <= self.data[parent] { break; }
let x = replace(&mut self.data[parent], zeroed());
ptr::write(&mut self.data[pos], x);
pos = parent;
}
ptr::write(&mut self.data[pos], new);
}
}
This code is quite unclear, and relies on a lot of things going right. However if we had a finally block, we could do the following:
fn sift_up(&mut self, start: usize, mut pos: usize) {
unsafe {
let new = ptr::read(&self.data[pos]);
while pos > start {
let parent = (pos - 1) >> 1;
if new <= self.data[parent] { break; }
ptr::copy_nonoverlapping(&mut self.data[pos], &self.data[parent], 1);
pos = parent;
}
finally {
ptr::write(&mut self.data[pos], new);
}
}
}
Which clearly captures the actual semantics we want. This functionality can be emulated by creating a struct with a drop impl, but it requires "weakly capturing" all the values through *const's. However that is noisy, cumbersome, confusing, and needlessly unsafe. A first class finally block can be verified to correctly run no matter where unwinding occurs (possibly through verifying that nothing it "closes" over is ever conditionally moved out).
I've constructed similar code while working on some trusted_len iterator problems (using the *const weak closing drop impl).
It would be fine with me if finally was considered unsafe, since its value to me is for cleanly failing in transient unsafe states.
I am logging this as only an issue because I don't have the knowledgebase to flesh out the precise rules, and because there's no way this can land for 1.0.
Contributor guide
No contributing guide indexed for this repository
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
The issue provides no repository files, tests, or implementation entry points. Start with the BinaryHeap::sift_up examples and the discussion of panic safety, unwinding, and weakly captured drop implementations. Done would require defining precise finally-block rules and a viable Rust language design, which the issue explicitly leaves unresolved.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- rust
- Domain
- compilers
- Issue type
- Feature
- Difficulty
- 5/5
- Estimated time
- Over a week
- Activity status
- Stale
- Clarity
- Needs clarification
- Newbie friendliness
- 25/100