What can be returned with static lifetime?

#![allow(unused)]
fn main() {
go1();}
fn go1()->&'static i32{
    &(123+1)
}
fn go2()->&'static str{  &"qde" }
fn go3()->&'static str{  &" qde".trim() }
//fn go4()->&'static str{  &" qde".replace("q","e") } 
//fn go5()->&'static i32{let x=1; &(123+x)}
//go4 and go5 don't compile   

go1 works but go5 has a error which says we are returning reference to something owned by current function.
(123+1) is also owned by the function why can we return it?
why does go5 fail?

  1. the most common source is from promoted static rvalues:
  2. once a 'static reference is obtained, it can be passed though functions like " qde".trim() in the form of (&'static ...) -> &'static ...

  1. a common safe function uses this is Box::leak ↩︎

1 Like

I don't think there is a limit on what types can be returned with static lifetimes from functions. However, values do not gain the static lifetime by being returned from a function just because it declares it's return type has a static lifetime. you can declare static variables with the static keyword using a similar syntax to the let keyword.
static foo: i32 = 42;
The value created by the expression (123+x) is not static and gets dropped as soon as it goes out of scope. String literals are 'static by default even without being declared with the static keyword. that's why go2 works. for go3, trim returns an &str and when that reference or slice is to an already static string literal it can also be a static reference. for go1, there might actually be some coercion going on. some programming languages will sometimes store some small numbers or integers in the static section of the program. python actually does this despite being bytecode interpreted.

static variables are a bit complicated, but if you declare your variables with the static keyword and ensure they are initialized with constant expressions that can be evaluated at compile time they should work fine. further reading:: Static items - The Rust Reference

What rvalues can be promoted? What I got from all three sources was that only expressions which you can put in a const can be promoted.
but
const A:&str=" qde".trim(); causes a error
while this is fine

fn go3()->&'static str{  &" qde".trim() }

also how are rvalues defined.

That's the point. The rule of thumb defined in the first link says:

// if this compiles
const X: &'static T = &CONST_EXPR;

// this should also compile
let x: &'static T = &CONST_EXPR;
// or equivalently, `x` can be returned from a function as a 'static reference

So you've already seen const A:&str=" qde".trim(); doesn't compile, thus it can't be returned as a 'static reference.
For " qde".trim(), it's not a const expression as the third link defines.

It's defined here.

This code works and compiles

`#![allow(unused)]`
fn main() {
println!("{}",go3());}
fn go3()->&'static str{  &" qde".trim() }

So you've already seen const A:&str=" qde".trim(); doesn't compile, thus it can't be returned as a 'static reference.

Isn't " qde".trim() returned as a static reference here?

My mistake. That's because <&str>::trim(&'static str) -> &'static str. It's not a promoted case.

1 Like

There's no promotion happening in the trim case. If you start out with a &'static str then .trim() can turn that into a string slice of the same lifetime, as it merely returns a new view into the same data.

1 Like

And thanks for this case, I've update my first reply:

note the promoted reference can be passed though functions like this.

Note that string literals like "qde" are already &'static str, if you borrow them again you get a &'something &'static str, which however the compiler can easily turn back into &'static str by automatically reborrowing.

1 Like

In this case &" qde".trim() parses as &(" qde".trim()), but as " qde".trim() is already a &'static str, the same overall argument still applies ^^

And the OP features &"qde", too, I guess…

1 Like

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.