-
Notifications
You must be signed in to change notification settings - Fork 12.9k
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
Can't as
cast Void to usize
#75647
Comments
I think for zero-variant enums it fails mostly as an oversight. This doesn't even have to generate any MIR as it is unreachable code anyway. Nominating for lang team discussion. |
From the head comment at rust/src/librustc_typeck/check/cast.rs Line 10 in 7189ca6
as cast to anything, desugaring to match x {} .
|
No, enum casts have nothing to do with C-style enums. This works: pub enum MirPhase {
Build = 0,
Const = 1,
Validated = 2,
}
fn main() {
let _val = MirPhase::Build as usize;
} |
Oh, the comment says "C-like". That's not the same as |
Here's the offending check: rust/src/librustc_middle/ty/mod.rs Lines 2497 to 2499 in 668ef72
It seems that the "payload-free" check is not just "all variants have no data" but also "it is not empty". I would hesitate to change this definition because it's likely to affect C-like enum handling elsewhere, but maybe |
I'd argue a no-variant enum is payload-free. But all uses of that function should be carefully checked. Adding a new case to |
These were historically known as "C-like" enums, and <source>:1:12: error: expected unqualified-id at end of input
1 | enum Void {}
| ^
Compiler returned: 1
Can you maybe elaborate more on this? |
Sure, C might not permit them, but I don't see how that's a reason to disallow |
I mean, what value does |
It's not actually reachable, so it could just typecheck without actually ever needing to produce a value. |
@lzutao It can compile the same way as |
Currently, the compiler marks
Unreachable is unsafe, does it mean that |
@lzutao This uses no unsafe code: enum Void { }
fn void_as_usize(x: Void) -> usize {
match x {}
} Here the code after the match statement (if there was any) would be unreachable, and this requires no unsafe code. Basically EDIT: Your linked example is pattern matching on an |
Thanks, I got that part now. But the question raised by Scott still remain: What is the concrete example of macros that have use cases for Also, |
The actual macro where this came up was a safe wrapper that declares an int-like enum and an array indexed by the enum. Roughly, it creates a type It is possible to work around this issue by explicitly checking for this case, but I don't really see a reason for it not to work in the first place.
Any operation on Void is unreachable. That means that the compiler can do whatever it wants to for codegen here because it doesn't matter, the function is not callable. But from a typing point of view, I think that |
It's no surprise that macros run into this -- this happens any time that we have special exceptions. " Not sure what the next step here is -- probably an RFC? This is a language extension after all. |
Discussed in the @rust-lang/lang meeting today:
|
I have opened #76199 to fix this issue. |
…tsakis Permit uninhabited enums to cast into ints This essentially reverts part of rust-lang#6204; it is unclear why that [commit](rust-lang@c0f587d) was introduced, and I suspect no one remembers. The changed code was only called from casting checks and appears to not affect any callers of that code (other than permitting this one case). Fixes rust-lang#75647.
As reported on Zulip: https://rust-lang.zulipchat.com/#narrow/stream/122651-general/topic/void.20as.20usize
This works for simple enums with one or more variants, but for zero it fails, possibly due to interaction with
#[repr(C)]
. This kind of code can come up in macro code.cc @RalfJung
The text was updated successfully, but these errors were encountered: