Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

How to return a reference to a global variable OnceLock?

I’m trying to implement a derive-macro which would implement a trait for handling global variables. Say, there’re some enum types and I would like to have a separate OnceLock for each enum. In that case, there’s a need for a handle to get it in a general way. The problem lies in the returned lifetimes.

use std::sync::OnceLock;

const v: OnceLock<Vec<u32>> = OnceLock::new();

trait GetGlobal: Sized {
    fn get_global() -> &'static OnceLock<Self>;
}

impl GetGlobal for Vec<u32> {
    fn get_global() -> &'static OnceLock<Self> {
        &v
    }
}

fn main() {
}

The code above generates the following error:

error[E0515]: cannot return reference to temporary value
  --> ./ex_110.rs:11:9
   |
11 |         &v
   |         ^-
   |         ||
   |         |temporary value created here
   |         returns a reference to data owned by the current function

How should I go about remedying it? Not to mention, that it would be better off returning a reference to the underlying data, via OnceLock::get(). Still, it spawns the same lifetime error.

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

>Solution :

Having v as a constant won’t work. Roughly speaking, constants evaluate to expressions that are copied to the locations they are used in, so your &v becomes &OnceLock::new(), hence creating a temporary value. static items on the other hand are a concrete location in memory. Make your OnceLock a static variable. From the docs of static (emphesized by me):

On the surface, static items seem very similar to consts: both contain a value, both require type annotations and both can only be initialized with constant functions and values. However, statics are notably different in that they represent a location in memory. That means that you can have references to static items and potentially even modify them, making them essentially global variables.

Here’s your code with static replacing const and it compiles on the Playground:

use std::sync::OnceLock;

static V: OnceLock<Vec<u32>> = OnceLock::new();

trait GetGlobal: Sized {
    fn get_global() -> &'static OnceLock<Self>;
}

impl GetGlobal for Vec<u32> {
    fn get_global() -> &'static OnceLock<Self> {
        &V
    }
}

fn main() {
}
Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading