Conditionally-Revoked Borrows
Nobody has claimed this yet.
- Dominant language
- Markdown
- Stars
- 6.6k
- Forks
- 1.7k
- Avg merge
- 16h 14m
- Merged PRs (30d)
- 1
Description
Rust's borrow checker, even with the SEME extension doesn't support the straight function with this signature:
pub fn cond_revoked_borrow
<'a, A, B,
F: for<'s> FnOnce(&'s mut A) -> &'s B,
G: for<'s> FnOnce(&'s B) -> bool>
(a: &'a mut A, op: F, cond: G)
-> Result<&'a B, &'a mut A> {
{
let b = op(a);
if cond(b) {
return Ok(b)
}
}
return Err(a)
}
A realistic specialization:
{
let buf = cursor.next();
if is_valid(buf) {
return Ok(buf)
}
}
return Err(cursor)
In the standard erased-lifetime semantics, this function is safe, and you replace either of the returns with an infinite loop, it does: if the condition holds and b is returned, it is fine as a is borrowed for the entirity of 'a, and if it isn't, the scope of the borrow by op is limited to the block, and the Err return is fine.
However, if lifetimes aren't erased, then we encounter a problem - when we execute op, we must select a region parameter. Because cond could return false, the region may have to be at least 'a, but then if cond actually returns true, we need to "revoke" the region.
Should this pattern be legal? Should optimizations be allowed to assume it doesn't happen?
This isn't a totally non-conservative extension, because you can have this:
pub fn cond_revoked_borrow_acausal
<'a, A, B,
F: for<'s> FnOnce(&'s mut A) -> &'s B,
G: for<'s> FnOnce(&'s B) -> bool>
(a: &'a mut A, op: F, cond: G)
-> Result<&'a B, &'a mut A> {
if fortune_teller::cond_will_return_true() {
{
let b = op(a);
if cond(b) {
return Ok(b)
}
}
panic!("the fortune teller lied");
} else {
{
let b = op(a);
if cond(b) {
panic!("the fortune teller lied");
}
}
return Err(a)
}
}
Which compiles, is consistent with the previous version up to panics (and I could've put a loop {} to make it consistent up to divergence), and works if you have a suitable implementation of fortune_teller, but this could create problems in the style of out-of-thin-air values.
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 contains no file or test entry point; begin by analyzing the two Rust examples and the SEME versus erased-lifetime distinction described here. The work is complete when the project decides whether conditionally revoked borrows are legal and whether optimizations may assume they do not occur, with the decision recorded in the RFC process.
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
- 20/100