Skip to content

How to use PhantomData? #271

Open
Open
@panstromek

Description

@panstromek

I am writing this here, because I feel like it belongs to unsafe-code-guidelines, I hope this is the right place to discuss it. It's more of a suggestion to put it in the guidelines than a real question.

Currently I see few problems with this concept.

  1. Discoverability - ie. You don't know you need it unless you already know about it.
    If there's a situation when you should use PhantomData<T> to signal that you own an allocation, compiler doesn't give you any warning, and there's very little information online about it. There's a great chance a lot of users never even heard about it, (at least I think).

  2. It's not exactly clear what it does.
    Docs + Nomicon say that it's needed for variance, which is more or less clear, but then it also says it's needed for drop check, which is not very well explained. Nomicon has a few paragraphs about that, but it's still unclear what exactly goes wrong if you don't specify PhantomData - it just "just leads to unsoundness" but why? I guess I'm just looking for a concrete example here.

  3. It's unclear if you actually need it and how to use it
    For example Docs and Nomicon only talk about use cases with generic types, so it's unclear if you should use it even for things that are not generic.

One specific problem I had is some simple wrapper around opened file from libc:

struct MyFile {
    file: *mut libc::FILE
}

There's a lot of questions about this code.
Is PhantomData<FILE> needed here?
Even when the struct is not generic?
Does it matter when this type is from libc?
libc::FILE doesn't have a destructor, does it matter at all here?
This struct has a Drop impl that calls fclose . If I need PhantomData for drop check, why? Why is Drop impl not enough?
What goes wrong if I don't have PhantomData<FILE> field?

I think clarifying this example specifically would be great, because something like this will probably be the first experience with unsafe code for many users, given that a lot of Rust adopters have to interface with existing C/C++ code.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions