little_monkey
little_monkey

Reputation: 439

How can I make a variable borrow for 'static?

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 ?

Upvotes: 10

Views: 8619

Answers (5)

Vlad Faust
Vlad Faust

Reputation: 550

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)
}

Upvotes: -4

Paul
Paul

Reputation: 1

Make a constant with static lifetime:

static NUM: i32 = 18;

Upvotes: -3

kmdreko
kmdreko

Reputation: 59827

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
);

Upvotes: 9

John Kugelman
John Kugelman

Reputation: 361556

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.)

Upvotes: 9

user8866053
user8866053

Reputation:

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.

Upvotes: 1

Related Questions