How do I Create a Generic ZST From "Nothing"

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.

Ah, I figured it out.

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.

Pointers created by NonNull::dangling() are considered valid for zero-sized types. See the std::ptr module documentation.

5 Likes

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.

7 Likes

I thought I had tried that earlier, but I must have done something wrong. That indeed works, thanks!

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.