NoAddr wrapper for pointers with an irrelevant address

For historical reasons, the address of a zero-sized type is often significant. However, in many cases, the address of a reference is completely irrelevant, and thus if the reference is to a zero-sized type, it could be omitted from the type with no consequence.

This would be especially useful for when references to ZST marker types are used to make the borrow checker enforce certain invariants, such as synchronizing accesses to global variables.

This would make generic datastructures that sometimes contain ZSTs significantly more efficient, as they could fully omit those fields in those cases.

NoAddr<T> would have method to retrieve a reference to the inner type, and if the inner type was some form of pointer to a zst, it would simply return a reference created via ptr::dangling. this is sound because zero-sized reads and writes are always valid.

it would also impl Deref and DerefMut depending on what the inner pointer impls.

unlike regular pointers and references, PartialEq and PartialOrd would not be implemented on them.

common useage would be stuff like NoAddr<Box<T>>, NoAddr<&T>, and NoAddr<&mut T>.

implementing this in regular code would require a trait that all ZSTs impl, as well as something like specialization or negative bounds (then an associated type could be used to define the inner type of the NoAddr struct).

How would this differentiate Box (or Vec) from for example, Pin<Box<T>>. Where the pinned Box's address is usually sensitive, or my own special MyBox<T>, which uses pointer tagging, so NoAddr<MyBox<T>> should be the same as MyBox<T> even if the T is a ZST.

Edit: and does this recurse into fields (that would be a hazard since a private field Box could be address sensitive). If not, how would NoAddr know which pointer to erase.

I like this idea, but there are a lot of unanswered questions

i think probably this would need to be backed by some sort of (sealed?) trait in the standard library, similar to how NonZero and other such wrappers work

1 Like

Wouldn't that be a semver hazard though? If I have a ZST that can only be created through some private mechanism, if there's an implicit ZST trait that leaks that it is a ZST, can I ever add a non-ZST field to it (say, for debug tracing)?

the ZST trait could be perma-unstable and only used internally in the standard library.