-
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
Which patterns on union fields should be considered safe? #87520
Comments
In the initial HIR-based implementation any field read was considered unsafe as described in the RFC, whether it's done through a dot access or pattern destructuring. |
The Here by accessing |
So, indeed it always contains a valid value, and that is trivially correct -- no assumption/assertion needed. So, I don't see any parallel with UB-based optimizations here. |
@RalfJung |
Oh, I missed the So in a sense this is assuming that the union field satisfies the validity invariant without even looking at it... which does seem very dubious, yes. |
We discussed this in today's @rust-lang/lang meeting. Our initial reaction is that several of the examples currently considered safe should not be. (Some of them might potentially be in the future based on safe-transmute infrastructure, but they shouldn't be until we have that infrastructure. And some of them shouldn't ever be.) It seems OK to match a ZST without an unsafe block. But matching a non-ZST implies that the code inside the match arm will only run if the value matches, and if the compiler doesn't enforce that semantic then that seems inordinately confusing and error-prone. For a non-union, it's UB to put an invalid value into an enum, but for a union field, it's perfectly valid to write a value to one field that would be invalid for the type of another, as long as you never read a field that doesn't have a valid value for its type. I've started a Zulip thread to discuss the desired semantics further. |
Removing nomination as we are not doing much here at the moment. We do need to return to this topic! |
Moved from #85263 as the PR has been merged.
Summary of safety of pattern matching against Rust
union
sWritten by @Smittyvb, copied from #85263 (comment)
The unsafety checker is being to rewritten operate on the THIR instead of the MIR. As a part of that, I was implementing the unsafety rules for
union
s, and encountered some weird edge cases with the way the MIR unsafety checker handlesunion
s. In general, writing to a union is safe but reading isunsafe
. There are some cases where writing to a union is unsafe (such as when that might cause aDrop
call) that are not being implemented in this PR.Behavior specified by RFC 1444
Actual behavior
The MIR unsafety checker doesn't implement that behavior exactly. Due to the way that the MIR is constructed and optimized, some destructuring patterns against unions that that the RFC specifies to be unsafe are allowed.
The behavior of the MIR is mostly "irrefutable pattern matching against unions without any bindings after desugaring or-patterns is safe", with some extra weird behavior when niches are involved.
Here are some examples of what the MIR considers safe and unsafe. Here is the prelude for all of these examples:
Patterns considered safe
Patterns considered
unsafe
All of these require an
unsafe
block to compile.cc @Smittyvb @RalfJung @nikomatsakis
The text was updated successfully, but these errors were encountered: