Why can I return a reference to a local literal but not a variable?

前端 未结 1 1891
佛祖请我去吃肉
佛祖请我去吃肉 2020-11-22 07:39

Why does this code compile?

fn get_iter() -> impl Iterator {
    [1, 2, 3].iter().map(|&i| i)
}

fn main() {
    let _it = get_iter(         


        
相关标签:
1条回答
  • 2020-11-22 08:09

    In your example, [1, 2, 3] is not treated as local variable, but as static one!

    Let's take a look at this code:

    fn foo() -> &'static [i32] {
        &[1, 2, 3]
    }
    

    This works!

    Some time ago, RFC 1414: Rvalue Static Promotion was merged: "Promote constexpr rvalues to values in static memory instead of stack slots". This means that basically all literals you write can live forever. Thus, things like let _: &'static i32 = &42; also work!

    If we avoid using a literal array, we can see the expected error:

    fn bar() -> impl Iterator<Item = i32> {
        vec![1, 2, 3].iter().map(|&i| i)
    }
    

    Here we get the "v does not live long enough" error.

    This isn't limited to integers or arrays; it applies broadly to any literal that is composed solely of literals:

    fn promote_integer() -> &'static i32 {
        &42
    }
    
    fn promote_float() -> &'static f64 {
        &42.42
    }
    
    fn promote_str() -> &'static str {
        "Hello World!"
    }
    
    struct Foo(char);
    
    fn promote_struct() -> &'static Foo {
        &Foo('x')
    }
    

    Beyond literals, this also works for a tiny number of functions in the standard library, but these were likely a mistake. Deciding on if the result of arbitrary const functions can be automatically promoted to static is still an open topic.

    0 讨论(0)
提交回复
热议问题