Skip to content

UnsafeUnion type #371

Description

@glaebhoerl

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.

Activity

  1. nrc commented on Oct 8, 2014

    @nrc
    Member

    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.

  2. glaebhoerl commented on Oct 8, 2014

    @glaebhoerl
    ContributorAuthor

    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?)

  3. mahkoh commented on Oct 8, 2014

    @mahkoh
    Contributor

    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.

  4. Stebalien commented on Aug 19, 2016

    @Stebalien
    Contributor

    Triage: fixed by #1444

  5. added
    T-langRelevant to the language team, which will review and decide on the RFC.
    on Aug 19, 2016
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    T-langRelevant to the language team, which will review and decide on the RFC.

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions