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
system
Closed
September 19, 2024, 10:14pm
4
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.