Contravariant data pointer

⚓ Rust    📅 2025-11-01    👤 surdeus    👁️ 8      

surdeus

Info

This post is auto-generated from RSS feed The Rust Programming Language Forum - Latest topics. Source: Contravariant data pointer

I've looked at thread 124650, and while a write-only safe reference will have more limitations than uses, a pointer type that is contravariant with respect to its pointee type may be a different matter. NonNull being covariant is sound because most of its public api is unsafe right?

Currently, I use this:

use core::{ptr::NonNull, marker::PhantomData};
#[repr(transparent)]
struct ConNull<T>(NonNull<()>, PhantomData<fn(T)>);

But as you can clearly see, this type has no idea how to handle the wide pointer metadata, so it accepts only Sized types. Why write this?

One situation where this pointer type is useful is when creating unidirectional channel types, e.g. futures::channel::{mpsc, oneshot}: the sending end (say, Tx<T> where T is the message type) is contravariant with respect to T, but because most Tx implementations point to the inner allocation with non-opaque pointers, Tx often ended up invariant.

Sending should be contravariant because for S being a subtype of T, sending S through Tx<T> is well-defined but T through Tx<S> isn't.

That's how I convinced myself to need this, anyway. Are there more idiomatic ways to implement this kind of pointer?

1 post - 1 participant

Read full topic

🏷️ Rust_feed