Make (A)Rc/Weak allocator_api APIs more consistent by zachs18 · Pull Request #119761 · rust-lang/rust (original) (raw)

Make Arc/sync::Weak/Rc/rc::Weak unstable feature(allocator_api) APIs more consistent with other containers (well, Box), and with each other.

  1. fn into_raw_with_allocator for all.
    • Pairs with from_raw_in (which already exists on all 4 types).
    • Name matches Box::into_raw_with_allocator.
    • Associated fns on Rc/Arc, methods on Weaks.
  2. fn allocator for all.
    • For Rc/Arc, the existing associated fns are changed to allow unsized pointees.
    • For Weaks, methods are added.
  3. Remove where A: Clone bound on (stable) Rc::downcast and downcast_unchecked, (unstable) assume_inits, and some (stable) trait impls
    • (Arc::{downcast{,_unchecked}, assume_init} were changed by Fix some Arc allocator leaks #120445)
    • downcast(_unchecked) and assume_init semantically should not require cloning the allocator; they are essentially just ((un)checked) pointer casts.
    • Remove A: Clone bound from From<Vec<T, A>> for Arc<[T], A> (Rc's already didn't have a A: Clone bound) and TryFrom<Arc<[T], A>> for Arc<[T; N], A> (done by Fix some Arc allocator leaks #120445) (see below for Rc)
  4. Make TryFrom<Rc<[T]>> for Rc<[T; N]> allocator-aware.

This is adding 61 new unstable functions, changing the bounds on 6 3 unstable functions, and changing the (unstable) bounds on 7 5 stable functions, so I think it needs at least a libs-api FCP? If it also needs an ACP I can make one. (If the parts of this PR should be split I can do that too.)

@rustbot label +A-allocators +T-libs-api -T-libs

Future PR

As a follow-on to this PR, I plan to make a PR/ACP later to move into_raw(_parts) from Container<_, A: Allocator> to only Container<_, Global> (where Container = Vec/Box/Rc/rc::Weak/Arc/sync::Weak) so that users of non-Global allocators have to explicitly handle the allocator when using into_raw-like APIs.

The current behaviors of stdlib containers are inconsistent with respect to what happens to the allocator when into_raw is called (which does not return the allocator)

Type into_raw currently callable with behavior of into_raw
Box any allocator allocator is dropped
Vec any allocator allocator is forgotten
Arc/Rc/Weak any allocator allocator is forgotten(Arc) (sync::Weak) (Rc) (rc::Weak)

In my opinion, neither implicitly dropping nor implicitly forgetting the allocator is ideal; dropping it could immediately invalidate the returned pointer, and forgetting it could unintentionally leak memory. My (to-be) proposed solution is to just forbid calling into_raw(_parts) on containers with non-Global allocators, and require calling into_raw_with_allocator(/Vec::into_raw_parts_with_alloc)

Footnotes

  1. Technically 5 new and 1 renamed, since rc::Weak::into_raw_with_allocator is not newly added, as it was modified and renamed from rc::Weak::into_raw_and_alloc.