-
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
Compilation error when matching reference to empty enum #131452
Comments
For more background (but partially outdated), also see this blog post by @nikomatsakis. Cc @rust-lang/opsem @rust-lang/types @Nadrieril My comment referred to the fact that the safety invariant is uncontroversial in your example, and sufficient to ensure that without unsafe code, nothing weird can happen -- in the specific case considered here, where the match is on a reference. There are related, more subtle cases though. For instance, what if Also for references, we may allow code to temporarily break the So my position on this heavily depends on whether the place we are matching on is "safe" or not. A place is "unsafe" if it involves For safe places, I am much less concerned. Maybe we want an opt-in lint that recommends never patterns to make this explicit. Maybe we want the lint to be warn-by-default when there is unsafe code nearby? But that seems hard and we don't have any other lint like this. There's also the question of irrefutable patterns exploiting empty types, such as |
Can't we make a distinction between unsafe and safe places and auto-scrutinise the discriminant of safe places? IOW declare that |
Yes, that is basically what I am suggesting. It is a new distinction between two kinds of places that I don't think we already have, so it's not an entirely trivial extension of the status quo.
|
Well, since |
+1 to most of what Ralf just said. I'm in favor of making the
As far as I remember we hadn't yet committed to that, at least in more complex cases like
We can suggest |
Note
Useful background links which have been shared in comments:
min_exhaustive_patterns
#119612 (comment) was stabilized a couple of months ago.Summary
I tried this code:
I expected to see this happen: This compiles successfully.
Instead, this happened: (E0004 compiler error, expandable below)
E0004 Compiler Error
Searching for "Rust E0004" links to docs that don't explain why references to uninhabited types need to be matched: https://doc.rust-lang.org/error_codes/E0004.html - you have to search for "references are always considered inhabited" which takes you to this issue from 2020 - more on this history in the Background section below.
Motivating example
This comes up commonly when creating macros which generate enums, e.g. a very simplified example (playground link):
Compiler Error
The fact that this doesn't work for empty enums is quite a gotcha, and I've seen this issue arise a few times as an edge case. In most cases, it wasn't caught until a few months after, when someone uses the macro to create an enum with no variants.
But why would we ever use such a macro to generate empty enums? Well this can fall out naturally when generating a hierarchy of enums, where some inner enums are empty, e.g.
Workarounds
Various workarounds include:
_ => unreachable!("Workaround for empty enums: references to uninhabited types are considered inhabited at present")
match *self
match *self {}
match self { ! }
in the body as suggested by Ralf which is non-stable.Background
This was previously raised in this issue: #78123 but was closed as "expected behaviour" - due to the fact that:
However, when I raised this as a motivating example in rust-lang/unsafe-code-guidelines#413 (comment), @RalfJung suggested I raise a new rustc issue for this, and that actually the
match
behaviour is independent of the UB semantics decision:Opinions
This was written before reading this blog post where the suggested "auto-never" rules capture these intuitions/opinions much better than I ever could.
After learning about the
!
pattern, I find it quite surprising that we require an explicit!
pattern and thatmatch self { }
doesn’t in itself capture the same intention asmatch self { ! }
.Ideally if we change the behaviour of this, I’d also expect the following to compile:
And not require a
Some(!)
pattern.Meta
rustc --version --verbose
:Also works on nightly.
The text was updated successfully, but these errors were encountered: