I'm building a simple heterogeneous type map and I'm having an issue when I need to load a Zero Sized Type ( ZST ).
So far it's been simple, when I insert data, I make an allocation, get the pointer that was allocated, write the data to that pointer, and then later I'm able to retrieve the data from the pointer.
With ZSTs, though it's weird. I can't allocate, so instead I just store a null pointer. Then when I need to retrieve the type, I have a generic type parameter T for the type I need to cast the data to, and I therefore can tell that T has a Layout with a size 0.
But since I never actually created a pointer to a T, I need to create a reference to a T out of thin air.
I don't know how to do that, and even once I figure that out, I'm not sure if I'll run into lifetime issues, because I can't return a reference to a T that I created in the function that is being called, because that T would get dropped when the function returns.
I was able to put it in a Box and then leak it, and get a pointer to the leaked Box. Roughly:
fn insert<T>(data: T) {
let ptr = if Layout::of::<T>().size() == 0 {
let b = Box::new(data);
Box::leak(b) as *mut T as *mut u8
} else {
// Allocate and write
};
}
I guess that didn't do what I thought I needed to do, but that was better because I can treat the pointer the same way I do other pointers.
And it happens that Box::leak() will in fact return a dangling pointer, because Box::new() doesn't allocate anything for a ZST.
So, if your non-ZST path uses Box::leak(), then just use it for ZSTs too. But if you have special ZST handling, then NonNull::dangling() is a more direct way to get a valid pointer.