Description
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.
-
Discoverability - ie. You don't know you need it unless you already know about it.
If there's a situation when you should usePhantomData<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). -
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. -
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.