struct OutRef<'a, T : 'a> {
ptr: ptr::NonNull<T>,
_lifetime: PhantomData<&'a ()>,
}
impl<'a, T : 'a> OutRef<'a, T> {
#[inline]
pub fn from1 (p: &'a mut T)
-> OutRef<'a, T>
{
let i: i32 = 0;
//let k = p as i32;
#[allow(unused_unsafe)]
unsafe {
// # Safety
//
// - Respects the invariant, since something
// init can be seen as maybeuninit
OutRef {
ptr: p.into(),
_lifetime: PhantomData,
}
}
}
}
fn main ()
{
let mut s: &'static str = "Static str"; // s pointer to static str
let mut s = 9;
s = OutRef::<&'static str>::from1(&mut s); // pointer to s
{
let s = String::from("Short-lived str");
at_s.write(&s); // override s with a pointer to the short-lived str
}
dbg!(s); // Use after free!
}
get error:
error[E0308]: mismatched types
--> src/main.rs:94:39
|
94 | s = OutRef::<&'static str>::from1(&mut s); // pointer to s
| ^^^^^^ expected &str, found integer
|
= note: expected type `&mut &str`
found type `&mut {integer}`
error[E0308]: mismatched types
--> src/main.rs:94:9
|
94 | s = OutRef::<&'static str>::from1(&mut s); // pointer to s
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected integer, found struct `lib::OutRef`
|
= note: expected type `{integer}`
found type `lib::OutRef<'_, &str>`
error: aborting due to 3 previous errors
Some errors have detailed explanations: E0308, E0425.
For more information about an error, try `rustc --explain E0308`.
error: could not compile `playground`.
e.g.
although from1 is called on OutRef::<&'static str>,
the T is not &'static str, but &str
You just have type mismatch errors. That has nothing to do with lifetimes. You're trying to call from1 with 9 as an argument while having defined T to be of the type &str.
fn main ()
{
let mut s: &'static str = "Static str"; // s pointer to static str
let n = 9;
let s1 = String::from("dynamic str");
let mut s = s1.as_str();
let at_s = OutRef::<&'static str>::from1(&mut s); // pointer to s
{
let s = String::from("Short-lived str");
//.write(&s); // override s with a pointer to the short-lived str
}
dbg!(s); // Use after free!
}
shows compiler expected 'a to be 'static:
error[E0597]: s1 does not live long enough
--> src/main.rs:95:17
|
95 | let mut s = s1.as_str();
| ^^---------
| |
| borrowed value does not live long enough
| argument requires that s1 is borrowed for 'static
...
103 | }
| - s1 dropped here while still borrowed
so, should it be clear that:
OutRef::<&'static str>
The first reply correctly tells you, that T is &'static str, but 'a doesn't have to be 'static. That just means you can call OutRef::from1 with a &str regardless of its lifetime. Not more not less. You can never assign a short-lived value to a longer-lived value, because it'd allow you to access freed memory.
The error message hides the lifetime, otherwise it'd either show &'static, &'a or &'_ (anonymous lifetime, aka there is no name, because it has been inferred dynamically). In your second error case, it specifically complains about your value to not be 'static, because you yourself declared at_s to be of the type OutRef<&'static str>, which is inferred from the usage of the turbofish operator when you called OutRef::from1.
error[E0597]: s1 does not live long enough
--> src/main.rs:95:17
|
95 | let mut s = s1.as_str();
| ^^---------
| |
| borrowed value does not live long enough
| argument requires that s1 is borrowed for 'static
...
103 | }
| - s1 dropped here while still borrowed
does it mean
OutRef::<&'static str> has assigned 'static to 'a?
If you think it did means 'a is 'static, then you have to agree my conclusion:
OutRef::<&'static str>
assign &str ===> T, 'static ===> 'a
or you can try another example, this time delete 'static from OutRef::<&'static str>::from1 to OutRef::<&str>::from, then you will find compiling passes
fn main ()
{
let mut s: &'static str = "Static str"; // s pointer to static str
let n = 9;
let s1 = String::from("dynamic str");
let mut s = s1.as_str();
let at_s = OutRef::<&str>::from1(&mut s);
{
let s = String::from("Short-lived str");
at_s.write(&s); // override s with a pointer to the short-lived str
}
dbg!(s); // Use after free!
}
fn lol<'a>(s: &'a mut &'static str) -> OutRef<'a, &'static str> {
OutRef::from1(s)
}
fn main() {
let r = {
let mut s = "abc";
let r = lol(&mut s);
// r is valid inside this block...
println!("{:?}", r);
// ...but not outside it. (therefore 'a is not 'static)
r // Error: `s` does not live long enough
};
}