I'm writing wrapper code for an external C library, and I'm trying to convince the Rust compiler to enforce external lifetime restrictions that are not reflected in the Rust code itself. For example, one type of "opaque handle" can return a child handle that is only valid for the lifetime of the parent handle.
I experimented with std::marker::PhantomData
, but I couldn't convince the compiler to return the expected error.
In other words, I'd like the following block of code fail to compile:
struct Parent;
struct Child; // Note that there is no reference to the parent struct
impl Parent {
fn get_child( &self ) -> Child {
Child
}
}
// I'd like this to complain with "p does not live long enough"
fn test() -> Child {
let p = Parent;
p.get_child()
}
fn main() {
let c = test();
}
You had the right idea with PhantomData
. You add a lifetime parameter and a PhantomData
field to Child
. The PhantomData
generic parameter is what you want to emulate in the struct. In this case you want Child
to act as if it contains a &Parent
.
struct Child<'a> {
parent: PhantomData<&'a Parent>,
}
impl Parent {
fn get_child<'a>(&'a self) -> Child<'a> {
Child {
parent: PhantomData,
}
}
}
You also need to modify the test
function to have a generic argument, otherwise you don't see your requested doesn't live long enough
error,
because the Child needs a lifetime
error occurs first.
fn test<'a>() -> Child<'a> {
let p = Parent;
p.get_child()
}
Try it out in the Playground
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With