-
Notifications
You must be signed in to change notification settings - Fork 13k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Publicly expose the allocated representation of Rc and Arc #80029
Conversation
The goal of this change is to provide more flexibility over how an `Arc<T>` is allocated. An example of when this could be useful is when the user does not want to panic on allocation failure and instead return a Result. The changes here provide a way of constructing an `Arc<T>` by first creating an `ArcInner<T>` wrapping that in a `Box<ArcInner<T>>`, and finally creating an `Arc<T>` from the `Box<ArcInner<T>>`. The last step does no allocation of it's own and merely takes control of the `ArcInner<T>` from the allocation within the Box. This does not make any of the fields within the `ArcInner<T>` visible so it is *not* stabilizing the exact layout of the `ArcInner<T>`. The only operations that can be done with `ArcInner<T>` is initializing one from a `T` and subsequently creating an `Arc<T>` from a `Box<ArcInner<T>>`.
`ArcInner` does not seem like the most descriptive name for a type that's now publicly accessible. Rename it to `ArcRepr` since it's the underyling representation of an `Arc`.
The goal of this change is to provide more flexibility over how an `Rc<T>` is allocated. An example of when this could be useful is when the user does not want to panic on allocation failure and instead return a Result. The changes here provide a way of constructing an `Rc<T>` by first creating an `RcBox<T>` wrapping that in a `Box<RcBox<T>>`, and finally creating an `Rc<T>` from the `Box<RcBox<T>>`. The last step does no allocation of it's own and merely takes control of the `RcBox<T>` from the allocation within the Box. This does not make any of the fields within the `RcBox<T>` visible so it is *not* stabilizing the exact layout of the `RcBox<T>`. The only operations that can be done with `RcBox<T>` is initializing one from a `T` and subsequently creating an `Rc<T>` from a `Box<RcBox<T>>`.
`RcBox` does not seem like the most descriptive name for a type that's now publicly accessible. Rename it to `RcRepr` since it's the underyling representation of an `Rc`.
Thanks for the pull request, and welcome! The Rust team is excited to review your changes, and you should hear from @m-ou-se (or someone else) soon. If any changes to this PR are deemed necessary, please add them as extra commits. This ensures that the reviewer can see what has changed since they last reviewed the code. Due to the way GitHub handles out-of-date commits, this should also make it reasonably obvious what issues have or haven't been addressed. Large or tricky changes may require several passes of review and changes. Please see the contribution instructions for more information. |
Going through Box seems somewhat ad hoc in the face of ongoing work with the allocator API. Wouldn't it be better to have a Somewhat similar to fallible allocations in |
(Hi @cramertj, what was wrong with the auto-assigned reviewer? Not having my name in https://github.com/rust-lang/highfive/blob/master/highfive/configs/rust-lang/rust.json is deliberate. I might be slow to respond further.) This PR exposes implementation details that I feel should never be stabilized. I’d be more inclined to consider a fallible |
I'm fine with try_new, (that was the second option listed in https://internals.rust-lang.org/t/expose-a-way-to-create-an-arc-fallibly/13551). I just chose this option since I didn't get strong feedback one way or the other there and it let me avoid the question of what Error to return when try_new fails. I didn't see this approach conflicting with the ongoing allocator API work. In the future when Arc has a second type param for the allocator then it would simply get added to the from_repr requirements. Something like:
Your prototype returns an |
I have no problem preferring a try_new method, but on the point of stabilizing implementation details I wanted to point out that this does not stabilize the implementation details of the Rc/Arc. It only stabilizes the fact that Arc/Rc are wrappers around a Box'd version of something. The implementation of that something is not stabilized and they are still free to change. |
Well, for one it would make the size of the heap allocation observable which wasn't before. It would also set in stone that it can represented by a single allocation, conceivably the counters and the payload itself could have been stored separately.
It sounded like you wanted to separate the time at which the storage is allocated vs. the time at which it is actually used. If that's not the goal then yeah the
From previous discussions the Or to put it differently, there already are vague plans for what you want but they're not fully implemented yet, only |
Valid points.
Great.
Okay. I'll go forward with a |
A new feature makes sense since previous discussion and RFC 2116 only discussed collections, not pointer-like containers. So some new discussion will be necessary. I have thought about the |
I'd like to add my +1 to the spirit of this PR. In my project I also need a way to construct (potentially large) As a systems language, Rust definitely needs something like |
See #80310 for similar work being done for |
Thanks for the pointer. I'm planning on putting together a new PR with the try_new api, and I'll follow that Box discussion to ensure that Rc/Arc match appropriately. |
FWIW, |
Do they? The counters could be looked up by pointer value, e.g. in a static, thread-safe table. Not the greatest implementation, but theoretically possible with the current design. Lookup would work since you're not allowed to provide arbitrary pointers, only pointers created by |
#63291 (comment) proposes a separate 'builder' type for I'd prefer some kind of 'builder' like this over exposing implementation details like |
☔ The latest upstream changes (presumably #80310) made this pull request unmergeable. Please resolve the merge conflicts. |
I think that's solving a different problem. I'm working in an environment where we want to be sure that allocation failures do not cause a panic and are handled at the call-site where the allocation occurs. The motivation for this change was to allow external unsafe code to allocate and initialize an ArcRepr itself handling it however we want, then the conversion into an Arc would not require any additional allocation. Having a try_new method on Arc also accomplishes my goal, which is what I was planning on proposing next, but luckily #80310 beat me to it. I'm going to go ahead and close this PR since #80310 added all the functionality I wanted. |
As discussed on the internals forum https://internals.rust-lang.org/t/expose-a-way-to-create-an-arc-fallibly/13551
I'm working on a project that is very strict about when it's appropriate to allocate and is not allowed to panic on allocation failure. The current mechanism of creating an Rc/Arc does not allow gracefully failing to allocate. This series of changes provides an optional way of constructing an Rc/Arc where the user provides an already Box'd version of the Rc/Arc internal representation and the Rc/Arc can be constructed by taking over the allocation. This gives control to the user over how to construct the Box, which can be done in a fallible way in our case.
In the process of making the types visible it seemed to me that they should be renamed. I'm not set on the names
RcRepr
andArcRepr
and would welcome better suggestions.