closures are not required to outlive generic arguments mentioned in their body
Nobody has claimed this yet.
- Dominant language
- Rust
- Stars
- 119k
- Forks
- 16.1k
- PR merge metrics
- PR metrics pending
Description
mod side_table {
use std::sync::atomic::{AtomicPtr, Ordering};
static STORAGE: AtomicPtr<String> = AtomicPtr::new(std::ptr::null_mut());
pub fn set<'a: 'a>(x: &'a String) {
// TODO: assert that this is the first time we've called `set` to avoid
// overwriting the value.
STORAGE.store((&raw const *x).cast_mut(), Ordering::Release)
}
/// # Safety
///
/// This must only be called after `set` has been called for the lifetime `'a`.
pub unsafe fn get<'a>() -> &'a String {
unsafe { &*STORAGE.load(Ordering::Acquire) }
}
}
fn yikes<'a>(x: &'a String) -> impl FnOnce() + use<> {
side_table::set::<'a>(x);
|| {
// SAFETY: We've put a reference in the storage which is
// valid for the whole lifetime `'a`
let print_me = unsafe { side_table::get::<'a>() };
println!("{print_me}");
}
}
fn main() {
let closure = {
let temp = String::from("temporary");
yikes(&temp)
};
closure();
}
I believe the safety comment in the closure is correct and this should be sound. It explicitly checks that get is called with the lifetime 'a.
This is the even more general version of https://github.com/rust-lang/rust/issues/84366 https://github.com/rust-lang/rust/issues/112905
I discussed closure outives requirements with @BoxyUwU recently and there we considered that longterm, we would like the following rules:
- closures have to outlive all generic parameters mentioned in their signature
- for any lifetime/type parameter referenced in the body of the closure, we check that this generic parameter is outlived by at least one element of the signature
- which implies that the closure can only ever be used while these parameters are still valid
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 reproducing the Rust example from the issue and checking how the compiler handles the closure returned by yikes. Read the linked issues #84366 and #112905, then evaluate the proposed closure outlives rules; done means the compiler no longer accepts the unsound case while enforcing the stated lifetime requirements.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- rust
- Domain
- compilers
- Issue type
- Bug
- Difficulty
- 5/5
- Estimated time
- Over a week
- Activity status
- Quiet
- Clarity
- Mostly clear
- Newbie friendliness
- 35/100