rust-lang / rust-lang/rfcs

Modify `Arc` and `Rc` so the allocator is moved into the inner allocation

Open
#3,540 4 comments 12 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

T-libs
Dominant language
Markdown
Stars
6.6k
Forks
1.7k
Avg merge
16h 14m
Merged PRs (30d)
1

Description

Basically, at the moment Arc<T, A> and its Weak<T, A> uses:

pub struct Arc<T: ?Sized, A: Allocator = Global> {
    ptr: NonNull<ArcInner<T>>,
    phantom: PhantomData<ArcInner<T>>,
    alloc: A,
}

pub struct Weak<T: ?Sized, A: Allocator = Global> {
    ptr: NonNull<ArcInner<T>>,
    alloc: A,
}

struct ArcInner<T: ?Sized> {
    strong: atomic::AtomicUsize,
    weak: atomic::AtomicUsize,
    data: T,
}

(Something similar happens in Rc and its Weak, so this whole issue could also be applied to them.)

My idea is to move alloc from Arc and Weak to InnerArc:

pub struct Arc<T: ?Sized, A: Allocator = Global> {
    ptr: NonNull<ArcInner<T, A>>,
    phantom: PhantomData<ArcInner<T, A>>,
}

pub struct Weak<T: ?Sized, A: Allocator = Global> {
    ptr: NonNull<ArcInner<T>>,
}

struct ArcInner<T: ?Sized, A> {
    strong: atomic::AtomicUsize,
    weak: atomic::AtomicUsize,
    alloc: A,
    data: T,
}

This would produce 2 benefits:

  1. The size of Arc is guaranteed to be the size of a single pointer, which is cool. Also, being more realistic, it means that if you have a non-zero-sized allocator, you don't have to pay the cost of its size on each clone of the instance, instead the allocator is stored in the inner pointer. That means that multiple copies of the same instance won't require multiple copies of the allocator, saving memory unlike the current approach,
  2. Doing this also means that A doesn't require implementing Clone if you want to clone the Arc, since it's stored in the shared pointer. This would relax the current Arc cloning implementation, no longer requiring A: Allocator + Clone but only A: Allocator. It would probably relax the same constrain in make_mut, unwrap_or_clone, downcast, downcast_unchecked, From<Vec<T, A>> for Arc<[T], A> and TryFrom<Arc<[T], A>> for Arc<[T; N], A>.

Contributor guide

No contributing guide indexed for this repository

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

No files or tests are named. Start by examining the current Arc, Weak, Rc, and Weak representations and the listed allocator-related APIs, then evaluate the proposed shared inner allocation and relaxed Clone bounds for both types. Done requires resolving the design for Arc and Rc, including its API and compatibility implications.

Written by the indexing model from the issue text.

Assessment

Tech stack
rust
Domain
backend-api-design
Issue type
Feature
Difficulty
5/5
Estimated time
Over a week
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
25/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.