Skip to content

Static lifetime deduced for constant, but not for return values of const fn #90370

@hniksic

Description

@hniksic

In rust borrowed constants have static lifetimes, even if the constants are simple literals in the middle of a function. For example, this compiles:

fn assert_static(_r: &'static u32) {}
fn main() {
    assert_static(&1); // compiles
}

This works even in more involved situations, such as when the "literal" is a macro-generated array of structs whose fields are literals. (That's my actual use case, but I'll refer to the simple case of just having a u32 for simplicity.)

The problem is that it no longer works if the value is returned by a const fn:

const fn inc(n: u32) -> u32 {
    n + 1
}

fn assert_static(_r: &'static u32) {}

fn main() {
    assert_static(&1);
    assert_static(&inc(1)) // doesn't compile
}

Playground

error[E0716]: temporary value dropped while borrowed
  --> src/main.rs:9:20
   |
9  |     assert_static(&inc(1)) // doesn't compile
   |     ---------------^^^^^^-
   |     |              |
   |     |              creates a temporary which is freed while still in use
   |     argument requires that borrow lasts for `'static`
10 | }

I would expect (or rather wish) for the latter code to compile since the former did. Note that, since const and static are static, it is possible to work around it by creating an explicit const or static inbetween. For example, all of these compile:

fn main() {
    assert_static(&1);
    {
        const TMP: u32 = inc(1);
        assert_static(&TMP);
    }
    {
        static TMP: u32 = inc(1);
        assert_static(&TMP);
    }
    assert_static({
        const TMP: u32 = inc(1);
        &TMP
    });
    assert_static({
        static TMP: u32 = inc(1);
        &TMP
    });
}

Playground

While a workaround is available, it is not always obvious. Also it would be much nicer not to have to introduce all the temporary constants/statics, especially in code that calls several different const fns.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions