rust-lang / rfcs

RFCs for changes to Rust
https://rust-lang.github.io/rfcs/
Apache License 2.0
5.96k stars 1.57k forks source link

RFC: Unsafe Set Enum Discriminants #3727

Open jamesmunns opened 2 weeks ago

jamesmunns commented 2 weeks ago

Summary

This RFC proposes a way to write the discriminant of an enum when building it "from scratch". This introduces two new library components, an unsafe set_discriminant function, and a discriminant_of! macro, which can be used with any enum, regardless of repr or any other details.

This RFC is a follow-on to the offset_of_enum feature, tracked by https://github.com/rust-lang/rust/issues/120141.

Rendered

jamesmunns commented 2 weeks ago

I've gotten feedback from @RalfJung in Zulip that it's probably more reasonable to have set_discriminant() take an *mut T rather than an &mut MaybeUninit<T>, and I think that is reasonable. I'll probably update this draft to switch these in a bit, if there are no counter-objections.

Edit: Changes made.

jamesmunns commented 1 week ago

Addressed all review comments so far. Link to the diff of changes since the initial version: https://github.com/rust-lang/rfcs/pull/3727/files/5c74b691972d36d30e27f253e8e2673d9930316f..eb486ef529eea98b7d2d9b0ffcd2254ac16a4ea0

coolreader18 commented 1 week ago

What's the current legality of initializing niche-optimized enums?

let mut x: Option<NonNull<u8>> = None;
(&raw mut x).cast::<NonNull<u8>>().write(NonNull::dangling()); // UB?

I suppose there are guarantees made about the layout of Option for FFI purposes, but this feels... sketchy (though miri says it's fine, including with more complex niches like char). That to say, unless these semantics are already defined, I feel like the section about calling set_discriminant on niche-optimized enums should be strengthened from "encouraged for explicitness" to "should"/"must". Maybe with an exception for Option/Result-like enums with a single niche at 0, since FFI-compatibility guarantees are already made for those, but I'd err on not allowing it if possible.

matthieu-m commented 1 week ago

I was thinking about the (possible) future alternative receivers for set_discriminant:

So, all in all, for now I see two alternatives I like: