tgoop.com/random_rust_dev/209
Create:
Last Update:
Last Update:
Rust Tip для чернокнижников.PhantomData<T>
vs PhantomData<fn() -> T>
- не одно и то жеPhantomData<T>
указывает на семантику владения T
.PhantomData<fn() -> T>
- лишь на то что где-то будет использоваться этот T
.
Drop-check будет считать, что PhantomData<T>
может вызывать Drop
у T
, а PhantomData<fn() -> T>
- не будет.
Еще одно важное отличие это авто-трейты.PhantomData<T>
наследует их от T
, а вот PhantomData<fn() -> T>
нет.
Если T
будет !Send
или !Sync
, то в первом случае и ваш тип будет. А в случае функции - нет. Указатели на функции Send
, Sync
, Unpin
и прочие Freeze
независимо от типов аргументов и возвращаемого типа.
#[derive(Default)]
struct Foo<T>(PhantomData<T>);
#[derive(Default)]
struct Bar<T>(PhantomData<fn() -> T>);
let foo: Foo<Rc<u8>> = Foo::default();
let bar: Bar<Rc<u8>> = Bar::default();
std::thread::spawn(|| { drop(foo); }); // error: `Rc<u8>` cannot be sent between threads safely
std::thread::spawn(|| { drop(bar); }); // success!
Следует учитывать, что
PhantomData<fn(T)>
переворачивает ковариантность, так что его стоит использовать когда именно это и нужно.Удачной вам охоты на фантомные данные 👻
BY Random Rust Dev
Share with your friend now:
tgoop.com/random_rust_dev/209