闭包的隐式类型导致生命周期推断错误。

5

这是一个简单的复现(使用2月2日的夜版Rust编译器):

fn main() {
    let closure = |_v| {};
    // this one works fine
    // let closure = |_v: &_| {};
    {
        let x = 1;
        closure(&x);
    }
    {
        let y = 1;
        closure(&y);
    }
}

错误信息为:
6  |         let x = 1;
   |             - binding `x` declared here
7  |         closure(&x);
   |                 ^^ borrowed value does not live long enough
8  |     }
   |     - `x` dropped here while still borrowed
...
11 |         closure(&y);
   |         ------- borrow later used here

这不太合理,因为变量x没有被closure捕捉,而只是通过引用传递的参数。

为闭包参数提供一个显式引用_v: &_可以解决这个问题,但这应该自动推断出来吗?

这是借用检查器的某个错误/限制吗?还是我在这里缺少了更基本的东西?

1个回答

5

这看起来对我来说可能是类型推断的一个错误。

我认为正在发生的事情是

fn main() {
    let closure = |_v| {};

    { 
        let x = 1; // Lifetime `a begins
        closure(&x); // closure is inferred to be fn(&'a i32)
        // Lifetime 'a end
    }
    {
        let y = 1; // Lifetime `b begins
        closure(&y); // attempt to call closure fn(&'a i32) with &'b i32
        // Lifetime 'b end
    }
}

但将闭包定义为

let closure = |_v: &'_ i32| {};

停止编译器推断其生命周期并按照应有的方式使用hrtb


2
我已经提出了一个问题 - pigeonhands
1
这似乎是一个推断生命周期问题,将 a 移动到与闭包定义相同的作用域中也可以解决它。https://play.rust-lang.org/?version=stable&mode=debug&edition=2021&gist=66d000d43378f6b8046b557fcf390072 - pigeonhands
这可能是一个错误,但它是众所周知的,并且修复并不容易。请注意,有时即使将参数声明为引用也无法解决问题;对于这些情况,我们有不稳定的 for<'a> |v: &'a i32| 语法。 - Chayim Friedman

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接