There was a short thread about #[no_panic]
attribute in 2015.
I’ve recently written some amount of unsafe
code, and I found it’s hard to make sure code is panic-safe. Code calls some functions and perform potentially-panicing operations like vec[i]
while manually allocating and releasing memory.
Unsafe code could easily corrupt memory or leak on panic.
Consider an artificial example:
struct MySmallVec<T> {
ptr: *mut T,
len: u8,
cap: u8,
}
impl<T> MySmallVec<T> {
unsafe fn update_as_vec<R, F>(&mut self, f: F) -> R
where F : FnOnce(&mut Vec<T>) -> R
{
unsafe {
let mut v = Vec::from_raw_parts(self.ptr, self.len as usize, self.cap as usize);
f(&mut v);
assert!(v.capacity() <= u8::MAX);
self.ptr = v.as_mut_ptr();
self.len = v.len() as u8;
self.cap = v.capacity() as u8;
mem::forget(v);
}
}
}
There are hidden problems with this code: if it panics in f()
or f
reserves too much memory, destructor of Vec
is called and and MySmallVec
object becomes invalid.
But caller can catch_unwind
and continue working with corrupted memory.
C++ has noexcept
function attribute, and Rust could have similar #[no_panic]
attribute:
#[no_panic]
unsafe fn update_as_vec<R, F>(&mut self, f: F) -> R { ... }
The program will terminate if code is paniced inside that function. And it is much safer than working with corrupted memory.
Bug in that function can be fixed. However, if function is not intended to panic, author could simply add #[no_panic]
attribute and sleep better instead of thinking about panic-safety.
Can we have #[no_panic]
please?