Background: I'm writing a garbage collector which needs a sentinel value for "dead" pointers. In order to implement CoerceUnsized, I can't use Option<NonNull<T> to represent my underlying raw pointer, so I use *const T instead. However, if T is ?Sized, it's impossible to create a null pointer to T using std::ptr::null(). In particular, all I really care about is whether my null pointer returns true when is_null() is called on it.
Is there a way to create one in a more roundabout way?
My first guess was to do something like this:
unsafe fn make_my_null_pointer<T: ?Sized>() {
let ptr: *const T = MaybeUninit::zeroed().assume_init();
}
However, this is wildly unsafe. Is there a method which is more blessed to do so?
Would it be possible to create a null pointer from an existing valid pointer, though? In my case, I can use an existing pointer with a valid vtable - can I construct one with an address part of null and a vtable of the correct variety?
Here's the main issue. I can't implement CoerceUnsized on a pointer type containing Option<NonNull<T>>, unless there's some method to do so that I haven't heard of.
The layout of *const dyn Trait is not guaranteed, so you still need some other way of deconstructing and constructing. Those are part of the ptr_metadata feature:
*const MaybeUnsized as *const () for a pointer to the data if you need it (you don't for NULL)
Well, pondering this a bit, I guess you could create a fallible version...
if your pointer is thin (one usize), just use NULL (via transmute_copy probably)
otherwise, check that your wide pointer is two usize
Else bail
transmute it to [usize; 2]
compare against *const _ as *const () as usize to see if it's unambiguous which of the two array entries is the metadata
Bail if ambiguous
set the data half to 0
transmute it back
Didn't try it myself but probably this needs transmute_copy and there are some other assumptions, like pointer metadata is always initialized and thus valid to read for the sake of comparison.