Open
Description
Imagine a function like this that initializes an object through an external C API:
impl Timer {
pub fn init<'timer, 'opaque: 'timer, T>(self: Pin<&'timer mut Self>, f: fn(&T), opaque: &'opaque T) {
// call to C API
}
}
When converting this to use PinInit, it is not possible to confirm that the opaque value outlives the timer:
impl Timer {
pub fn init<T>(f: fn(&T), opaque: *mut T) -> impl PinInit<Self> {
pin_init_from_closure(move |slot: *mut Timer|
// call to C API
}
}
}
If PinInit received for example an &'a MaybeUninit<T>
, it would be possible to do add the constraint to the signature:
impl Timer {
pub fn init<'timer, 'opaque: 'timer, T: 'opaque>(f: fn(&T), opaque: &'opaque mut T)
-> impl PinInit<'timer, Self> {
unsafe {
pin_init_from_closure(move |slot: &'timer mut MaybeUninit<Timer>| {
// call to C API
})
}
}
}
MaybeUninit
is not suitable (for example it does not support unsized types); but it should be possible to wrap a *mut T
and constrain it to a generic lifetime:
pub struct ToInit<'a, T>(*mut T, PhantomData<&'a mut MaybeUninit<T>>);
impl Timer {
pub fn init<'timer, 'opaque: 'timer, T: 'opaque>(f: fn(&T), opaque: ToInit<'opaque, T>)
-> impl PinInit<'timer, Self> {
unsafe {
pin_init_from_closure(move |slot: ToInit<'timer, Timer>| {
// call to C API
})
}
}
}
This arises in QEMU, which implements callbacks using (roughly) function pointers instead of traits like Linux.
Metadata
Metadata
Assignees
Labels
No labels