闭包参数的终身注释 [英] Lifetime annotation for closure argument

查看:87
本文介绍了闭包参数的终身注释的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想编译以下代码:

struct Provider {}

impl Provider {
    fn get_string<'a>(&'a self) -> &'a str { "this is a string" }
}

fn main() {
    let provider = Provider{};
    let mut vec: Vec<&str> = Vec::new();

    // PROBLEM: how do I say that this reference s here
    // needs to live as long as vec?
    let fun = |s: &str| {
        vec.push(s);
    };

    fun(provider.get_string());
}

游乐场链接

这是我得到的编译错误:

This is the compile error that I get:

error[E0495]: cannot infer an appropriate lifetime due to conflicting requirements
 --> src/main.rs:9:22
  |
9 |     let mut vec: Vec<&str> = Vec::new();
  |                      ^^^^
  |
note: first, the lifetime cannot outlive the anonymous lifetime #1 defined on the block at 11:24...
 --> src/main.rs:11:25
  |
11|     let fun = |s: &str| {
  |                         ^
note: ...so that reference does not outlive borrowed content
 --> src/main.rs:12:18
  |
12|         vec.push(s);
  |                  ^
note: but, the lifetime must be valid for the block suffix following statement 2 at 13:6...
 --> src/main.rs:13:7
  |
13|     };
  |       ^
note: ...so that variable is valid at time of its declaration
 --> src/main.rs:11:9
  |
11|     let fun = |s: &str| {
  |         ^^^

推荐答案

如果删除所有生存期注释并让编译器推断完成其工作,您的代码就可以正常工作:

Your code works just fine if remove all the lifetime annotations and let the compiler inference do its job:

struct Provider;

impl Provider {
    fn get_string(&self) -> &str { "this is a string" }
}

fn main() {
    let provider = Provider;
    let mut vec = Vec::new();

    let mut fun = |s| {
        vec.push(s);
    };

    fun(provider.get_string());
}

简而言之,没有任何方法可以显式地引用局部变量的生存期,而只能引用函数参数.不过,编译器知道该怎么做.

In short, there's no way to explicitly refer to the lifetime of a local variable, only function arguments. The compiler knows how to do it, though.

如果您确实需要它,则可以创建一个函数来注释生命周期:

If you truly needed it, you could create a function to allow annotating the lifetimes:

fn thing<'a>(provider: &'a Provider) -> Vec<&'a str> {
    let mut vec: Vec<&'a str> = Vec::new();

    {
        let mut fun = |s: &'a str| vec.push(s);

        fun(provider.get_string());
    } // End mutable borrow of `vec`

    vec
}

fn main() {
    let provider = Provider;
    thing(&provider);
}

为什么原始注释会阻止一切正常工作?

why did the original annotations stop things from working?

具体来说就是这个:

let fun = |s: &str| {
    vec.push(s);
};

这将在闭包上声明一个新的生存期.使用人造语法(您无法在闭包参数上声明生存期),等同于:

This declares a new lifetime on the closure. Using a made-up syntax (you can't declare lifetimes on closure arguments), it would be equivalent to:

let fun = <'a> |s: &'a str| {
    vec.push(s);
};

这是编译器出现错误的原因:

Which is why the compiler has the error:

生存期不能超过[闭包块]上定义的匿名生存期#1

the lifetime cannot outlive the anonymous lifetime #1 defined on [the closure's block]

所生成的生存期与Provider的生存期之间没有任何联系.省略它可以使编译器插入所需的但不可更改的生存期.

There's no connection between that generated lifetime and that of the Provider. Leaving it out allows the compiler to insert the desired but unnamable lifetime.

这篇关于闭包参数的终身注释的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆