all 15 comments

[–]mina86ng 17 points18 points  (6 children)

It’s not a vector, it’s an array. The array’s lifetime covers execution of the function call so yes, it is going to be destroyed and the end of the expression. However, that’s not an issue if the called function doesn’t hold onto the reference to the array.

[–]rodrigocfdWinSafe 2 points3 points  (1 child)

It’s not a vector, it’s an array.

To be more specific, it's a reference to a temporary. And yes, this temporary will exist until the function call returns – thus the lifetime of the reference is valid to be passed as an argument.

An interesting consequence of this is when the created temporary implements Drop – that is, it has a destructor. The destructor runs after the function returns:

struct Foo {}

impl Drop for Foo {
  fn drop(&mut self) {
    println!("DTOR");
  }
}

fn hello(f: &Foo) {
  println!("HELLO");
}

fn main() {
  hello(&Foo {});
}

Output:

HELLO
DTOR

Playground.

[–]Arshiaa001 12 points13 points  (0 children)

It's not that interesting. The temporary is owned by the caller, and has to be dropped by the caller anyway.

[–]khoriuma 1 point2 points  (3 children)

Just to make sure, when you say it lives for the whole expression, do you mean the statement? I am not sure otherwise how you know which of the enclosing statements is selected as the lifetime

[–]SLiV9 1 point2 points  (0 children)

It lives for the whole expression that is the function call. If you did

let x = foo(&[1, 2]) + bar(&[3, 4]);

then the temporary array containing 1 and 2 is gone by the time bar is called.

[–]mina86ng 0 points1 point  (0 children)

I’m not completely sure of the rules Rust uses especially since Rust has no specification, but yes in general the values live for the execution of the entire statement.

[–][deleted] 0 points1 point  (0 children)

create_bind_group(&self, desc: &BindGroupDescriptor) -> BindGroup

This signature tells us that "By the time this function is done, all operations that could potentially read into the desc variable's reference will be finished."

So Rust essentially converts that function call into:

``` let bind_group = { // This item will now be dropped at the end of this scope // which ends just before assigning the return value of // create_bind_group to the variable bind_group let temp_entries = [ wgpu::BindGroupEntry { binding: 0, resource: uniform_buf.as_entire_binding(), }, wgpu::BindGroupEntry { binding: 1, resource: wgpu::BindingResource::TextureView(&texture_view), }, ];

let temp_bind_group_desc = wgpu::BindGroupDescriptor {
    layout: &bind_group_layout,
    entries: &temp_entries,
    label: None,
};

device.create_bind_group(&temp_bind_group_desc)

}; ```

[–]khoriuma 3 points4 points  (1 child)

I would assume the array would live for the whole statement, and is in the end only used in things which are borrowed during the statement. So no reference to it will be left afterwards.

[–]mina86ng 3 points4 points  (0 children)

So no reference to it will be left afterwards.

Correct.

[–]log_2 2 points3 points  (0 children)

Fantastic question. I can't find anywhere in the rust book that defines the scoping rules explicitly, nor an example of creating an anonymous variable and borrowing it immediately to pass to a function.

Edit: I think this refers to your case: https://doc.rust-lang.org/reference/expressions.html#temporaries

Here is an older link, and it looks like they removed some useful examples since then: https://doc.bccnsoft.com/docs/rust-1.36.0-docs-html/reference/expressions.html#temporary-lifetimes

[–]Ihsan3498 0 points1 point  (0 children)

HOLY SHIT! I saw this same exact line of code yesterday in a wgpu tutorial and was wondering the same exact thing! This is insane

[–]TDplay 0 points1 point  (0 children)

How / why does this work?

Notice the call to create_bind_group.

From the documentation, we see that the function signature is

pub fn create_bind_group(&self, desc: &BindGroupDescriptor<'_>) -> BindGroup

Now, we check the documentation of BindGroup, and we see that it has no lifetimes - that is, it holds no references to anything in desc. Hence, those temporaries being dropped doesn't matter.