The case for fallible shrinking in Vec

Currently, the shrink_to and shrink_to_fit functions on Vec invoke the handle_alloc_error function which either panics or aborts the program. This is also the reason the functions are compiled out on builds which do not allow invoking the oom-handler, see the function definition of shrink_to in std, making it impossible to reduce the size of a vectors allocation safely.

#[cfg(not(no_global_oom_handling))]
#[stable(feature = "shrink_to", since = "1.56.0")]
pub fn shrink_to(&mut self, min_capacity: usize)

This can be solved with two different approaches.

Silent Failure

Currently the documentation for neither shrink_to nor shrink_to_fit make no guarantees that the allocation will actually be shrunk.

Vec::shrink_to The capacity will remain at least as large as both the length and the supplied value.

The current allocator api proclaims for the shrink function that

Alllocator::shrink If this method returns Err, then ownership of the memory block has not been transferred to this allocator, and the contents of the memory block are unaltered.

Therefore, shrinking could ignore the allocation error returned and proceed as if nothing happened.

try_shrink_*

This would be my preferred solution to the problem which would be to introduce a mirror of the try_reserve_* APIs but for shrinking, so the methods try_shrink_to and try_shrink_to_fit. This would also makes it clearer to the caller what the current allocation behaviour was.

Although, I am interested in if I am missing something, as I couldn't find any prior discussion about this.

3 Likes

What are you going to do with the result? Successful shrinking is also allowed to not change the capacity (say, because the allocator only hands out memory in 16-byte chunks and you are trying to shrink a 40-byte vector).

EDIT: withdrawn, kind of. I forgot that the current Allocator API only ever returns a pointer on success, meaning that if shrinking “succeeds”, the caller has to assume it’s exactly the capacity that was requested. I say “kind of” because I think being able to tell the caller what’s actually available would be an improvement to the API, and I know that’s been discussed elsewhere.

The into_boxed_slice method requires a successful shrinking to soundly return, and I imagine there's other unsafe code in the ecosystem that relies on a successful shrink_to_fit in an analogous fashion.

1 Like

That rules out solution 1 to the problem then, do you think there is an argument against the try_shrink_* functions?

1 Like

Seems reasonable to me.

1 Like

You could file an ACP to get it considered for inclusion in the standard library.

3 Likes