如何返回具有多个生存期的impl迭代器?

安德烈·Genereux

我在impl特质上的一生中遇到麻烦。我正在尝试使以下代码工作:

struct Foo<'op, Input> {
    op: Box<dyn Fn(Input) -> i32 + 'op>,
}

impl<'op, Input> Foo<'op, Input> {
    fn new<Op>(op: Op) -> Foo<'op, Input>
    where
        Op: Fn(Input) -> i32 + 'op,
    {
        Foo { op: Box::new(op) }
    }

    fn apply<'input_iter, InputIter>(
        self,
        input_iter: InputIter,
    ) -> impl Iterator<Item = i32> + 'op + 'input_iter
    where
        InputIter: IntoIterator<Item = Input> + 'input_iter,
    {
        input_iter.into_iter().map(move |input| (self.op)(input))
    }
}

操场

这给了我以下错误:

error[E0495]: cannot infer an appropriate lifetime due to conflicting requirements
  --> src/lib.rs:20:36
   |
20 |         input_iter.into_iter().map(move |input| (self.op)(input))
   |                                    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
   |
note: first, the lifetime cannot outlive the lifetime 'op as defined on the impl at 5:6...
  --> src/lib.rs:5:6
   |
5  | impl<'op, Input> Foo<'op, Input> {
   |      ^^^
   = note: ...so that the types are compatible:
           expected Foo<'_, _>
              found Foo<'op, _>
note: but, the lifetime must be valid for the lifetime 'input_iter as defined on the method body at 13:14...
  --> src/lib.rs:13:14
   |
13 |     fn apply<'input_iter, InputIter>(
   |              ^^^^^^^^^^^
note: ...so that return value is valid for the call
  --> src/lib.rs:16:10
   |
16 |     ) -> impl Iterator<Item = i32> + 'op + 'input_iter
   |          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

这是我对所涉及生命的理解。Foo拥有一个op,这是一个闭包,可能在其中某个地方有一个引用,因此它可能有一定的寿命。这用'op表示,并且Foo受约束以致无法生存。到现在为止还挺好。

在apply()中,想法是我们要消耗一个input_iter和self并返回使用self.op映射的input_iter中每个元素的迭代器。input_iterator也可能包含引用,因此它可能具有自己的生命周期界限,以'input_iter表示。

我想要的是返回一个同时拥有self和input_iter所有权的迭代器。这样做时,必须同时使用它们的生命周期参数,以确保它不超过input_iter引用或op引用。我以为impl Iterator<Item = i32> + 'op + 'input_iter可以做到这一点,但我似乎在某个地方走错了路。

它抱怨关闭也很奇怪。我知道闭包不能超过'op,因为它需要拥有运算符及其引用的所有权。这是很合理的。我不明白的是为什么它需要活到'input_iter一样长。闭包和输入迭代器根本不应该在意彼此。连接它们的唯一一件事是它们都具有相同的所有者(输出迭代器)。

我在这里想念什么?

弗朗西斯·加涅

生命周期参数并不总是代表对象(或借用)确切生命周期。让我们考虑这个例子:

fn main() {
    let a = 3;
    let b = 5;
    let c = min(&a, &b);
    println!("{:?}", c);
}

fn min<'a>(a: &'a i32, b: &'a i32) -> &'a i32 {
    if a < b {
        a
    } else {
        b
    }
}

在这里,min采用两个具有相同生存期的参考参数。但是,我们称其为借用具有不同生存期的不同变量。那么为什么要编译此代码?

答案是分型和差异较大的寿命是亚型寿命较短的; 相反,较短的寿命是较大寿命的超类型在上面的示例中,编译器必须找到一个与两个输入生存期都兼容的生存期。编译器通过找到两个生命周期的通用超类型(即包含这两个生命周期的最短生命周期)来完成此任务。这称为统一


回到你的问题。这似乎是编译器不会在处理多个生命周期界限impl Trait非常清楚的时刻。但是,并不需要两个生命周期界限:一个就足够了。编译器将缩短该单个寿命如果需要同时满足的要求selfinput_iter

struct Foo<'op, Input> {
    op: Box<dyn Fn(Input) -> i32 + 'op>,
}

impl<'op, Input> Foo<'op, Input> {
    fn new<Op>(op: Op) -> Foo<'op, Input>
    where
        Op: Fn(Input) -> i32 + 'op,
    {
        Foo { op: Box::new(op) }
    }

    fn apply<InputIter>(
        self,
        input_iter: InputIter,
    ) -> impl Iterator<Item = i32> + 'op
    where
        Input: 'op,
        InputIter: IntoIterator<Item = Input> + 'op,
    {
        input_iter.into_iter().map(move |input| (self.op)(input))
    }
}

fn main() {
    let y = 1;
    let foo = Foo::new(|x| x as i32 + y);

    let s = "abc".to_string();
    let sr: &str = &*s;
    let bar = sr.chars();

    let baz: Vec<_> = foo.apply(bar).collect();
    println!("{:?}", baz);
}

尝试main四处移动线条,以使自己确信生命周期确实是统一的。

在这一点上,调用生命周期'op有些误导。它也可能被称为'a

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章

对于具有多个生存期参数的迭代器,impl迭代器失败

具有多个生存期的迭代器

从函数返回的迭代器的生存期要求冲突

如何告诉编译器我返回的枚举变量始终没有生存期?

在实现返回可变引用的迭代器时,如何解决“无法为autoref推断适当的生存期”?

如何指定一个impl的生存期应该与“ self”的生存期相同?

如何使用结构和impl的生存期为实现推断合适的生存期?

在迭代器特征中指定关联类型的生存期

如何为引用自身但不会突变的迭代器的关联类型指定生存期?

如何使用impl函数声明枚举生存期?

具有生存期值的Rust函数返回类型

别名具有生存期的泛型函数?

具有不同会话生存期的Laravel

从String转换为&str具有不同的生存期

Rust字符串生存期和迭代器适配器(生存期编译错误)

返回带有自我生存期的参考

如何创建具有特定生存期的可变字符串?

如何将shared_ptr传递给具有较低生存期的类?

有没有办法传递对泛型函数的引用并返回与参数的生存期无关的impl特性?

具有父类型生存期的引用不能用于子类型生存期

如何指定一个带引用的闭包,并返回实现与该引用具有相同生存期的特征的任何类型?

Rust中嵌套迭代器的所有权和生存期,用于字符串比较

如何将返回值的生存期设置为要移入的变量的生存期?

为什么在同一范围内可能有多个具有静态生存期的可变引用

使用函数定义特征,该函数返回与一个参数具有相同生存期的关联类型

即使数组包含的值也具有静态生存期,也无法将静态引用返回给临时数组

具有生存期限制的递归函数内部循环中的借入检查器错误

如何指定AsRef的生存期?

作为参数传递给方法的迭代器项的生存期的“冲突要求”