pub unsafe trait Opaque {
type Kind<'a>: ?Sized
where Self: 'a;
}
Expand description
An opaqueified self-referential struct “key”.
Safety
This is unsafe because there are a bunch of soundness invariants that need to be upheld. The following list is non-exhaustive:
Kind
must not have aDrop
impl in any “path” that may trace back to the original self-referential type, if saidDrop
impl can observe the self-referential type.- We assume
Kind
has the same layout for any'a
. This is true as of the time of writing this, and relies on Rust not having lifetime specialization.
It’s recommended to use the selfref::opaque!
macro instead, which
enforces these invariants. For example, this doesn’t compile:
ⓘ
use std::cell::Cell;
use selfref::opaque;
struct Foo<'a> {
foo: Cell<Option<&'a Foo<'a>>>,
}
impl<'a> Drop for Foo<'a> {
fn drop(&mut self) {
}
}
struct FooKey;
opaque! {
impl Opaque for FooKey {
type Kind<'a> = Foo<'a>;
}
}
But by removing the Drop
impl, it compiles:
use std::cell::Cell;
use selfref::opaque;
struct Foo<'a> {
foo: Cell<Option<&'a Foo<'a>>>,
}
//impl<'a> Drop for Foo<'a> {
// fn drop(&mut self) {
// }
//}
struct FooKey;
opaque! {
impl Opaque for FooKey {
type Kind<'a> = Foo<'a>;
}
}
Examples
use core::cell::Cell;
use selfref::Opaque;
struct Foo<'a> {
foo: Cell<Option<&'a Foo<'a>>>,
}
struct FooKey;
// SAFETY: Foo has no Drop impl and has the same layout for any 'a.
unsafe impl Opaque for FooKey {
type Kind<'a> = Foo<'a>;
}