You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
vec: add try_* methods and a try_vec! macro to make Vec usable in without infallible allocation methods
As a part of the work for #86942 the `no_global_oom_handling` cfg was added in #84266, however enabling that cfg makes it difficult to use `Vec`: the `vec!` macro is missing and there is no way to insert or push new elements, nor to create a `Vec` from an iterator (without resorting to `unsafe` APIs to manually expand and write to the underlying buffer).
This change adds `try_` equivalent methods for all methods in `Vec` that are disabled by `no_global_oom_handling` as well as a `try_vec!` as the equivalent of `vec!`.
Performance and implementation notes: A goal of this change was to make sure to NOT regress the performance of the existing infallible methods - a naive approach would be to move the actual implementation into the fallible method, then call it from the infallible method and `unwrap()`, but this would add extra compare+branch instructions into the infallible methods. It would also be possible to simply duplicate the code for the fallible version - I did opt for this in a few cases, but where the code was larger and more complex this would lead to a maintenance nightmare. Instead, I moved the implementation into an `*_impl` method that was then specialized based on a new `VecError` trait and returned `Result<_, VecError>`, this trait also provided a pair of methods for raising errors. Never (`!`) was used as the infallible version of this trait (and always panics) and `TryReserveError` as the fallible version (and returns the correct error object). All these `VecError` method were marked with `#[inline]`, so after inlining the compiler could see for the infallible version always returns `Ok()` on success (and panics on error) thus the `?` operator or `unwrap()` call was a no-op, and so the same non-branching instructions as before are generated.
I also added `try_from_iter` and `try_expand` methods for completeness, even though their infallible equivalents are trait implementations.
0 commit comments