Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

"lifetime may not live long enough" for static reference to function pointer

Tags:

rust

This piece of code does not compile:

pub struct Test<T> {
    Test: &'static fn(T) -> T,
}

This is a reduced snippet from something more complex.

I get "the parameter type T may not live long enough" and a hint to add T: 'static, but I do not see exactly why the lifetime of fn(T) -> T should be affected by the lifetime of T.

Why do I get this error and can I workaround it to avoid requiring T: 'static?

like image 986
gigabytes Avatar asked May 28 '26 20:05

gigabytes


1 Answers

What you probably want is:

pub struct Test<'a, T> {
    f: &'a fn(T) -> T,
}

To answer why the compiler doesn't allow the 'static reference, having a &'static fn(T) -> T for non-static T doesn't really make sense:

fn make_static_fn<T>(_: T) -> &'static fn(T) -> T { todo!() }

let f: &'static fn(_) -> _;
// Assume the following block compiles, which it would if &'static fn(T) -> T were allowed
{
    let a = 42;
    f = make_static_fn(&a); // T = &'a i32
}

// This is fine, as 0 is const, so &0 is a static reference, and 'static: '_
// which includes 'a, so &0 coerces to &'a i32 = T
let a_ref = (f)(&0);
// From the compiler's point of view, a_ref is a reference with lifetime 'a,
// a lifetime that already expired. The existence of a_ref requires that the
// `a` variable from the inner block earlier is still borrowed.

Playground

For a more concrete example of how this could lead to UB, the following uses a dyn Fn() -> T rather than a function pointer.

// This function is totally valid
fn make_static_fn<T: Copy>(t: T) -> &'static dyn Fn() -> T {
    Box::leak(Box::new(move || { t }))
}

fn main() {
    let f: &'static dyn Fn() -> _;
    // Assume the following block compiles, which it would if &'static Fn() -> T were allowed
    {
        let a = 42;
        // f creates copies of &a
        f = make_static_fn(&a); // T = &'a i32
    }

    let a_ref = (f)();
    // If the compiler allowed this, a_ref would contain a reference to a!
}

Playground

like image 121
myster Avatar answered May 30 '26 14:05

myster



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!