Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Can I create an "unsafe closure"?

Tags:

closures

rust

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.

like image 798
Shepmaster Avatar asked Nov 01 '22 12:11

Shepmaster


1 Answers

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.

like image 63
reem Avatar answered Nov 09 '22 06:11

reem