Skip to content
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

UnsafeUnion type #371

Closed
glaebhoerl opened this Issue Oct 8, 2014 · 4 comments

Comments

Projects
None yet
4 participants
@glaebhoerl
Copy link
Contributor

glaebhoerl commented Oct 8, 2014

Splicing in my comment from a related RFC:

  • Add a built-in type UnsafeUnion<A, B>.
  • This is essentially like unions in C: a type compatible with the size and alignment of both A and B. So sizeof(UnsafeUnion<A, B>) = max(sizeof(A), sizeof(B)), and alignof(UnsafeUnion<A, B>) = lcm(alignof(A), alignof(B)).
  • Unlike C, it doesn't have fields, rather "construction" and "deconstruction" both simply happen using transmute(). So transmute::<A, UnsafeUnion<A, B>>, transmute::<B, UnsafeUnion<A, B>>, transmute::<UnsafeUnion<A, B>, A>, and transmute::<UnsafeUnion<A, B>, B> all have well-defined behavior, in basically the same circumstances as in C. (This means that the input and output of transmute would not have the same size/alignment in these cases. I don't know whether this is an issue, provided that they are both known.)
  • transmutes of pointers/references, on the other hand, should only be valid in one direction: e.g. you can legally transmute &UnsafeUnion<A, B> to &A, but not vice versa.
  • Because the representation of UnsafeUnions is idempotent: repr(UnsafeUnion<A, A>) = repr(A), commutative: repr(UnsafeUnion<A, B>) = repr(UnsafeUnion<B, A>), and associative: repr(UnsafeUnion<A, UnsafeUnion<B, C>>) = repr(UnsafeUnion<UnsafeUnion<A, B>, C>), larger unions can simply be composed from the binary one. The use of transmute for {,de}construction is also completely impervious to this nesting. We could then also potentially provide synonyms like type UnsafeUnion3<A, B, C> = UnsafeUnion<A, UnsafeUnion<B, C>> for convenience.
  • It should also be layout-compatible with C, and so should be usable to represent C unions in the FFI.

This would primarily be for (a) unsafe code and (b) interfacing with C.

@nrc

This comment has been minimized.

Copy link
Member

nrc commented Oct 8, 2014

re the last point - we have been moving in the direction of leaving layouts undefined and requiring an annotation to get a specific (C-compatible) layout, which I think is a good thing. I would recommend the same here.

@glaebhoerl

This comment has been minimized.

Copy link
Contributor Author

glaebhoerl commented Oct 8, 2014

I agree with that in general, but in this particular case, where would you put the annotation? This is a type, not a language construct -- seems like that would require separate UnsafeUnion and CUnsafeUnion types, which seems a bit excessive. I'm also not sure how much room there is for different representations at all, though I'm also not familiar with how C defines it.

(The minimum size/alignment are dictated by size and alignment constraints of the contained types - and I guess you could make it even larger or more loosely aligned, but why?)

@mahkoh

This comment has been minimized.

Copy link
Contributor

mahkoh commented Oct 8, 2014

As in the other RFC, this should be possible in Rust without special cases in the compiler. Instead of making one RFC per type, one should try to find out what features are necessary to implement this in a library.

@Stebalien

This comment has been minimized.

Copy link
Contributor

Stebalien commented Aug 19, 2016

Triage: fixed by #1444

@nrc nrc closed this Aug 19, 2016

@nrc nrc added the T-lang label Aug 19, 2016

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.