I was trying to implement an unsized type and realized that Option<T> requires T: Sized. Thinking this was some arbitrary requirement, I tried implementing my own Option and realized that one simply can't unsize enums. Specifically, I was trying to do the following:
use std::any::Any;
struct Struct<A: ?Sized + Any>(A);
enum Enum<A: ?Sized + Any> {
Some(A),
None,
}
fn main() {
// Works.
let s = Struct(0);
let s = &s as &Struct<Any>;
// Doesn't work (non-scalar cast).
let e = Enum::Some(0);
let e = &e as &Enum<Any>;
}
If you want to store something that does not implement size, you have to store externally in the heap because we do not know its actual size. So you either know its size in which case you can store it in the collection, or you do not, in which case you need to store it in the heap.
No. Everything I want to store on the stack is sized (&Struct<Any>, &Enum<Any>, Struct<i32>, Enum<i32>). I'm just trying to cast a &Enum<i32> to an &Enum<Any>.
The code I posted above does work. I'm just wondering why I can't do this with enums.
These two statements seem to contradict. You are saying all the things you want to store are sized? Well then they will implement Sized and therefore the Sized requirement for the enum is no problem?
You can't put DSTs on the stack but you can make references to sized values on the stack and cast these to references to DSTs.
use std::fmt::Debug;
fn debug(value: &Debug) {
// `Debug` is a DST.
// `&Debug` is Sized.
println!("{:?}", value);
}
fn main() {
// These are Sized.
let a = 0i32;
let b = 0i64;
debug(&a as &Debug);
debug(&b as &Debug);
}