PhantomData type usage in rust

耗尽温柔 提交于 2019-12-24 00:42:12

问题


I was going through some rust source code and I found a data type called PhantomData. I was going through the rust documentation and searched through the internet a lot. However, I couldn't understand the actual use of this data type with rust. If possible, could somebody please explain me this in simple manner?

pub struct GPIOD {
   _marker: PhantomData<*const ()>,
}

回答1:


The PhantomData struct is meant to signal to the compiler that a type or lifetime is being used in some way that is transparent to the compiler.

To quote the docs:

Adding a PhantomData field to your type tells the compiler that your type acts as though it stores a value of type T, even though it doesn't really. This information is used when computing certain safety properties.

For example, if we look at the iterator type for a slice [T]: std::slice::Iter<'a, T> and its declaration using the src button we'll see that it's actually declared as such:

struct Iter<'a, T: 'a> {
    start: *const T,
    end: *const T,
    _phantom: PhantomData<&'a T>,
}

std makes frequent use of pointer arithmetic to make optimizations more readily available (Although that is not to endorse the usage of pointer arithmetic in user code). In this case, we need to assure ourselves that the data that is pointed to by the two raw pointers (Which carry no lifetimes) outlive the struct, so we keep a PhantomData<&'a T> to tell the compiler to act like as if Iter owned a &'a T therefore enforcing lifetime rules for it.




回答2:


In addition to the other answer, I'd like to add an example. As said in the other answer, PhantomData allows to add an arbitrary lifetime dependence between 2 structure.

Suppose that you have a struct that manages a logging tool with a message receiver, and a struct that represents an actual logger that sends messages to the manager. Although the logger does not directly depends on the manager, the manager must outlive the logger to prevent send errors.

The naive code does not create any dependency between the 2 structs:

struct LogManager {
    // ...
}

impl LogManager {
    fn logger(&self) -> Logger {
        // returns a fresh `Logger` that holds no reference to `LogManager`...
    }
}

struct Logger {
    // ...
}

Now, if the Logger holds a phantom reference, we can force a dependency between the 2 structs:

struct Logger<'a> {
    // ...
    _marker: PhantomData<'a ()>,
}

and in the impl block:

impl LogManager {
    fn logger(&self) -> Logger {
        Logger {
            // ...
            // Here, `Logger` will have a lifetime dependent of the `LogManager`'s
            // lifetime due to `PhantomData`:
            _marker: PhantomData,
        }
    }
}

Now, no instance of Logger can outlive the LogManager where it comes from.



来源:https://stackoverflow.com/questions/57844962/phantomdata-type-usage-in-rust

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!