Code style Q: how to name a field holding PhantomData?

I am writing the following code:

    #[derive(Default, Debug)]
    pub struct OnceBox<T> {
        inner: OnceNonZeroUsize,
        phantom: PhantomData<T>,
    }

would would be the best name for phantom field? phantom is too long to my taste :frowning:

In the standard library, I see phantom, marker, _marker, and _p.

1 Like

Yeah, this is exactly what I am asking -- my own code demonstrates similar richness, and I spend a second thinking about this every single time...

I wanted to suggest :ghost:, but that's not valid even with #![feature(non_ascii_idents)].

11 Likes

Hm, actually, ghost might not be as bad as a name..

1 Like

ghost, fake, mock, void, null, pseudo, bogus, shadow, unused, blank, mirage

1 Like

spoon, cake, mcguffin, lacuna, palimpsest, skeuomorph

4 Likes

cake wins.

Everybody knows the cake is a lie.

6 Likes

If this is a personal choice rather than one that requires team agreement, I would just go with _p in contexts where the leading _ is acceptable.

How about mark? It's shorter.

Since PhantomDatas only appear out of necessity, and since code > documentation, I've personally found that naming that field with a short description of the role of the PhantomData field to "fit" the code quite neatly: the code looks more readable, even if it's at the cost of a longer field name.

Examples

struct OnceBox<T> {
    inner: OnceNonZeroUsize,
    _owns_T: PhantomData<T>,
}
/// Uses thread-locals in some of its methods.
struct Foo {
    // …
    _thread_local: PhantomData<*mut ()>,
}
/// Like `&'a T`, but with the provenance of the initial pointer it
/// was created with (_e.g._, to cast this "back" to a reference to
/// a _bigger_ `T`).
struct RefWithProvenance<'lt, T> {
    ptr: ptr::NonNull<T>,
    _lt: PhantomData<&'lt T>,
    // or:
    _borrows: PhantomData<&'lt T>,
}
struct MyDynFn<T> {
    // …
    _contravariant: PhantomData<fn(T)>,
}
  • funnily enough, and a proof that we can never be "too explicit" about PhantomDatas, is that, had the PhantomData field been named _phantom or _p, then it is hard to tell if somebody writing:

    struct MyDynFn<T> {
        // …
        _p: PhantomData<dyn Fn(T)>,
    }
    

    has opted out of contravariance on purpose (vs. using fn(T)).


TL,DR

Let's give the PhantomData fields meaningful names :pray:

10 Likes

This is one place where I can see _ being useful as a pseudo-identifier for struct and enum variant fields, e.g.

struct Foo {
    _: PhantomData<Bar>
} 

It would also be consistent with the same feature already being available for locals and fn parameters.

However, I think it should have different semantics in that the value should not immediately be dropped, for the reason that if it were, what would be left of the containing value of type Foo is a partially-moved value.

Or we could go the radical other extreme and go with @Yandros's proposal :slightly_smiling_face:

When I'm using PhantomData for things like Send + Sync or lifetimes I'll usually call it something like __not_send so people know it's not meant to be used directly and has a very specific purpose.

1 Like

All joking aside, I agree completely. Name things directly according to what you are hoping to accomplish. More why than what.

4 Likes

I just use __ for such fields :slight_smile:

I often use _boo to spook the type system into doing what I want.

3 Likes