Does `try_reserve` guarantees that the content is preserved on allocation failure?

I'm writing a library that calls String::try_reserve internally, and I wonder whether the content of the string is preserved on failure or not.

I read the API docs of String::try_reserve and Vec::try_reserve, and even RFC 2116. No documents explicitly guarantees that the data in the containers (especially Vec and String is important for me) are preserved on allocation failure.
RFC 2116 mentions about data loss as "additional background", but it is just a background.

Does String::try_reserve guarantees to preserve its content even when it fails, or does it dive into "safe, valid, but unspecified data" state?

2 Likes

Almost certainly nothing happens to the current content if the new allocation fails, because nothing can happen before there’s a new allocation to which to move the data. So explicitly specifying this was probably overlooked as being "too obvious" from an implementer’s viewpoint – but I agree that it (and such exception safety invariants in general) should definitely be documented in detail! Any &mut-taking function that returns a Result should document what state the argument/receiver is left in, whether the result is a success or a failure.

3 Likes

It should probably be documented better, but all of the try_reserve[_exact]() functions have the semantics of Allocator::grow() in practice (emphasis mine):

If this returns Ok, then ownership of the memory block referenced by ptr has been transferred to this allocator. The memory may or may not have been freed, and should be considered unusable unless it was transferred back to the caller again via the return value of this method.

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.

3 Likes

Reported to rust-lang/rust.