Does raw pointers have a lifetime?
If not, how the compiler can deduce a life time from it
The code below, test has a signature like that:
pub fn test<'a, T>(ptr: *mut T) -> OutRef<'a, T>
It does has a 'a lifetime; but when I call it, I use
// fn test2<T>(x: &mut MaybeUninit<T>) -> *mut T
let ptr = test2(self);
test(ptr)
How ever, the returned OutRef<'a, T> does remembers the correct lifetime,
fn as_out_ref(self: &'_ mut MaybeUninit<T>)
-> OutRef<'_, T>
{
#[allow(unused_unsafe)]
unsafe {
let ptr = test2(self);//self.as_mut_ptr();
test(ptr)
}
}
let mut x = MaybeUninit::<i32>::uninit();
let at_x = x.as_out_ref();
drop(x);
println!("{:?}", *at_x.ptr);
will not be compiled.
But, the code
let mut n: String = String::from("123");
let np = lib::test(&mut n as *mut String);
drop(n);
unsafe {
println!("{:?}", *np.ptr);
}
does passes compiling, and
pub fn test3<'a, T>(ptr: *mut T, life: &'a String) -> OutRef<'a, T> {
OutRef {
ptr: ptr,
_lifetime: PhantomData,
}
}
let mut n: String = String::from("123");
let np = lib::test3(&mut n as *mut String, &n);
drop(n);
unsafe {
println!("{:?}", *np.ptr);
}
passes too, I don't know why, can anybody help?
Full code:
mod lib {
use ::core::{
marker::PhantomData,
mem::MaybeUninit,
};
// Invariant: ptr points to a valid `MaybeUninit<T>`
#[derive(Debug)]
pub
struct OutRef<'a, T : 'a> {
pub ptr: *mut T,
_lifetime: PhantomData<&'a ()>,
}
impl<'a, T : 'a> OutRef<'a, T> {
pub
fn write (self: OutRef<'a, T>, value: T)
-> &'a mut T
{
unsafe {
// # Safety
//
// - this is `MaybeUninit<T>::write`
self.ptr.write(value);
&mut *self.ptr
}
}
}
pub
trait MaybeUninitExt<T> {
fn as_out_ref (self: &'_ mut Self)
-> OutRef<'_, T>
;
}
pub fn test<'a, T>(ptr: *mut T) -> OutRef<'a, T> {
OutRef {
ptr: ptr,
_lifetime: PhantomData,
}
}
fn test2<T>(x: &mut MaybeUninit<T>) -> *mut T {
let p = x.as_mut_ptr();
p
}
impl<T : Copy> MaybeUninitExt<T> for MaybeUninit<T> {
fn as_out_ref(self: &'_ mut MaybeUninit<T>)
-> OutRef<'_, T>
{
#[allow(unused_unsafe)]
unsafe {
let ptr = test2(self);//self.as_mut_ptr();
test(ptr)
// # Safety
//
// - Respects the invariant
// OutRef {
// ptr: self.as_mut_ptr(),
// _lifetime: PhantomData,
// }
}
}
}
impl<'a, T : 'a> From<&'a mut T> for OutRef<'a, T> {
#[inline]
fn from (p: &'a mut T)
-> OutRef<'a, T>
{
#[allow(unused_unsafe)]
unsafe {
// # Safety
//
// - Respects the invariant, since something
// init can be seen as maybeuninit
OutRef {
ptr: p,
_lifetime: PhantomData,
}
}
}
}
}
use lib::{
MaybeUninitExt,
OutRef,
};
use ::core::mem::MaybeUninit;
fn write_ft (at_x: OutRef<'_, i32>)
-> &'_ mut i32
{
at_x.write(42)
}
fn main ()
{
let mut n: String = String::from("123");
let np = lib::test(&mut n as *mut String);
drop(n);
unsafe {
println!("{:?}", *np.ptr);
}
let mut x = MaybeUninit::<i32>::uninit();
let at_x = x.as_out_ref();
drop(x);
println!("{:?}", *at_x.ptr);
// let x: &mut i32 = write_ft(at_x);
// assert_eq!(
// dbg!(*x),
// 42,
// );
}