-
Notifications
You must be signed in to change notification settings - Fork 12.7k
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
#[repr(transparent)] for Box<T>? #52976
Comments
How does this interact with |
They don't. I already do this in my C API even though it's not entirely defined behavior at the moment: https://github.com/LiveSplit/livesplit-core/blob/3ac0834f70a3963f1b7e4fec84b0803c51e6349e/capi/src/fuzzy_list.rs#L12-L24 |
Yeah, what @CryZe said. This is not for importing foreign functions, this is for easily and safely exposing Rust functions that allocate+return+deallocate |
How would this interact with #50882? |
Sadly, they wouldn't be compatible when allocator is not zero-sized. I'm surprised |
The allocator value that would be used in most cases is |
Nothing in |
@sfackler The question is more whether this would be guaranteed for any allocators (I suspect not). In that case, |
I feel like if it would / should be guaranteed, then PhantomData<T> would /
should be used instead.
Ingvar Stepanyan <[email protected]> schrieb am Mo. 6. Aug. 2018 um
13:23:
… @sfackler <https://github.com/sfackler> The question is more whether this
would be guaranteed for any allocators (I suspect not). In that case,
repr(transparent) would indeed not work, but I suspect there are other
parts of compiler that currently rely on lang item behind Box being just
a pointer...
—
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
<#52976 (comment)>,
or mute the thread
<https://github.com/notifications/unsubscribe-auth/ABYmbsshbFXIf5D0N2GfHm6UuPDPtwFOks5uOCcigaJpZM4VsMCs>
.
|
Sorry, I didn't get it - instead of what? |
|
Agreed. IIUC the motivation for storing |
Also, I suppose, if allocator does want to share some extra data, it can always allocate pointer with larger size and store that metadata (or a pointer to one) alongside actual data in the heap. |
Why does Box need to differ from unique_ptr in this respect? |
Do you mean C++ unique_ptr? Why would Box be similar to it? For one, Rust already has lots of differences with C++, including in memory management, and in particular availability of zero-sized types which is what @CryZe and me are suggesting to use for custom allocators. |
Box is the direct analogue of C++'s unique_ptr. If I understand it correctly, you want to prohibit the use of stateful allocators (e.g. an arena) with Box because it will allow you to treat Box the same as a raw pointer for FFI? |
Yes, but not necessarily prohibit - as I said, even for cases where allocator does need to store some unique state (that can't be put into So this preserves flexibility for allocators while allows to use |
Right now, I understand the motivation of extending I understand the desire to allow I haven't heard any arguments in support of not making this change now. So are there any? Otherwise we should just make |
I'm absolutely still in favour of this change, but the backpressure was hard when I raised the issue. Did it change / can we agree allocators to be limited to |
FWIW, we don't even have to apply the |
Well, it can't because it's not guaranteed by the compiler at all (even if happens to be compatible on popular platforms). |
If the Box documentation says that Box is guaranteed to have the same layout as a *mut T, and the compiler violates it, the compiler has a bug. |
Yeah, but documentation currently doesn't say that, and merely writing that down won't guarantee that it actually works that way everywhere :) |
I'd much rather have a strict |
Hence this proposal.
Of course not, that would need to come with tests, but AFAIK the compiler currently gives structs with default layout and a single field the same layout as that field on all platforms that Rust currently supports. So beyond adding a test to liballoc checking that this is the case for Box, not much more would need to be done.
That would prevent extending Box with an allocator type parameter, which is something that we want to do, and an entire working group is trying to solve. Since |
It wouldn't prevent it, just constraint to using ZST as an allocator parameter, which is what I suggested originally and you seemed to support above as well? |
We want to support non zero-sized allocator parameters, and this is incompatible with that.
I support guaranteeing that |
Okay, I guess I misread
as encouragement of supporting only ZST A's. |
This officializes what was only shown as a code example in [the unsafe code guidelines](https://rust-lang.github.io/unsafe-code-guidelines/layout/function-pointers.html?highlight=box#use) and follows [the discussion](rust-lang/unsafe-code-guidelines#157) in the corresponding repository. It is also related to [the issue](rust-lang#52976) regarding marking `Box<T>` `#[repr(transparent)]`.
@Lokathor pointed out, that this "implementation detail" is "documented" in the
|
Fine by me - not the outcome I initially hoped for, but it does the trick and reaches same goal anyway :) |
The goal of using standard library containers with different allocators, including non-zero-size handles, is part of an accepted RFC that precedes the new transparency guarantee being proposed here: https://rust-lang.github.io/rfcs/1398-kinds-of-allocators.html#what-about-standard-library-containers Ideally we would have |
This PR solves that: #62514 Once we stabilize Box<T, A> we just need to clarify that that only holds if A is zero-sized, and that's pretty much it AFAICT. We plan to submit an RFC to guarantee this for all types for which this holds as part of the UCGs RFC. There is a PR in the UCG repo with proposed wording for that as well: rust-lang/unsafe-code-guidelines#164 (is blocked on some nit-picking on how to abbreviate one-aligned ZSTs but there is consensus that we want to guarantee that). So when that happens the documentation comment guaranteeing this wouldn't be technically necessary anymore, since it would be a given, but it would obviously be documentation worth having. |
I think #62514 is only adding comments, and there seems to be needing language level mechanism if we want to move forward. |
The comment there guarantees that box can be used in C FFI. Isn't that enough to resolve this? |
Is it? From FFI ABI perspective, adding those comments doesn't turn ABI for |
As long as it is guaranteed and there is some test verifying that it is the case, it doesn't need a special attribute. |
Box is as special as |
ok, i guess that's the magic of |
Clarify `Box<T>` representation and its use in FFI This officializes what was only shown as a code example in [the unsafe code guidelines](https://rust-lang.github.io/unsafe-code-guidelines/layout/function-pointers.html?highlight=box#use) and follows [the discussion](rust-lang/unsafe-code-guidelines#157) in the corresponding repository. It is also related to [the issue](rust-lang#52976) regarding marking `Box<T>` `#[repr(transparent)]`. If the statement this PR adds is incorrect or a more in-depth discussion is warranted, I apologize. Should it be the case, the example in the unsafe code guidelines should be amended and some document should make it clear that it is not sound/supported.
We now have some extensive documentation about use of Box with FFI and generally the properties we guarantee: https://doc.rust-lang.org/nightly/std/boxed/index.html#memory-layout. Closing. |
#43036 added
#[repr(transparent)]
with one of the goals being safe FFI interaction for newtypes, and added that attribute to bunch of built-in types such asNonZero
,Waker
,Unique
etc.One use-case that could be really helpful for FFI though is adding it to
Box<T>
. I haven't found any previous discussions on pros and cons of doing so, so apologies if this is way off and there are obvious reasons why it can't be such, but as far as I can tell, this is not a breaking change neither from API nor from memory representation perspective.Looking from definition,
Box
is just a wrapper aroundUnique
which is already#[repr(transparent)]
and wrapsNonNull
which is also#[repr(transparent)]
which, in turn, wraps raw pointer which is FFI-safe.Adding this attribute to
Box
would make it transparent wrapper all the way down around a raw pointer, and so would allow to do FFI interactions by simply leakingBox
as return type in allocator functions and accepting it as-is in deallocator function without manualinto_raw
andfrom_raw
conversions.Aside from ergonomics improvement (allocation / deallocation is pretty common operation in
cdylib
s), this would also allow code to be more self-documenting as just from looking at rustdoc you would be able to tell which pointers are owned and will be allocated or consumed by Rust side.Counter-argument might be that one can implement custom transparent
CBox
on top ofNonNull
, but this involves reimplementing many APIs and guaranteesBox
already provides e.g.Unique
is not exposed at the moment, and then you also have various standard traits that "just work" withBox
, so if it would be possible to avoid reimplementing all of that with no obvious downsides, it might be still useful to shared library authors.The text was updated successfully, but these errors were encountered: