As the title says.
pub unsafe trait Allocator {
fn allocate(&self, layout: Layout) -> Result<NonNull<[u8]>, AllocError>;
unsafe fn deallocate(&self, ptr: NonNull<u8>, layout: Layout);
}
The two required methods on an Allocator
both take different pointer types, this seems weird to me. Why has that choice been made?
Furthermore, why are u8
and [u8]
chosen at all? Why not just have NonNull<()>
or NonNull<[()]>
for both methods?
My understanding is that choosing [u8]
or u8
is a fine idea because it has the least-strict layout requirements that can actually be allocated (since Layout
requires align
to be non-zero). But, I think requiring a cast every time could be a better design choice.
The allocator might over-allocate, and NonNull<[u8]>
is a fat pointer including length information.
Why u8
rather than ()
? Not sure, but it probably reflects the idea that all memory is a bunch of bytes in the end. Also the fact that pointers to ZSTs are allowed to dangle might have something to do with it.