Confused by temporary

So I follow the learnwgpu tutorial.
The code uses a bunch of temporaries when configuring everything.
But I didn't really think about it until I run into this:
In the Texture and Bind groups chapter, the Vertex impl desc() associated function return VertexBufferLayout<'a>:

    fn desc<'a>() -> wgpu::VertexBufferLayout<'a> {
        wgpu::VertexBufferLayout {
            array_stride: std::mem::size_of::<Vertex>() as wgpu::BufferAddress,
            step_mode: wgpu::VertexStepMode::Vertex,
            attributes: &[
                wgpu::VertexAttribute {
                    shader_location: 0,
                    format: wgpu::VertexFormat::Float32x3,
                    offset: 0,
                },
                wgpu::VertexAttribute {
                    shader_location: 1,
                    format: wgpu::VertexFormat::Float32x2,
                    offset: std::mem::size_of::<[f32; 3]>() as wgpu::BufferAddress,
                },
            ],
        }
    }

this compiles fine (why? Constant promotion ?) However as mentioned in the tutorial, this does not compile:

    fn desc<'a>() -> wgpu::VertexBufferLayout<'a> {
        wgpu::VertexBufferLayout {
            array_stride: std::mem::size_of::<Vertex>() as wgpu::BufferAddress,
            step_mode: wgpu::VertexStepMode::Vertex,
            attributes: &wgpu::vertex_attr_array![0 => Float32x3, 1 => Float32x2],
        }
    }

error[E0515]: cannot return value referencing temporary value

However this is expanded in almost exactly the same code:

    fn desc<'a>() -> wgpu::VertexBufferLayout<'a> {
        wgpu::VertexBufferLayout {
            array_stride: std::mem::size_of::<Vertex>() as wgpu::BufferAddress,
            step_mode: wgpu::VertexStepMode::Vertex,
            attributes: &[
                ::wgpu::VertexAttribute {
                    format: ::wgpu::VertexFormat::Float32x3,
                    offset: 0,
                    shader_location: 0,
                },
                ::wgpu::VertexAttribute {
                    format: ::wgpu::VertexFormat::Float32x2,
                    offset: 0 + ::wgpu::VertexFormat::Float32x3.size(),
                    shader_location: 1,
                },
            ],
        }
    }

The only significant difference (I think) is the call to VertexFormat::size() which is const.

So am I right to think that what allow the 1st version to compile is constant promotion of the temporary VertexAttribute array ?
If so, what prevent the second version using the macro to compile ?

Thanks for your help

I figured out that the 2nd and 3rd code snippets could be made working by capturing the result of wgpu::vertex_attr_array![] with a compile time constant:

    fn desc<'a>() -> wgpu::VertexBufferLayout<'a> {
        wgpu::VertexBufferLayout {
            array_stride: 4 as wgpu::BufferAddress,
            step_mode: wgpu::VertexStepMode::Vertex,
            attributes: &{
				const ATTR: [wgpu::VertexAttribute; 2] =
					wgpu::vertex_attr_array![0 => Float32x3, 1 => Float32x2];
				ATTR
			},
        }
    }

Further experiment shows that VertexFormat::Float32x3.size() prevents automatic constant promotion (albeit being a const fn), which I couldn't explain why. Hope other people could help with this.

EDIT: according to github.com/rust-lang/const-eval/promotion.md:

In particular, we cannot promote calls to arbitrary const fn , as discussed in detail in rust-lang/const-eval#19. Thus, only functions marked #[rustc_promotable] are promotable.

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.