Lifetime extension fails when constructor takes array

I thought I understood temporary lifetime extension a fair bit, but I have no idea why this doesn't compile:

this code gives a "temporary value dropped while borrowed" error
#![allow(dead_code)]

struct A<const N: usize> {
    x: u8,
    y: [u8; N],
}

struct B {
    x: u8,
    y: (),
}

const fn construct<const N: usize>(x: u8, y: [u8; N]) -> A<N> {
    A{
        x,
        y,
    }
}

const fn convert<const N: usize>(a: &A<N>) -> &B {
    unsafe { &*(core::ptr::from_ref(a) as *const B) }
}

const C1: &B = convert(&construct(7, *b"abc"));

take away the array argument and suddenly it works fine:

this code compiles fine
#![allow(dead_code)]

struct A<const N: usize> {
    x: u8,
    y: [u8; N],
}

struct B {
    x: u8,
    y: (),
}

const fn construct<const N: usize>(x: u8) -> A<N> {
    A{
        x,
        y: [0; N],
    }
}

const fn convert<const N: usize>(a: &A<N>) -> &B {
    unsafe { &*(core::ptr::from_ref(a) as *const B) }
}

const C1: &B = convert(&construct::<4>(7));

more weirdness: it works fine if you take a reference to an array:

#![allow(dead_code)]

struct A<const N: usize> {
    x: u8,
    y: [u8; N],
}

struct B {
    x: u8,
    y: (),
}

const fn construct<const N: usize>(x: u8, y: &[u8; N]) -> A<N> {
    A{
        x,
        y: *y,
    }
}

const fn convert<const N: usize>(a: &A<N>) -> &B {
    unsafe { &*(core::ptr::from_ref(a) as *const B) }
}

const C1: &B = convert(&construct(7, b"abc"));

This is the best guide I know of on the topic.

There's no temporary lifetime extension because "it might not be necessary" in the context of the call. (Edit: Also, this isn't a let statement.)

So this is a constant promotion scenario, not a temporary lifetime extension scenario. Constant promotion allows the code to compile in a let statement, for example. But it doesn't apply in your const.

These work.

const C1: &B = convert(&construct(7, const { *b"abc" } ));
const C2: &B = convert(&construct(7, [b'a', b'b', b'c'] ));
1 Like

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.