在玩 async/await 时,我偶然发现了这个终生难题。 我假设predicate接受一个引用/值并产生静态未来 - 它没有对其参数的引用并且不捕获任何值。 相反,我抱怨寿命太短。

为什么它会失败,生命周期'2哪里?

use futures::future;
use std::future::Future;

fn validate<F, Fut>(_: F)
where
    F: FnMut(&str) -> Fut,
    Fut: Future<Output = bool>,
{
}

fn predicate(_: impl AsRef<str>) -> impl Future<Output = bool> {
    future::ready(true)
}

fn main() {
    validate(|x| predicate(x));
}

错误信息:

error: lifetime may not live long enough
  --> src\main.rs:16:18
   |
16 |     validate(|x| predicate(x));
   |               -- ^^^^^^^^^^^^ returning this value requires that `'1` must outlive `'2`
   |               ||
   |               |return type of closure is impl futures::Future
   |               has type `&'1 str`

error: aborting due to previous error

#1楼 票数:2 已采纳

这里的错误消息有点令人困惑,因为它谈论的是两个生命周期, '1'2 ,但实际上并没有说明'2指的是什么。

这里有两个生命周期很重要:

  • &str参数,消息标记为生命周期'1
  • 未来类型变量Fut ,在消息中用生命周期'2标记,尽管它没有明确说明。

predicate的推断生命周期(使用生命周期省略规则)如下所示:

fn predicate<'x>(_: impl AsRef<str> + 'x) -> impl Future<Output = bool> + 'x {
    future::ready(true)
}

即使实现实际上并没有使用字符串输入,如果不使用它也会很奇怪,所以这对于真正的实现来说可能是正确的。 编译器推断函数的返回值使用输入,因此它们必须具有兼容的生命周期。

但是, validate的生命周期被推断为不同:

fn validate<'1, '2, F, Fut>(_: F)
where
    F: FnMut(&'1 str) -> Fut,
    Fut: Future<Output = bool> + '2,
{
}

此函数接受比predicate要求更广泛的参数,这意味着它不能保证强制执行predicate需要的约束。

您可以通过在validate类型中明确指定来解决这个问题:

fn validate<'a, F, Fut>(_: F)
where
    F: FnMut(&'a str) -> Fut,
    Fut: Future<Output = bool> + 'a,
{
}

'a生命周期约束这两种类型表明validate期望F使用来自&str数据,因此将确保字符串存在足够长的时间。 任何违反此合同的validate实现也不会编译。

  ask by flopacero translate from so

未解决问题?本站智能推荐:

1回复

使用 Tokio 0.2 生成非静态未来

我有一个异步方法应该并行执行一些期货,并且只有在所有期货完成后才返回。 但是,它通过引用传递了一些数据,这些数据不像'static (它将在 main 方法中的某个点被删除)。 从概念上讲,它类似于( Playground ): async fn do_sth(with: &u64) {
1回复

参考'静态的寿命不够长?

考虑下一个代码: fn get_ref<'a, R>(slice: &'a Vec<i32>, f: fn(&'a Vec<i32>) -> R) -> R where R: 'a, { f(slice) } fn m
1回复

Rust:“.. 活得不够久”

这是代码(具有 Rust 初学者难度): 操场 我不确定我是否明白出了什么问题(但肯定有问题)。 'a在这里是一个main()函数作用域, index和refcell一直存在,直到 main() 退出。 matcher接受的参考RefCell是生活至少'a和引用一个框,生活至少'a和点到T
1回复

为什么变量的寿命不够长?

考虑应该返回给定Path的文件扩展名的此函数。 pub fn get_extension<'a>(path: &'a Path) -> Option<&'a str> { let path_str = path.as_str().unwra
1回复

PathBuf的寿命不够长

我正在尝试在构建脚本中使用以下代码: 我收到以下错误: 我实际上是在保存自己变量中的每个值。 那么这怎么可能不会超过这个陈述呢? 我知道还有“into_os_string”,但为什么我的方法不起作用? 我真的想要了解整个一生的事情,但这很难。 也许有人可以快速浏览我的
1回复

变量的寿命不够长:匹配选项类型

我正在使用getopts,而我之前从这样的标志中获取了一个值: 但是,我想通过使路径可选来更好地处理可能的错误。 这是我的新代码: 但是,当我尝试编译这段代码时,我得到的错误'f' does not live long enough 。 我完全难过了。 继承我代码的MC
1回复

尽管直接返回该项,但Iterator :: max的结果寿命不够长

这段代码( Playground ): ...导致此错误: 我不明白这个错误: Iterator::max返回Option<Self::Item> ,而不是Option<&Self::Item> ,因此max不应该是引用,因此一切都应该很好。
2回复

使用通用函数创建容器,向其添加项目,然后遍历项目时,值的使用寿命不够长

我正在尝试编写一个创建默认值的泛型函数,并遍历其内部“缓冲区”。 所有这些都发生在没有参数的函数中,也没有返回值。 我似乎已经宣布生命周期不正确,我很难正确地设置它们以便工作。 下面是一个实现Default和IntoIterator特征的示例类型,以及一个需要一个方法的名为Foo的新特