How can I make a variable borrow for 'static?
Asked Answered
A

5

9

In vulkano, to create a CPUAccessibleBuffer you need give it some data and the CPUAccessibleBuffer::from_data function requires the data to have the 'static lifetime.

I have some data in &[u8] array (created at runtime) that I would like to pass to that function.

However, it errors with this message

argument requires that `data` is borrowed for `'static`

So how can I make the lifetime of the data 'static ?

Angelika answered 8/11, 2021 at 18:10 Comment(0)
M
9

You should use CpuAccessibleBuffer::from_iter instead, it does the same thing but does not require the collection to be Copy or 'static:

let data: &[u8] = todo!();

let _ = CpuAccessibleBuffer::from_iter(
    device,
    usage,
    host_cached,
    data.iter().copied(), // <--- pass like so
);

Or if you actually have a Vec<u8>, you can pass it directly:

let data: Vec<u8> = todo!();

let _ = CpuAccessibleBuffer::from_iter(
    device,
    usage,
    host_cached,
    data, // <--- pass like so
);
Maressa answered 8/11, 2021 at 20:3 Comment(0)
C
8

If you really must create the data at runtime, and you really need to last for 'static, then you can use one of the memory leaking methods such as Box::leak or Vec::leak to deliberately leak a heap allocation and ensure it is never freed.

While leaking memory is normally something one avoids, in this case it's actually a sensible thing to do. If the data must live forever then leaking it is actually the correct thing to do, semantically speaking. You don't want the memory to be freed, not ever, which is exactly what happens when memory is leaked.

Example:

fn require_static_data(data: &'static [u8]) {
    unimplemented!()
}

fn main() {
    let data = vec![1, 2, 3, 4];
    require_static_data(data.leak());
}

Playground

That said, really think over the reallys I led with. Make sure you understand why the code you're calling wants 'static data and ask yourself why your data isn't already 'static.

  • Is it possible to create the data at compile time? Rust has a powerful build time macro system. It's possible, for example, to use include_bytes! to read in a file and do some processing on it before it's embedded into your executable.

  • Is there another API you can use, another function call you're not seeing that doesn't require 'static?

(These questions aren't for you specifically, but for anyone who comes across this Q&A in the future.)

Christinchristina answered 8/11, 2021 at 19:48 Comment(1)
You deserve the +1 for include_bytes! at a minimum. That's just wild for compile-time reading in of files/data. I can see how useful that could be, and yet also how utterly abused it would be by some developers I know. And on occasion, I'll admit I'll probably be both types of developer!Leyte
T
1

If the data is created at runtime, it can't have a static lifetime. Static means that data is present for the whole lifetime of the program, which is necessary in some contexts, especially when threading is involved. One way for data to be static is, as Paul already answered, explicitly declaring it as such, i.e.:

static constant_value: i32 = 0;

However, there's no universally applicable way to make arbitrary data static. This type of inference is made at compile-time by the borrow checker, not by the programmer.

Usually if a function requires 'static (type) arguments (as in this case) it means that anything less could potentially be unsafe, and you need to reorganize the way data flows in and out of your program to provide this type of data safely. Unfortunately, that's not something SO can provide within the scope of this question.

Tatting answered 8/11, 2021 at 18:26 Comment(0)
A
-3

Make a constant with static lifetime:

static NUM: i32 = 18;
Ask answered 8/11, 2021 at 18:17 Comment(1)
Please take a look at @CtrlAltF2's answer, which was posted around the same time as yours, for the level of detail we like to see for answers on Stack Overflow.Uzziel
R
-4

Following @John Kugelman's answer, I've implemented this function:

/// Return a tuple of a boxed value and a static mutable reference to it.
/// # Safety
/// Once the box is dropped, the reference will be dropped as well,
/// leading to undefined behavior if it is used afterwards.
pub unsafe fn static_box<T>(value: T) -> (Box<T>, &'static mut T) {
    let boxed = Box::new(value);
    let raw = std::boxed::Box::leak(boxed);
    let boxed = Box::from_raw(raw);
    (boxed, raw)
}
Rasla answered 7/5 at 14:51 Comment(3)
Do not do this! You are returning two values that require exclusive access, but they refer to the same object. This is undefined behavior even without accessing either field (miri reports this). The unsafe qualifier and documented safety invariant is not sufficient.Maressa
It works nice if you know what you're doing. Sometimes you need to tell the compiler that this particular value indeed has static lifetime, especially when working with C libs, taking full responsibility for your actions.Rasla
When @Maressa says it's undefined behavior even without accessing either field that means there is no safe way to use this function. Constructing the Box is immediate undefined behavior, irrespective of how it's used. It doesn't matter that the function is marked unsafe.Christinchristina

© 2022 - 2024 — McMap. All rights reserved.