Search code examples
rustclosuresunsafe

Can I create an "unsafe closure"?


I have some code that, when simplified, looks like:

fn foo() -> Vec<u8> {
    unsafe {
        unsafe_iterator().map(|n| wrap_element(n)).collect()
    }
}

The iterator returns items that would be invalidated if the underlying data changed. Sadly, I'm unable to rely on the normal Rust mechanism of mut here (I'm doing some... odd things).

To rectify the unsafe-ness, I traverse the iterator all at once and make copies of each item (via wrap_element) and then throw it all into a Vec. This works because nothing else has a chance to come in and modify the underlying data.

The code works as-is now, but since I use this idiom a few times, I wanted to DRY up my code a bit:

fn zap<F>(f: F) -> Vec<u8>
    where F: FnOnce() -> UnsafeIter
{
    f().map(|n| wrap_element(n)).collect()
}

fn foo() -> Vec<u8> {
    zap(|| unsafe { unsafe_iterator() }) // Unsafe block
}

My problem with this solution is that the call to unsafe_iterator is unsafe, and it's the wrap_element / collect that makes it safe again. The way that the code is structured does not convey that at all.

I'd like to somehow mark my closure as being unsafe and then it's zaps responsibility to make it safe again.


Solution

  • It's not possible to create an unsafe closure in the same vein as an unsafe fn, since closures are just anonymous types with implementations of the Fn, FnMut, and/or FnOnce family of traits. Since those traits do not have unsafe methods, it's not possible to create a closure which is unsafe to call.

    You could create a second set of closure traits with unsafe methods, then write implementations for those, but you would lose much of the closure sugar.