Description
Updated bug report follows (see bottom for original bug report)
This bug appears to have been filed in error but then spawned a very interesting conversation.
The question centers around how empty enums (e.g. enum Foo { }
, which has zero variants) which in principle cannot safely exist, interact with our casting operations (namely safe as
and unsafecast::transmute
).
Here is an some code that I wrote that summarizes the various scenarios that were described in the comments. Most of the scenarios do not compile (which is good). The fifth, sixth, and seventh all compile; their runtime behaviors vary, but most are acceptable. The only questionable thing @pnkfelix can see here is the behavior for the seventh example, cfg ex7
.
Code:
#[allow(dead_code)];
use std::cast;
enum Foo { }
struct Bar;
#[cfg(ex1)]
fn main() {
let i = Foo as int;
println!("i: {:?}", i);
}
#[cfg(ex2)]
fn main() {
fn f(f: Foo) -> int { f as int }
}
#[cfg(ex3)]
fn main() {
let i : Foo = unsafe { cast::transmute(3) };
println!("i: {:?}", i);
}
#[cfg(ex4)]
fn main() {
let b : Bar = Bar;
let i : Foo = b as Foo;
println!("b: {:?}", b);
println!("i: {:?}", i);
}
#[cfg(ex5)]
fn main() {
let b : Bar = Bar;
let i : Foo = unsafe { cast::transmute(b) };
println!("b: {:?}", b);
println!("i: {:?}", i);
}
#[cfg(ex6)]
fn main() {
let b : Bar = Bar;
let i : Foo = unsafe { cast::transmute(b) };
println!("b: {:?}", b);
match i {
}
}
#[cfg(ex7)]
fn main() {
let b : Bar = Bar;
let i : Foo = unsafe { cast::transmute(b) };
println!("b: {:?}", b);
match i {
_ => { println!("The impossible!"); }
}
}
Transcript of compile (+ runs when compilable):
% rustc --cfg ex1 /tmp/ee.rs && ./ee
/tmp/ee.rs:8:13: 8:16 error: unresolved name `Foo`.
/tmp/ee.rs:8 let i = Foo as int;
^~~
error: aborting due to previous error
% rustc --cfg ex2 /tmp/ee.rs && ./ee
/tmp/ee.rs:14:27: 14:35 error: non-scalar cast: `Foo` as `int`
/tmp/ee.rs:14 fn f(f: Foo) -> int { f as int }
^~~~~~~~
error: aborting due to previous error
% rustc --cfg ex3 /tmp/ee.rs && ./ee
/tmp/ee.rs:1:1: 1:1 error: transmute called on types with different sizes: int (64 bits) to Foo (0 bits)
/tmp/ee.rs:1 #[allow(dead_code)];
^
% rustc --cfg ex4 /tmp/ee.rs && ./ee
/tmp/ee.rs:26:19: 26:27 error: non-scalar cast: `Bar` as `Foo`
/tmp/ee.rs:26 let i : Foo = b as Foo;
^~~~~~~~
error: aborting due to previous error
% rustc --cfg ex5 /tmp/ee.rs && ./ee
b: Bar
task '<main>' failed at 'enum value matched no variant', /Users/fklock/Dev/Mozilla/rust.git/src/libstd/repr.rs:559
% rustc --cfg ex6 /tmp/ee.rs && ./ee
b: Bar
task '<main>' failed at 'scrutinizing value that can't exist', /tmp/ee.rs:44
% rustc --cfg ex7 /tmp/ee.rs && ./ee
b: Bar
The impossible!
%
Original bug report follows:
Something like this works:
enum Foo { }
let i = Foo as int;
Doesn't make any sense.