Don't require unsafe for struct and array patterns against union fields - #161771
Don't require unsafe for struct and array patterns against union fields#161771Jules-Bertholet wants to merge 6 commits into
unsafe for struct and array patterns against union fields#161771Conversation
|
r? @folkertdev rustbot has assigned @folkertdev. Use Why was this reviewer chosen?The reviewer was selected based on:
|
These patterns don't access the union directly, only their subpatterns do. So there is no need to require `unsafe`.
f7e9593 to
2c56306
Compare
unsafe for PatKind::Leaf against union fieldsunsafe for struct and array patterns against union fields
|
You should actually nominate for T-lang if you want them to look at this. |
|
Worth noting, for our discussion, that the example in the PR description compiles today, i.e., ahead of this PR landing: union Foo {
field: u8,
}
fn bar(foo: Foo) {
match foo {
Foo { field: _ } => (), // OK!
}
}What fails are things like this: union Foo {
field: (u8,),
}
fn bar(foo: Foo) {
match foo {
Foo { field: (..) } => (), // ERROR: Needs `unsafe`.
}
} |
|
Thanks for the correction, I edited the OP |
|
Just checking: we still Assuming we do, then I agree that allowing these categories of irrefutable patterns in union patterns makes sense 👍 |
| | PatKind::Deref { .. } | ||
| | PatKind::DerefPattern { .. } | ||
| | PatKind::Range { .. } | ||
| | PatKind::Slice { .. } |
There was a problem hiding this comment.
Pondering: [..] is also an irrefutable pattern but isn't updated here (right?)
I don't know if it's possible, but could this whole match change to being about irrefutable pattern instead, or something? If we have to whack-a-mole a whole bunch of things here, that makes me less "oh yeah let's do it" than I was before, since I don't know why people would write this.
(Notably if you're using a pat_param from a macro it'd actually be easier for it to always be unsafe so you don't need to suppress the unneeded-unsafe if they pass something simple.)
Part of why we said that unsafeck is on THIR is that it's more of a lexical check than a flow-sensitive one, so being a bit more unsafe than strictly necessary is generally fine if it's something that the human description of the thing is something that people would say "it's unsafe to do that".
There was a problem hiding this comment.
Pondering:
[..]is also an irrefutable pattern but isn't updated here (right?)
Yes it is. There's even a test.
could this whole match change to being about irrefutable pattern instead
No, irrefutability isn't sufficient. x is an irrefutable pattern but still needs to be unsafe; & _ probably should be as well. Nor is it even necessary; the unstable guard patterns are refutable, but shouldn't require unsafe.
What we care about is that the pattern does not perform a read/assert validity.
|
We talked about this in today's lang meeting. This change seems fine individually, but along the lines of @scottmcm's comments above, I'd like to do it in a way that preserves (or improves) the overall consistency and simplicity of the language. One way to evaluate that would be to review a reference PR for the change. @Jules-Bertholet would you be willing to draft one for us to review? |
|
@tmandry Here you go: rust-lang/reference#2350 While drafting, I noticed one issue: this change makes #162213 slightly worse, because now whether a const pattern requires |
| self.inside_adt = old_inside_adt; | ||
| } | ||
| _ => { | ||
| visit::walk_pat(self, pat); |
There was a problem hiding this comment.
This doesn't correctly handle guard patterns. Currently, it flags any patterns inside a guard pattern condition inside a union pattern as also accessing the union. This is incorrect. For example, the following code doesn't compile, even with this PR, but I think it should:
#![feature(guard_patterns)]
#![expect(incomplete_features)]
union MyUnion {
thing: i32,
}
fn foo(x: MyUnion) {
match x {
MyUnion {
thing: (_ if matches!(1, 1)),
} => {}
}
}The in_union_destructure flag needs to reset to false when walking the guard pattern condition.
@Jules-Bertholet What do you mean here? From my testing, it seems that the potential semver hazard is just that an "implicit const" defined by a unit struct can be safely matched in a union with this PR, while an actual const item cannot. |
These patterns don't access the union directly, only their subpatterns do. So there is no need to require
unsafe.For example, the following now compiles:
Also removes the
unsaferequirement for the unstable guard patterns (#129967) in this position.@rustbot label T-lang needs-fcp A-patterns F-guard_patterns I-lang-nominated