From 991ea90c832d25c894940c4d57a033581fa171b9 Mon Sep 17 00:00:00 2001 From: Michael Bradshaw Date: Sun, 24 Feb 2019 21:30:21 -0800 Subject: [PATCH 01/26] Transparent Unions RFC --- text/0000-transparent-unions.md | 103 ++++++++++++++++++++++++++++++++ 1 file changed, 103 insertions(+) create mode 100644 text/0000-transparent-unions.md diff --git a/text/0000-transparent-unions.md b/text/0000-transparent-unions.md new file mode 100644 index 00000000000..c873ec03739 --- /dev/null +++ b/text/0000-transparent-unions.md @@ -0,0 +1,103 @@ +- Feature Name: transparent_unions +- Start Date: 2019-02-13 +- RFC PR: +- Rust Issue: + +# Summary +[summary]: #summary + +Allow `#[repr(transparent)]` on `union`s that have exactly one non-zero-sized field (just like `struct`s). + +# Motivation +[motivation]: #motivation + +Some `union` types are thin newtype-style wrappers around another type, like `MaybeUninit` (and [once upon a time](https://doc.rust-lang.org/1.26.1/src/core/mem.rs.html#950), `ManuallyDrop`). This type is intended to be used in the same places as `T`, but without being `#[repr(transparent)]` the actual compatibility between it and `T` is left unspecified. + +Making types like these `#[repr(transparent)]` would be useful in certain cases. For example, making a `union Wrapper` transparent: + +- Clearly expresses the intent of the developer. +- Protects against accidental violations of that intent (e.g., adding a new non-ZST field to a transparent union will result in a compiler error). +- Makes a clear API guarantee that a `Wrapper` can be transmuted to a `T`. + +Transparent `union`s are a nice complement to transparent `struct`s, and this RFC rounds out the `#[repr(transparent)]` feature. + +# Guide-level explanation +[guide-level-explanation]: #guide-level-explanation + +A `union` may be `#[repr(transparent)]` in exactly the same conditions in which a struct may be `#[repr(transparent)]`. Some concrete illustrations follow. + +A union may be `#[repr(transparent)]` if it has exactly one non-zero-sized field: + +```rust +// This union has the same representation as `usize`. +#[repr(transparent)] +union CustomUnion { + field: usize, + nothing: (), +} +``` + +If the `union` is generic over `T` and has a field of type `T`, it may also be `#[repr(transparent)]` (even if `T` is a zero-sized type): + +```rust +// This union has the same representation as `T`. +#[repr(transparent)] +pub union GenericUnion { // Unions with non-`Copy` fields are unstable. + pub field: T, + pub nothing: (), +} + +// This is okay even though `()` is a zero-sized type. +pub const THIS_IS_OKAY: GenericUnion<()> = GenericUnion { field: () }; +``` + +# Reference-level explanation +[reference-level-explanation]: #reference-level-explanation + +The logic controlling whether a `union` of type `U` may be `#[repr(transparent)]` should match the logic controlling whether a `struct` of type `S` may be `#[repr(transparent)]` (assuming `U` and `S` have the same generic parameters and fields). + +# Drawbacks +[drawbacks]: #drawbacks + +- `#[repr(transparent)]` on a `union` is of limited use. There are cases where it is useful, but they're not common and some users might unnecessarily apply `#[repr(transparent)]` to a `union`. + +# Rationale and alternatives +[alternatives]: #alternatives + +It would be nice to make `MaybeUninit` `#[repr(transparent)]`. This type is a `union`, and thus this RFC is required in order to allow making it transparent. + +Of course, the standard "do nothing" alternative exists. Rust doesn't strictly *require* this feature. But it would benefit from this, so the "do nothing" alternative is undesirable. + +# Prior art +[prior-art]: #prior-art + +See [the discussion on RFC #1758](https://github.com/rust-lang/rfcs/pull/1758) (which introduced `#[repr(transparent)]`) for some discussion on applying the attribute to a `union`. A summary of the discussion: + +> https://github.com/rust-lang/rfcs/pull/1758#discussion_r80436621 +> **nagisa:** "Why not univariant unions and enums?" +> **nox:** "I tried to be conservative for now given I don't have a use case for univariant unions and enums in FFI context." + +> https://github.com/rust-lang/rfcs/pull/1758#issuecomment-254872520 +> **eddyb:** "I found another important usecase: for `ManuallyDrop`, to be useful in arrays (i.e. small vector optimizations), it needs to have the same layout as `T` and AFAICT `#[repr(C)]` is not guaranteed to do the right thing" +> **retep998:** "So we'd need to be able to specify `#[repr(transparent)]` on unions?" +> **eddyb:** "That's the only way to be sure AFAICT, yes." + +> https://github.com/rust-lang/rfcs/pull/1758#issuecomment-274670231 +> **joshtriplett:** "In terms of interactions with other features, I think this needs to specify what happens if you apply it to a union with one field, a union with multiple fields, a struct (tuple or otherwise) with multiple fields, a single-variant enum with one field, an enum struct variant where the enum uses `repr(u32)` or similar. The answer to some of those might be "compile error", but some of them (e.g. the union case) may potentially make sense in some contexts." + +> https://github.com/rust-lang/rfcs/pull/1758#issuecomment-290757356 +> **pnkfelix:** "However, I personally do not think we need to expand the scope of the feature. So I am okay with leaving it solely defined on `struct`, and leave `union`/`enum` to a follow-on RFC later. (Much the same with a hypothetical `newtype` feature.)" + +In summary, many of the questions regarding `#[repr(transparent)]` on a `union` were the same as applying it to a multi-field `struct`. These questions have since been answered, and I see no problems with applying those same answers to `union`. + +# Unresolved questions +[unresolved]: #unresolved-questions + +None (yet). + +# Future possibilities +[future-possibilities]: #future-possibilities + +Univariant `enum`s are ommitted from this RFC in an effort to keep the scope small and avoid unnecessary bikeshedding. A future RFC could explore `#[repr(transparent)]` on a univariant `enum`. + +If a `union` has multiple non-ZST fields, a future RFC could propose a way to choose the representation of that enum ([example](https://internals.rust-lang.org/t/pre-rfc-transparent-unions/9441/6)). From e08e4a276d87607800e20b0ea368c35977b298ff Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Mon, 25 Feb 2019 06:46:55 -0800 Subject: [PATCH 02/26] Update text/0000-transparent-unions.md Co-Authored-By: mjbshaw --- text/0000-transparent-unions.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/text/0000-transparent-unions.md b/text/0000-transparent-unions.md index c873ec03739..12e4ac36875 100644 --- a/text/0000-transparent-unions.md +++ b/text/0000-transparent-unions.md @@ -64,7 +64,7 @@ The logic controlling whether a `union` of type `U` may be `#[repr(transparent)] # Rationale and alternatives [alternatives]: #alternatives -It would be nice to make `MaybeUninit` `#[repr(transparent)]`. This type is a `union`, and thus this RFC is required in order to allow making it transparent. +It would be nice to make `MaybeUninit` `#[repr(transparent)]`. This type is a `union`, and thus this RFC is required to allow making it transparent. Of course, the standard "do nothing" alternative exists. Rust doesn't strictly *require* this feature. But it would benefit from this, so the "do nothing" alternative is undesirable. From f7c332eddd5b1b0c7eb068462d87aca9552c2739 Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Mon, 25 Feb 2019 06:47:18 -0800 Subject: [PATCH 03/26] Update text/0000-transparent-unions.md Co-Authored-By: mjbshaw --- text/0000-transparent-unions.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/text/0000-transparent-unions.md b/text/0000-transparent-unions.md index 12e4ac36875..fa85077419c 100644 --- a/text/0000-transparent-unions.md +++ b/text/0000-transparent-unions.md @@ -88,7 +88,7 @@ See [the discussion on RFC #1758](https://github.com/rust-lang/rfcs/pull/1758) ( > https://github.com/rust-lang/rfcs/pull/1758#issuecomment-290757356 > **pnkfelix:** "However, I personally do not think we need to expand the scope of the feature. So I am okay with leaving it solely defined on `struct`, and leave `union`/`enum` to a follow-on RFC later. (Much the same with a hypothetical `newtype` feature.)" -In summary, many of the questions regarding `#[repr(transparent)]` on a `union` were the same as applying it to a multi-field `struct`. These questions have since been answered, and I see no problems with applying those same answers to `union`. +In summary, many of the questions regarding `#[repr(transparent)]` on a `union` were the same as applying it to a multi-field `struct`. These questions have since been answered, so there should be no problems with applying those same answers to `union`. # Unresolved questions [unresolved]: #unresolved-questions From cb3f67158c7baafb8987c5c22d205f8102b014a1 Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Mon, 25 Feb 2019 06:48:10 -0800 Subject: [PATCH 04/26] Update text/0000-transparent-unions.md Co-Authored-By: mjbshaw --- text/0000-transparent-unions.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/text/0000-transparent-unions.md b/text/0000-transparent-unions.md index fa85077419c..e29711fd8c8 100644 --- a/text/0000-transparent-unions.md +++ b/text/0000-transparent-unions.md @@ -100,4 +100,4 @@ None (yet). Univariant `enum`s are ommitted from this RFC in an effort to keep the scope small and avoid unnecessary bikeshedding. A future RFC could explore `#[repr(transparent)]` on a univariant `enum`. -If a `union` has multiple non-ZST fields, a future RFC could propose a way to choose the representation of that enum ([example](https://internals.rust-lang.org/t/pre-rfc-transparent-unions/9441/6)). +If a `union` has multiple non-ZST fields, a future RFC could propose a way to choose the representation of that `union` ([example](https://internals.rust-lang.org/t/pre-rfc-transparent-unions/9441/6)). From 381fcf6c80161b191ae99f78882506383919a49f Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Mon, 25 Feb 2019 06:48:20 -0800 Subject: [PATCH 05/26] Update text/0000-transparent-unions.md Co-Authored-By: mjbshaw --- text/0000-transparent-unions.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/text/0000-transparent-unions.md b/text/0000-transparent-unions.md index e29711fd8c8..5ac08d9c6e8 100644 --- a/text/0000-transparent-unions.md +++ b/text/0000-transparent-unions.md @@ -83,7 +83,7 @@ See [the discussion on RFC #1758](https://github.com/rust-lang/rfcs/pull/1758) ( > **eddyb:** "That's the only way to be sure AFAICT, yes." > https://github.com/rust-lang/rfcs/pull/1758#issuecomment-274670231 -> **joshtriplett:** "In terms of interactions with other features, I think this needs to specify what happens if you apply it to a union with one field, a union with multiple fields, a struct (tuple or otherwise) with multiple fields, a single-variant enum with one field, an enum struct variant where the enum uses `repr(u32)` or similar. The answer to some of those might be "compile error", but some of them (e.g. the union case) may potentially make sense in some contexts." +> + **[joshtriplett][joshtriplett_1]:** "In terms of interactions with other features, I think this needs to specify what happens if you apply it to a union with one field, a union with multiple fields, a struct (tuple or otherwise) with multiple fields, a single-variant enum with one field, an enum struct variant where the enum uses `repr(u32)` or similar. The answer to some of those might be "compile error", but some of them (e.g. the union case) may potentially make sense in some contexts." > https://github.com/rust-lang/rfcs/pull/1758#issuecomment-290757356 > **pnkfelix:** "However, I personally do not think we need to expand the scope of the feature. So I am okay with leaving it solely defined on `struct`, and leave `union`/`enum` to a follow-on RFC later. (Much the same with a hypothetical `newtype` feature.)" From eb37cceaaf3efc42ca31955f5833409ad4cf45b6 Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Mon, 25 Feb 2019 06:48:27 -0800 Subject: [PATCH 06/26] Update text/0000-transparent-unions.md Co-Authored-By: mjbshaw --- text/0000-transparent-unions.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/text/0000-transparent-unions.md b/text/0000-transparent-unions.md index 5ac08d9c6e8..cd18d2d58e0 100644 --- a/text/0000-transparent-unions.md +++ b/text/0000-transparent-unions.md @@ -85,7 +85,7 @@ See [the discussion on RFC #1758](https://github.com/rust-lang/rfcs/pull/1758) ( > https://github.com/rust-lang/rfcs/pull/1758#issuecomment-274670231 > + **[joshtriplett][joshtriplett_1]:** "In terms of interactions with other features, I think this needs to specify what happens if you apply it to a union with one field, a union with multiple fields, a struct (tuple or otherwise) with multiple fields, a single-variant enum with one field, an enum struct variant where the enum uses `repr(u32)` or similar. The answer to some of those might be "compile error", but some of them (e.g. the union case) may potentially make sense in some contexts." -> https://github.com/rust-lang/rfcs/pull/1758#issuecomment-290757356 +[pnkfelix_1]: https://github.com/rust-lang/rfcs/pull/1758#issuecomment-290757356 > **pnkfelix:** "However, I personally do not think we need to expand the scope of the feature. So I am okay with leaving it solely defined on `struct`, and leave `union`/`enum` to a follow-on RFC later. (Much the same with a hypothetical `newtype` feature.)" In summary, many of the questions regarding `#[repr(transparent)]` on a `union` were the same as applying it to a multi-field `struct`. These questions have since been answered, so there should be no problems with applying those same answers to `union`. From 45be61d52537e09abe743b4cb086fb2a6497f88e Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Mon, 25 Feb 2019 06:48:35 -0800 Subject: [PATCH 07/26] Update text/0000-transparent-unions.md Co-Authored-By: mjbshaw --- text/0000-transparent-unions.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/text/0000-transparent-unions.md b/text/0000-transparent-unions.md index cd18d2d58e0..e8b18f4b908 100644 --- a/text/0000-transparent-unions.md +++ b/text/0000-transparent-unions.md @@ -86,7 +86,7 @@ See [the discussion on RFC #1758](https://github.com/rust-lang/rfcs/pull/1758) ( > + **[joshtriplett][joshtriplett_1]:** "In terms of interactions with other features, I think this needs to specify what happens if you apply it to a union with one field, a union with multiple fields, a struct (tuple or otherwise) with multiple fields, a single-variant enum with one field, an enum struct variant where the enum uses `repr(u32)` or similar. The answer to some of those might be "compile error", but some of them (e.g. the union case) may potentially make sense in some contexts." [pnkfelix_1]: https://github.com/rust-lang/rfcs/pull/1758#issuecomment-290757356 -> **pnkfelix:** "However, I personally do not think we need to expand the scope of the feature. So I am okay with leaving it solely defined on `struct`, and leave `union`/`enum` to a follow-on RFC later. (Much the same with a hypothetical `newtype` feature.)" +> + **[pnkfelix][pnkfelix_1]:** "However, I personally do not think we need to expand the scope of the feature. So I am okay with leaving it solely defined on `struct`, and leave `union`/`enum` to a follow-on RFC later. (Much the same with a hypothetical `newtype` feature.)" In summary, many of the questions regarding `#[repr(transparent)]` on a `union` were the same as applying it to a multi-field `struct`. These questions have since been answered, so there should be no problems with applying those same answers to `union`. From 582fd1527e2b4c3c5fa35a2782584922e6659331 Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Mon, 25 Feb 2019 06:48:45 -0800 Subject: [PATCH 08/26] Update text/0000-transparent-unions.md Co-Authored-By: mjbshaw --- text/0000-transparent-unions.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/text/0000-transparent-unions.md b/text/0000-transparent-unions.md index e8b18f4b908..11a3245c4af 100644 --- a/text/0000-transparent-unions.md +++ b/text/0000-transparent-unions.md @@ -82,7 +82,7 @@ See [the discussion on RFC #1758](https://github.com/rust-lang/rfcs/pull/1758) ( > **retep998:** "So we'd need to be able to specify `#[repr(transparent)]` on unions?" > **eddyb:** "That's the only way to be sure AFAICT, yes." -> https://github.com/rust-lang/rfcs/pull/1758#issuecomment-274670231 +[joshtriplett_1]: https://github.com/rust-lang/rfcs/pull/1758#issuecomment-274670231 > + **[joshtriplett][joshtriplett_1]:** "In terms of interactions with other features, I think this needs to specify what happens if you apply it to a union with one field, a union with multiple fields, a struct (tuple or otherwise) with multiple fields, a single-variant enum with one field, an enum struct variant where the enum uses `repr(u32)` or similar. The answer to some of those might be "compile error", but some of them (e.g. the union case) may potentially make sense in some contexts." [pnkfelix_1]: https://github.com/rust-lang/rfcs/pull/1758#issuecomment-290757356 From d532738cda3bb743f76f300b763c720d4d0560fa Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Mon, 25 Feb 2019 06:49:01 -0800 Subject: [PATCH 09/26] Update text/0000-transparent-unions.md Co-Authored-By: mjbshaw --- text/0000-transparent-unions.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/text/0000-transparent-unions.md b/text/0000-transparent-unions.md index 11a3245c4af..ba5cc7115cd 100644 --- a/text/0000-transparent-unions.md +++ b/text/0000-transparent-unions.md @@ -73,7 +73,7 @@ Of course, the standard "do nothing" alternative exists. Rust doesn't strictly * See [the discussion on RFC #1758](https://github.com/rust-lang/rfcs/pull/1758) (which introduced `#[repr(transparent)]`) for some discussion on applying the attribute to a `union`. A summary of the discussion: -> https://github.com/rust-lang/rfcs/pull/1758#discussion_r80436621 +[nagisa_1]: https://github.com/rust-lang/rfcs/pull/1758#discussion_r80436621 > **nagisa:** "Why not univariant unions and enums?" > **nox:** "I tried to be conservative for now given I don't have a use case for univariant unions and enums in FFI context." From 4529a9523c6dee33a99cc2245f52afa210ae2359 Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Mon, 25 Feb 2019 06:49:13 -0800 Subject: [PATCH 10/26] Update text/0000-transparent-unions.md Co-Authored-By: mjbshaw --- text/0000-transparent-unions.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/text/0000-transparent-unions.md b/text/0000-transparent-unions.md index ba5cc7115cd..908aa08ba0d 100644 --- a/text/0000-transparent-unions.md +++ b/text/0000-transparent-unions.md @@ -74,7 +74,7 @@ Of course, the standard "do nothing" alternative exists. Rust doesn't strictly * See [the discussion on RFC #1758](https://github.com/rust-lang/rfcs/pull/1758) (which introduced `#[repr(transparent)]`) for some discussion on applying the attribute to a `union`. A summary of the discussion: [nagisa_1]: https://github.com/rust-lang/rfcs/pull/1758#discussion_r80436621 -> **nagisa:** "Why not univariant unions and enums?" +> + **[nagisa][nagisa_1]:** "Why not univariant unions and enums?" > **nox:** "I tried to be conservative for now given I don't have a use case for univariant unions and enums in FFI context." > https://github.com/rust-lang/rfcs/pull/1758#issuecomment-254872520 From bb735051847075320d43d2fc09e52ac4186e2016 Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Mon, 25 Feb 2019 06:49:26 -0800 Subject: [PATCH 11/26] Update text/0000-transparent-unions.md Co-Authored-By: mjbshaw --- text/0000-transparent-unions.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/text/0000-transparent-unions.md b/text/0000-transparent-unions.md index 908aa08ba0d..82514b5c9a9 100644 --- a/text/0000-transparent-unions.md +++ b/text/0000-transparent-unions.md @@ -75,7 +75,7 @@ See [the discussion on RFC #1758](https://github.com/rust-lang/rfcs/pull/1758) ( [nagisa_1]: https://github.com/rust-lang/rfcs/pull/1758#discussion_r80436621 > + **[nagisa][nagisa_1]:** "Why not univariant unions and enums?" -> **nox:** "I tried to be conservative for now given I don't have a use case for univariant unions and enums in FFI context." +> + **nox:** "I tried to be conservative for now given I don't have a use case for univariant unions and enums in FFI context." > https://github.com/rust-lang/rfcs/pull/1758#issuecomment-254872520 > **eddyb:** "I found another important usecase: for `ManuallyDrop`, to be useful in arrays (i.e. small vector optimizations), it needs to have the same layout as `T` and AFAICT `#[repr(C)]` is not guaranteed to do the right thing" From f9b9d8e30062b95fb5856a5fb757705ace3f9021 Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Mon, 25 Feb 2019 06:50:27 -0800 Subject: [PATCH 12/26] Update text/0000-transparent-unions.md Co-Authored-By: mjbshaw --- text/0000-transparent-unions.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/text/0000-transparent-unions.md b/text/0000-transparent-unions.md index 82514b5c9a9..789bccbe5dd 100644 --- a/text/0000-transparent-unions.md +++ b/text/0000-transparent-unions.md @@ -77,7 +77,7 @@ See [the discussion on RFC #1758](https://github.com/rust-lang/rfcs/pull/1758) ( > + **[nagisa][nagisa_1]:** "Why not univariant unions and enums?" > + **nox:** "I tried to be conservative for now given I don't have a use case for univariant unions and enums in FFI context." -> https://github.com/rust-lang/rfcs/pull/1758#issuecomment-254872520 +[eddyb_1]: https://github.com/rust-lang/rfcs/pull/1758#issuecomment-254872520 > **eddyb:** "I found another important usecase: for `ManuallyDrop`, to be useful in arrays (i.e. small vector optimizations), it needs to have the same layout as `T` and AFAICT `#[repr(C)]` is not guaranteed to do the right thing" > **retep998:** "So we'd need to be able to specify `#[repr(transparent)]` on unions?" > **eddyb:** "That's the only way to be sure AFAICT, yes." From 1bce145ca648d695b6d9b82be7cd9fc8bd5b1386 Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Mon, 25 Feb 2019 06:50:50 -0800 Subject: [PATCH 13/26] Update text/0000-transparent-unions.md Co-Authored-By: mjbshaw --- text/0000-transparent-unions.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/text/0000-transparent-unions.md b/text/0000-transparent-unions.md index 789bccbe5dd..5ab9c992a6b 100644 --- a/text/0000-transparent-unions.md +++ b/text/0000-transparent-unions.md @@ -80,7 +80,7 @@ See [the discussion on RFC #1758](https://github.com/rust-lang/rfcs/pull/1758) ( [eddyb_1]: https://github.com/rust-lang/rfcs/pull/1758#issuecomment-254872520 > **eddyb:** "I found another important usecase: for `ManuallyDrop`, to be useful in arrays (i.e. small vector optimizations), it needs to have the same layout as `T` and AFAICT `#[repr(C)]` is not guaranteed to do the right thing" > **retep998:** "So we'd need to be able to specify `#[repr(transparent)]` on unions?" -> **eddyb:** "That's the only way to be sure AFAICT, yes." +> + **eddyb:** "That's the only way to be sure AFAICT, yes." [joshtriplett_1]: https://github.com/rust-lang/rfcs/pull/1758#issuecomment-274670231 > + **[joshtriplett][joshtriplett_1]:** "In terms of interactions with other features, I think this needs to specify what happens if you apply it to a union with one field, a union with multiple fields, a struct (tuple or otherwise) with multiple fields, a single-variant enum with one field, an enum struct variant where the enum uses `repr(u32)` or similar. The answer to some of those might be "compile error", but some of them (e.g. the union case) may potentially make sense in some contexts." From f751ad344219ea73f752be07a3f13f3728101876 Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Mon, 25 Feb 2019 06:51:03 -0800 Subject: [PATCH 14/26] Update text/0000-transparent-unions.md Co-Authored-By: mjbshaw --- text/0000-transparent-unions.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/text/0000-transparent-unions.md b/text/0000-transparent-unions.md index 5ab9c992a6b..56b004b6bc4 100644 --- a/text/0000-transparent-unions.md +++ b/text/0000-transparent-unions.md @@ -78,7 +78,7 @@ See [the discussion on RFC #1758](https://github.com/rust-lang/rfcs/pull/1758) ( > + **nox:** "I tried to be conservative for now given I don't have a use case for univariant unions and enums in FFI context." [eddyb_1]: https://github.com/rust-lang/rfcs/pull/1758#issuecomment-254872520 -> **eddyb:** "I found another important usecase: for `ManuallyDrop`, to be useful in arrays (i.e. small vector optimizations), it needs to have the same layout as `T` and AFAICT `#[repr(C)]` is not guaranteed to do the right thing" +> + **[eddyb][eddyb_1]:** "I found another important usecase: for `ManuallyDrop`, to be useful in arrays (i.e. small vector optimizations), it needs to have the same layout as `T` and AFAICT `#[repr(C)]` is not guaranteed to do the right thing" > **retep998:** "So we'd need to be able to specify `#[repr(transparent)]` on unions?" > + **eddyb:** "That's the only way to be sure AFAICT, yes." From 7250c02c909e70cf4fca7dd86e46d1f231ce45a0 Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Mon, 25 Feb 2019 06:51:17 -0800 Subject: [PATCH 15/26] Update text/0000-transparent-unions.md Co-Authored-By: mjbshaw --- text/0000-transparent-unions.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/text/0000-transparent-unions.md b/text/0000-transparent-unions.md index 56b004b6bc4..eca3b61e96c 100644 --- a/text/0000-transparent-unions.md +++ b/text/0000-transparent-unions.md @@ -79,7 +79,7 @@ See [the discussion on RFC #1758](https://github.com/rust-lang/rfcs/pull/1758) ( [eddyb_1]: https://github.com/rust-lang/rfcs/pull/1758#issuecomment-254872520 > + **[eddyb][eddyb_1]:** "I found another important usecase: for `ManuallyDrop`, to be useful in arrays (i.e. small vector optimizations), it needs to have the same layout as `T` and AFAICT `#[repr(C)]` is not guaranteed to do the right thing" -> **retep998:** "So we'd need to be able to specify `#[repr(transparent)]` on unions?" +> + **retep998:** "So we'd need to be able to specify `#[repr(transparent)]` on unions?" > + **eddyb:** "That's the only way to be sure AFAICT, yes." [joshtriplett_1]: https://github.com/rust-lang/rfcs/pull/1758#issuecomment-274670231 From bea3b9fbe2417a892d41f1383e41ee77d03b0c51 Mon Sep 17 00:00:00 2001 From: Michael Bradshaw Date: Mon, 25 Feb 2019 07:03:42 -0800 Subject: [PATCH 16/26] Revise mentions of transparent enums --- text/0000-transparent-unions.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/text/0000-transparent-unions.md b/text/0000-transparent-unions.md index eca3b61e96c..5ab36cab0b1 100644 --- a/text/0000-transparent-unions.md +++ b/text/0000-transparent-unions.md @@ -19,7 +19,7 @@ Making types like these `#[repr(transparent)]` would be useful in certain cases. - Protects against accidental violations of that intent (e.g., adding a new non-ZST field to a transparent union will result in a compiler error). - Makes a clear API guarantee that a `Wrapper` can be transmuted to a `T`. -Transparent `union`s are a nice complement to transparent `struct`s, and this RFC rounds out the `#[repr(transparent)]` feature. +Transparent `union`s are a nice complement to transparent `struct`s, and this RFC is a step towards rounding out the `#[repr(transparent)]` feature. # Guide-level explanation [guide-level-explanation]: #guide-level-explanation @@ -98,6 +98,6 @@ None (yet). # Future possibilities [future-possibilities]: #future-possibilities -Univariant `enum`s are ommitted from this RFC in an effort to keep the scope small and avoid unnecessary bikeshedding. A future RFC could explore `#[repr(transparent)]` on a univariant `enum`. +Univariant `enum`s are ommitted from this RFC in an effort to keep the scope small. A future RFC could explore `#[repr(transparent)]` on a univariant `enum`. If a `union` has multiple non-ZST fields, a future RFC could propose a way to choose the representation of that `union` ([example](https://internals.rust-lang.org/t/pre-rfc-transparent-unions/9441/6)). From 038829b3fd6c020c718aa3f7acb3e363d3bfbc2f Mon Sep 17 00:00:00 2001 From: Michael Bradshaw Date: Mon, 25 Feb 2019 07:45:57 -0800 Subject: [PATCH 17/26] Remove unnecessary "do nothing" alternative --- text/0000-transparent-unions.md | 2 -- 1 file changed, 2 deletions(-) diff --git a/text/0000-transparent-unions.md b/text/0000-transparent-unions.md index 5ab36cab0b1..e3be28d8df5 100644 --- a/text/0000-transparent-unions.md +++ b/text/0000-transparent-unions.md @@ -66,8 +66,6 @@ The logic controlling whether a `union` of type `U` may be `#[repr(transparent)] It would be nice to make `MaybeUninit` `#[repr(transparent)]`. This type is a `union`, and thus this RFC is required to allow making it transparent. -Of course, the standard "do nothing" alternative exists. Rust doesn't strictly *require* this feature. But it would benefit from this, so the "do nothing" alternative is undesirable. - # Prior art [prior-art]: #prior-art From c53247128e95975f60abbb2a72999e243d6f8aeb Mon Sep 17 00:00:00 2001 From: Michael Bradshaw Date: Mon, 25 Feb 2019 07:56:23 -0800 Subject: [PATCH 18/26] Clarify generic ZST transparent unions --- text/0000-transparent-unions.md | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/text/0000-transparent-unions.md b/text/0000-transparent-unions.md index e3be28d8df5..295be653fb5 100644 --- a/text/0000-transparent-unions.md +++ b/text/0000-transparent-unions.md @@ -37,7 +37,22 @@ union CustomUnion { } ``` -If the `union` is generic over `T` and has a field of type `T`, it may also be `#[repr(transparent)]` (even if `T` is a zero-sized type): +For consistency with transparent `struct`s, a `union` must have exactly one non-zero-sized field. If all fields are zero-sized, the `union` must not be `#[repr(transparent)]`: + +```rust +// This (non-transparent) is already valid in stable Rust: +pub union Good { + pub nothing: (), +} + +// Error: transparent union needs exactly one non-zero-sized field, but has 0 +#[repr(transparent)] +pub union Bad { + pub nothing: (), +} +``` + +The one exception is if the `union` is generic over `T` and has a field of type `T`, it may be `#[repr(transparent)]` even if `T` is a zero-sized type: ```rust // This union has the same representation as `T`. From 541934e725d36672a9d83ea0de5b8b0dcdeb9b55 Mon Sep 17 00:00:00 2001 From: Michael Bradshaw Date: Mon, 25 Feb 2019 08:00:35 -0800 Subject: [PATCH 19/26] Add missing "union" word --- text/0000-transparent-unions.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/text/0000-transparent-unions.md b/text/0000-transparent-unions.md index 295be653fb5..3ce24fa4671 100644 --- a/text/0000-transparent-unions.md +++ b/text/0000-transparent-unions.md @@ -40,7 +40,7 @@ union CustomUnion { For consistency with transparent `struct`s, a `union` must have exactly one non-zero-sized field. If all fields are zero-sized, the `union` must not be `#[repr(transparent)]`: ```rust -// This (non-transparent) is already valid in stable Rust: +// This (non-transparent) union is already valid in stable Rust: pub union Good { pub nothing: (), } From 8c92decdb6dfbc926f982118e874a79547bf28f8 Mon Sep 17 00:00:00 2001 From: Michael Bradshaw Date: Tue, 26 Feb 2019 09:01:08 -0800 Subject: [PATCH 20/26] Add some initial text about transparent enums --- text/0000-transparent-unions.md | 149 +++++++++++++++++++++++++++----- 1 file changed, 129 insertions(+), 20 deletions(-) diff --git a/text/0000-transparent-unions.md b/text/0000-transparent-unions.md index 3ce24fa4671..029974015de 100644 --- a/text/0000-transparent-unions.md +++ b/text/0000-transparent-unions.md @@ -1,4 +1,4 @@ -- Feature Name: transparent_unions +- Feature Name: transparent_enunions - Start Date: 2019-02-13 - RFC PR: - Rust Issue: @@ -6,53 +6,90 @@ # Summary [summary]: #summary -Allow `#[repr(transparent)]` on `union`s that have exactly one non-zero-sized field (just like `struct`s). +Allow `#[repr(transparent)]` on `union`s an univariant `enum`s that have exactly one non-zero-sized field (just like `struct`s). # Motivation [motivation]: #motivation -Some `union` types are thin newtype-style wrappers around another type, like `MaybeUninit` (and [once upon a time](https://doc.rust-lang.org/1.26.1/src/core/mem.rs.html#950), `ManuallyDrop`). This type is intended to be used in the same places as `T`, but without being `#[repr(transparent)]` the actual compatibility between it and `T` is left unspecified. +Some `union` types are thin newtype-style wrappers around another type, like `MaybeUninit` (and [once upon a time](https://doc.rust-lang.org/1.28.0/src/core/mem.rs.html#955), `ManuallyDrop`). This type is intended to be used in the same places as `T`, but without being `#[repr(transparent)]` the actual compatibility between it and `T` is left unspecified. -Making types like these `#[repr(transparent)]` would be useful in certain cases. For example, making a `union Wrapper` transparent: +Likewise, some `enum` types only have a single variant, and are similarly thin wrappers around another type. + +Making types like these `#[repr(transparent)]` would be useful in certain cases. For example, making the type `Wrapper` (which is a `union` or univariant `enum` with a single field of type `T`) transparent: - Clearly expresses the intent of the developer. -- Protects against accidental violations of that intent (e.g., adding a new non-ZST field to a transparent union will result in a compiler error). -- Makes a clear API guarantee that a `Wrapper` can be transmuted to a `T`. +- Protects against accidental violations of that intent (e.g., adding a new variant or non-ZST field will result in a compiler error). +- Makes a clear API guarantee that a `Wrapper` can be transmuted to a `T` or substituted for a `T` in an FFI function's signature. -Transparent `union`s are a nice complement to transparent `struct`s, and this RFC is a step towards rounding out the `#[repr(transparent)]` feature. +Transparent `union`s and univariant `enum`s are a nice complement to transparent `struct`s, and this RFC rounds out the `#[repr(transparent)]` feature. # Guide-level explanation [guide-level-explanation]: #guide-level-explanation -A `union` may be `#[repr(transparent)]` in exactly the same conditions in which a struct may be `#[repr(transparent)]`. Some concrete illustrations follow. +A `union` may be `#[repr(transparent)]` in exactly the same conditions in which a `struct` may be `#[repr(transparent)]`. An `enum` may be `#[repr(transparent)]` if it has exactly one variant, and that variant matches the same conditions which `struct` requires for transparency. Some concrete illustrations follow. A union may be `#[repr(transparent)]` if it has exactly one non-zero-sized field: ```rust +// This union has the same representation as `f32`. +#[repr(transparent)] +union SingleFieldUnion { + field: f32, +} + // This union has the same representation as `usize`. #[repr(transparent)] -union CustomUnion { +union MultiFieldUnion { field: usize, nothing: (), } + +// This enum has the same representation as `f32`. +#[repr(transparent)] +enum SingleFieldEnum { + Variant(f32) +} + +// This enum has the same representation as `usize`. +#[repr(transparent)] +enum MultiFieldEnum { + Variant { field: usize, nothing: () }, +} ``` -For consistency with transparent `struct`s, a `union` must have exactly one non-zero-sized field. If all fields are zero-sized, the `union` must not be `#[repr(transparent)]`: +For consistency with transparent `struct`s, `union`s and `enum`s must have exactly one non-zero-sized field. If all fields are zero-sized, the `union` or `enum` must not be `#[repr(transparent)]`: ```rust // This (non-transparent) union is already valid in stable Rust: -pub union Good { +pub union GoodUnion { pub nothing: (), } +// This (non-transparent) enum is already valid in stable Rust: +pub enum GoodEnum { + Nothing, +} + // Error: transparent union needs exactly one non-zero-sized field, but has 0 #[repr(transparent)] -pub union Bad { +pub union BadUnion { pub nothing: (), } + +// Error: transparent enum needs exactly one non-zero-sized field, but has 0 +#[repr(transparent)] +pub enum BadEnum { + Nothing(()), +} + +// Error: transparent enum needs exactly one non-zero-sized field, but has 0 +#[repr(transparent)] +pub enum BadEmptyEnum { + Nothing, +} ``` -The one exception is if the `union` is generic over `T` and has a field of type `T`, it may be `#[repr(transparent)]` even if `T` is a zero-sized type: +The one exception is if the `union` or `enum` is generic over `T` and has a field of type `T`, it may be `#[repr(transparent)]` even if `T` is a zero-sized type: ```rust // This union has the same representation as `T`. @@ -62,29 +99,103 @@ pub union GenericUnion { // Unions with non-`Copy` fields are unstable. pub nothing: (), } +// This enum has the same representation as `T`. +#[repr(transparent)] +pub enum GenericEnum { + Variant(T, ()), +} + // This is okay even though `()` is a zero-sized type. pub const THIS_IS_OKAY: GenericUnion<()> = GenericUnion { field: () }; +pub const THIS_IS_OKAY_TOO: GenericEnum<()> = GenericEnum::Variant((), ()); +``` + +Transparent `enum`s have the addtional restriction that they require exactly one variant: + +```rust +// Error: transparent enum needs exactly one variant, but has 0 +#[repr(transparent)] +pub enum TooFewVariants { +} + +// Error: transparent enum needs exactly one variant, but has 2 +#[repr(transparent)] +pub enum TooManyVariants { + First(usize), + Second(usize), +} ``` # Reference-level explanation [reference-level-explanation]: #reference-level-explanation -The logic controlling whether a `union` of type `U` may be `#[repr(transparent)]` should match the logic controlling whether a `struct` of type `S` may be `#[repr(transparent)]` (assuming `U` and `S` have the same generic parameters and fields). +The logic controlling whether a `union` of type `U` may be `#[repr(transparent)]` should match the logic controlling whether a `struct` of type `S` may be `#[repr(transparent)]` (assuming `U` and `S` have the same generic parameters and fields). An `enum` of type `E` may be `#[repr(transparent)]` if it has exactly one variant, and that variant follows all the rules and logic controlling whether a `struct` of type `S` may be `#[repr(transparent)]` (assuming `E` and `S` have the same generic parameters, and `E`'s variant and `S` have the same and fields). + +Like transarent `struct`s, a transparent `union` of type `U` and transparent `enum` of type `E` have the same layout, size, and ABI as their single non-ZST field. If they are generic over a type `T`, and all their fields are ZSTs except for exactly one field of type `T`, then they have the same layout and ABI as `T` (even if `T` is a ZST when monomorphized). + +Like transparent `struct`s, transparent `union`s and `enum`s are FFI-safe if and only if their underlying representation type is also FFI-safe. # Drawbacks [drawbacks]: #drawbacks -- `#[repr(transparent)]` on a `union` is of limited use. There are cases where it is useful, but they're not common and some users might unnecessarily apply `#[repr(transparent)]` to a `union`. +`#[repr(transparent)]` on a `union` or `enum` is of limited use. There are cases where it is useful, but they're not common and some users might unnecessarily apply `#[repr(transparent)]` to a type in a cargo-cult fashion. # Rationale and alternatives [alternatives]: #alternatives -It would be nice to make `MaybeUninit` `#[repr(transparent)]`. This type is a `union`, and thus this RFC is required to allow making it transparent. +It would be nice to make `MaybeUninit` `#[repr(transparent)]`. This type is a `union`, and thus this RFC is required to allow making it transparent. One example in which a transparent representation would be useful is for unused parameters in an FFI-function: + +```rust +#[repr(C)] +struct Context { + // Imagine there a few fields here, defined by an external C library. +} + +extern "C" fn log_event(message: core::ptr::NonNull, + context: core::mem::MaybeUninit) { + // Log the message here, but ignore the context since we don't need it. +} + +fn main() { + extern "C" { + fn set_log_handler(handler: extern "C" fn(core::ptr::NonNull, + Context)); + } + + // Set the log handler so the external C library can call log_event. + unsafe { + // Transmuting is safe since MaybeUninit and Context + // have the same ABI. + set_log_handler(core::mem::transmute(log_event as *const ())); + } + + // We can call it too. And since we don't care about the context and + // we're using MaybeUninit, we don't have to pay any extra cost for + // initializing something that's unused. + log_event(core::ptr::NonNull::new(b"Hello, world!\x00".as_ptr() as *mut _).unwrap(), + core::mem::MaybeUninit::uninitialized()); +} +``` + +It is also useful for consuming pointers to uninitialized memory: + +```rust +#[repr(C)] +struct Cryptor { + // Imagine there a few fields here, defined by an external C library. +} + +// This method may be called from C (or Rust!), and matches the C +// function signature: bool(Cryptor *cryptor) +pub extern "C" fn init_cryptor(cryptor: &mut core::mem::MaybeUninit) -> bool { + // Initialize the cryptor and return whether we succeeded +} +``` # Prior art [prior-art]: #prior-art -See [the discussion on RFC #1758](https://github.com/rust-lang/rfcs/pull/1758) (which introduced `#[repr(transparent)]`) for some discussion on applying the attribute to a `union`. A summary of the discussion: +See [the discussion on RFC #1758](https://github.com/rust-lang/rfcs/pull/1758) (which introduced `#[repr(transparent)]`) for some discussion on applying the attribute to a `union` or `enum`. A summary of the discussion: [nagisa_1]: https://github.com/rust-lang/rfcs/pull/1758#discussion_r80436621 > + **[nagisa][nagisa_1]:** "Why not univariant unions and enums?" @@ -101,7 +212,7 @@ See [the discussion on RFC #1758](https://github.com/rust-lang/rfcs/pull/1758) ( [pnkfelix_1]: https://github.com/rust-lang/rfcs/pull/1758#issuecomment-290757356 > + **[pnkfelix][pnkfelix_1]:** "However, I personally do not think we need to expand the scope of the feature. So I am okay with leaving it solely defined on `struct`, and leave `union`/`enum` to a follow-on RFC later. (Much the same with a hypothetical `newtype` feature.)" -In summary, many of the questions regarding `#[repr(transparent)]` on a `union` were the same as applying it to a multi-field `struct`. These questions have since been answered, so there should be no problems with applying those same answers to `union`. +In summary, many of the questions regarding `#[repr(transparent)]` on a `union` or `enum` were the same as applying it to a multi-field `struct`. These questions have since been answered, so there should be no problems with applying those same answers to `union` univariant `enum`. # Unresolved questions [unresolved]: #unresolved-questions @@ -111,6 +222,4 @@ None (yet). # Future possibilities [future-possibilities]: #future-possibilities -Univariant `enum`s are ommitted from this RFC in an effort to keep the scope small. A future RFC could explore `#[repr(transparent)]` on a univariant `enum`. - If a `union` has multiple non-ZST fields, a future RFC could propose a way to choose the representation of that `union` ([example](https://internals.rust-lang.org/t/pre-rfc-transparent-unions/9441/6)). From 18ecba911f893675a50fe577820d6e93de34c866 Mon Sep 17 00:00:00 2001 From: Michael Bradshaw Date: Tue, 26 Feb 2019 23:38:57 -0800 Subject: [PATCH 21/26] s/method/function/ --- text/0000-transparent-unions.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/text/0000-transparent-unions.md b/text/0000-transparent-unions.md index 029974015de..0e14249b53a 100644 --- a/text/0000-transparent-unions.md +++ b/text/0000-transparent-unions.md @@ -185,7 +185,7 @@ struct Cryptor { // Imagine there a few fields here, defined by an external C library. } -// This method may be called from C (or Rust!), and matches the C +// This function may be called from C (or Rust!), and matches the C // function signature: bool(Cryptor *cryptor) pub extern "C" fn init_cryptor(cryptor: &mut core::mem::MaybeUninit) -> bool { // Initialize the cryptor and return whether we succeeded From 26d47b7c765a91bd4a4cf0538dd78a1a6ef10885 Mon Sep 17 00:00:00 2001 From: Michael Bradshaw Date: Tue, 26 Feb 2019 23:40:30 -0800 Subject: [PATCH 22/26] Fix indentation --- text/0000-transparent-unions.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/text/0000-transparent-unions.md b/text/0000-transparent-unions.md index 0e14249b53a..a0225af12fb 100644 --- a/text/0000-transparent-unions.md +++ b/text/0000-transparent-unions.md @@ -159,7 +159,7 @@ extern "C" fn log_event(message: core::ptr::NonNull, fn main() { extern "C" { fn set_log_handler(handler: extern "C" fn(core::ptr::NonNull, - Context)); + Context)); } // Set the log handler so the external C library can call log_event. From 4c88177fa3145481047330aabfc9ecd01c2390e9 Mon Sep 17 00:00:00 2001 From: Michael Bradshaw Date: Sat, 9 Mar 2019 14:09:23 -0800 Subject: [PATCH 23/26] Document the behavior of nonnull-style optimization --- text/0000-transparent-unions.md | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/text/0000-transparent-unions.md b/text/0000-transparent-unions.md index a0225af12fb..7b07195f2cc 100644 --- a/text/0000-transparent-unions.md +++ b/text/0000-transparent-unions.md @@ -6,7 +6,7 @@ # Summary [summary]: #summary -Allow `#[repr(transparent)]` on `union`s an univariant `enum`s that have exactly one non-zero-sized field (just like `struct`s). +Allow `#[repr(transparent)]` on `union`s and univariant `enum`s that have exactly one non-zero-sized field (just like `struct`s). # Motivation [motivation]: #motivation @@ -135,6 +135,8 @@ Like transarent `struct`s, a transparent `union` of type `U` and transparent `en Like transparent `struct`s, transparent `union`s and `enum`s are FFI-safe if and only if their underlying representation type is also FFI-safe. +A `union` may not be eligible for the same nonnull-style optimizations that a `struct` or `union` (with the same fields) are eligible for. Adding `#[repr(transparent)]` to `union` does not change this. To give a more concrete example, it is unspecified whether `size_of::()` is equal to `size_of::>()`, where `T` is a `union` (regardless of whether it is transparent). The Rust compiler is free to perform this optimization if possible, but is not required to, and different compiler versions may differ in their application of these optimizations. + # Drawbacks [drawbacks]: #drawbacks @@ -217,7 +219,9 @@ In summary, many of the questions regarding `#[repr(transparent)]` on a `union` # Unresolved questions [unresolved]: #unresolved-questions -None (yet). +The role of `#[repr(transparent)]` in nonnull-style optimizations is not entirely clear. Specifically, it is unclear whether the user can rely on these optimizations to be performed when they make a type transparent. [Transparent `union`s somewhat complicate the matter](https://github.com/rust-lang/rfcs/pull/2645#issuecomment-470699497). General concensus seems to be that the compiler is free to decide where and when to perform nonnull-style optimizations on `union`s (regardless of whether or not the `union` is transaprent), and no guarantees are made to the user about when and if those optimizations will be applied. It is still an open question exactly what guarantees (if any) Rust makes about transparent `struct`s (and `enum`s) and nonnull-style optimizations. + +This RFC doesn't propose any changes to transparent `struct`s, and so does not strictly depend on this question being resolved. But since this RFC is attempting to round out the `#[repr(transparent)]` feature, it seems reasonable to dedicate some time to attempting to round out the guarantees about `#[repr(transparent)]` on `struct`s. # Future possibilities [future-possibilities]: #future-possibilities From ce8b5694ab0b98a43815f66c990dc01b0e0bde6d Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Sun, 10 Mar 2019 15:21:29 -0700 Subject: [PATCH 24/26] Fix typo: union -> enum Co-Authored-By: mjbshaw --- text/0000-transparent-unions.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/text/0000-transparent-unions.md b/text/0000-transparent-unions.md index 7b07195f2cc..447c8095f30 100644 --- a/text/0000-transparent-unions.md +++ b/text/0000-transparent-unions.md @@ -135,7 +135,7 @@ Like transarent `struct`s, a transparent `union` of type `U` and transparent `en Like transparent `struct`s, transparent `union`s and `enum`s are FFI-safe if and only if their underlying representation type is also FFI-safe. -A `union` may not be eligible for the same nonnull-style optimizations that a `struct` or `union` (with the same fields) are eligible for. Adding `#[repr(transparent)]` to `union` does not change this. To give a more concrete example, it is unspecified whether `size_of::()` is equal to `size_of::>()`, where `T` is a `union` (regardless of whether it is transparent). The Rust compiler is free to perform this optimization if possible, but is not required to, and different compiler versions may differ in their application of these optimizations. +A `union` may not be eligible for the same nonnull-style optimizations that a `struct` or `enum` (with the same fields) are eligible for. Adding `#[repr(transparent)]` to `union` does not change this. To give a more concrete example, it is unspecified whether `size_of::()` is equal to `size_of::>()`, where `T` is a `union` (regardless of whether it is transparent). The Rust compiler is free to perform this optimization if possible, but is not required to, and different compiler versions may differ in their application of these optimizations. # Drawbacks [drawbacks]: #drawbacks From 1488266b5228be6cac58042332ef45aec5cfd2e8 Mon Sep 17 00:00:00 2001 From: Michael Bradshaw Date: Sun, 17 Mar 2019 09:54:28 -0700 Subject: [PATCH 25/26] Mention that FFI can lead to UB if values are uninit --- text/0000-transparent-unions.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/text/0000-transparent-unions.md b/text/0000-transparent-unions.md index 7b07195f2cc..37b7c851c58 100644 --- a/text/0000-transparent-unions.md +++ b/text/0000-transparent-unions.md @@ -19,7 +19,7 @@ Making types like these `#[repr(transparent)]` would be useful in certain cases. - Clearly expresses the intent of the developer. - Protects against accidental violations of that intent (e.g., adding a new variant or non-ZST field will result in a compiler error). -- Makes a clear API guarantee that a `Wrapper` can be transmuted to a `T` or substituted for a `T` in an FFI function's signature. +- Makes a clear API guarantee that a `Wrapper` can be transmuted to a `T` or substituted for a `T` in an FFI function's signature (though users must be careful to not pass uninitialized values through FFI to code where uninitialized values are undefined behavior (like C and C++)). Transparent `union`s and univariant `enum`s are a nice complement to transparent `struct`s, and this RFC rounds out the `#[repr(transparent)]` feature. From bf093950aaab2673d39d3bcbc9844bd54ae54ecb Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Tue, 30 Apr 2019 12:04:44 +0200 Subject: [PATCH 26/26] RFC 2645 --- ...000-transparent-unions.md => 2645-transparent-unions.md} | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) rename text/{0000-transparent-unions.md => 2645-transparent-unions.md} (98%) diff --git a/text/0000-transparent-unions.md b/text/2645-transparent-unions.md similarity index 98% rename from text/0000-transparent-unions.md rename to text/2645-transparent-unions.md index 71320855244..aad5ae73d3c 100644 --- a/text/0000-transparent-unions.md +++ b/text/2645-transparent-unions.md @@ -1,7 +1,7 @@ -- Feature Name: transparent_enunions +- Feature Name: `transparent_enunions` - Start Date: 2019-02-13 -- RFC PR: -- Rust Issue: +- RFC PR: [rust-lang/rfcs#2645](https://github.com/rust-lang/rfcs/pull/2645) +- Rust Issue: [rust-lang/rust#60405](https://github.com/rust-lang/rust/issues/60405) # Summary [summary]: #summary