-
Couldn't load subscription status.
- Fork 9
Description
#10 got a little too confusing, so I think it's good to separate this sub-issue into its own issue.
Currently, the Alloc trait looks like this:
pub unsafe trait Alloc {
unsafe fn alloc(&mut self, layout: Layout) -> Result<NonNull<u8>, AllocErr>;
unsafe fn dealloc(&mut self, ptr: NonNull<u8>, layout: Layout);
// ...
}I propose that we add an associated type called Err. All methods that currently return Result<_, AllocErr> would return Result<_, Self::Err>.
pub unsafe trait Alloc {
type Err: Debug;
unsafe fn alloc(&mut self, layout: Layout) -> Result<NonNull<u8>, Self::Err>;
unsafe fn dealloc(&mut self, ptr: NonNull<u8>, layout: Layout);
// ...
}Then, the std::alloc module would contain an AbortAlloc (or something named similarly).
#[cold]
fn alloc_abort<E: Debug>(err: E, layout: Layout) -> ! {
eprintln!("Allocator error: {:?} with layout: {:?}", err, layout);
std::process::abort()
}
pub struct AbortAlloc<A: Alloc>(A);
unsafe impl<A: Alloc> Alloc for AbortAlloc<A> {
type Err = !;
unsafe fn alloc(&mut self, layout: Layout) -> Result<NonNull<u8>, !> {
self.0.alloc(layout).map_err(|e| alloc_abort(e, layout))
}
unsafe fn dealloc(&mut self, ptr: NonNull<u8>, layout: Layout) {
self.0.dealloc(ptr, layout)
}
// The rest of the methods would simply fall through in the same way.
// ...
}
impl<A: Alloc> From<A> for AbortAlloc<A> {
fn from(allocator: A) -> Self {
AbortAlloc(allocator)
}
}Then, types like Vec could have their normal methods that interact with the allocator only be implemented when the Alloc::Err type is !. Otherwise, the try_* methods would be available which would propagate the error upwards.
Additionally, the new_in/etc methods would take an Into<A> parameter so that the user experience of creating an infallible collection wouldn't require the user to explicitly wrap their allocator in an AbortAlloc.