In the current implementation, this may fail in two cases:
n is zero
capacity overflow for n * size_of::<T>()
For the first we have two cases (as in the documentation, the implementer can choose between these):
The allocation returns Ok on zeroed n => dealloc_array should also return Ok.
The allocation returns Err on zeroed n => there is no pointer that can be passed to dealloc_array.
The second is ensured by the following safety constraint:
the layout of [T; n] must fit that block of memory.
This means, that we must call dealloc_array with the same n as in the allocation. If an array with n elements could be allocated, n is valid for T. Otherwise, the allocation would have failed.
Even if usable_size returns a higher value than n * size_of::<T>(), this is still valid. Otherwise the implementation violates this trait constraint:
The block's size must fall in the range [use_min, use_max], where:
[...]
use_max is the capacity that was (or would have been) returned when (if) the block was allocated via a call to alloc_excess or realloc_excess.
This only holds, as the trait requires an unsafe impl and the implementor must ensure those conditions:
A note regarding zero-sized types and zero-sized layouts: many methods in the Alloc trait state that allocation requests must be non-zero size, or else undefined behavior can result.
However, some higher-level allocation methods (alloc_one, alloc_array) are well-defined on zero-sized types and can optionally support them: it is left up to the implementor whether to return Err, or to return Ok with some pointer.
If an Alloc implementation chooses to return Ok in this case (i.e. the pointer denotes a zero-sized inaccessible block) then that returned pointer must be considered "currently allocated". On such an allocator, all methods that take currently-allocated pointers as inputs must accept these zero-sized pointers, without causing undefined behavior.
In other words, if a zero-sized pointer can flow out of an allocator, then that allocator must likewise accept that pointer flowing back into its deallocation and reallocation methods.
In the current implementation, this may fail in two cases:
n
is zeron * size_of::<T>()
For the first we have two cases (as in the documentation, the implementer can choose between these):
Ok
on zeroedn
=>dealloc_array
should also returnOk
.Err
on zeroedn
=> there is no pointer that can be passed todealloc_array
.The second is ensured by the following safety constraint:
This means, that we must call
dealloc_array
with the samen
as in the allocation. If an array withn
elements could be allocated,n
is valid forT
. Otherwise, the allocation would have failed.Even if
usable_size
returns a higher value thann * size_of::<T>()
, this is still valid. Otherwise the implementation violates this trait constraint:This only holds, as the trait requires an
unsafe impl
and the implementor must ensure those conditions: