简体   繁体   English

Rust:错误[E0495]:由于闭包中的冲突要求,无法为自动拒绝推断适当的生命周期

[英]Rust: error[E0495]: cannot infer an appropriate lifetime for autorefdue to conflicting requirements in closure

Raw idea原始想法

In a dummy project I have, I would like to use cycling iterators (to generate integers for example).在我的一个虚拟项目中,我想使用循环迭代器(例如生成整数)。

use std::iter::Cycle;

type IntegerCycle = Cycle<std::slice::Iter<'static, i32>>;

fn generate_cycles() -> [IntegerCycle; 2] {
  let mut cycles = [
    [1, 2].iter().cycle(),
    [2, 4].iter().cycle(),
  ];

  cycles
}


fn main() {
  let mut cycles = generate_cycles();
  // ...
}

Refactor重构

Although the previous piece of code works as intended, my real world example is a bit more complicated, so I am looking to adapt the generate_cycles function to be able to perform more operations (in the following example, multiply by 2, then generate the cycling iterators).尽管前一段代码按预期工作,但我的实际示例有点复杂,因此我希望调整generate_cycles函数以能够执行更多操作(在以下示例中,乘以 2,然后生成循环迭代器)。 For this, I tried to use arraymap :为此,我尝试使用arraymap

extern crate arraymap;

use arraymap::ArrayMap;
use std::iter::Cycle;

type IntegerCycle = Cycle<std::slice::Iter<'static, i32>>;

fn generate_cycles() -> [IntegerCycle; 2] {
  let mut cycles = [
    [1, 2],
    [2, 4],
  ];

  cycles
    .map(|points| {
      points.map(|point| point*2)
    })
    .map(|points| {
      points.iter().cycle()
    })
}


fn main() {
  let mut cycles = generate_cycles();
  // ...
}

The problem问题

The above solution does not work, and, as a Rust beginner recently exposed to the concept of "lifetime", I do not understand why the compiler is complaining here, or what I can do to make him happy.上面的解决方案是行不通的,而且,作为一个最近接触到“生命周期”概念的 Rust 初学者,我不明白编译器为什么在这里抱怨,或者我可以做些什么让他开心。

error[E0495]: cannot infer an appropriate lifetime for autorefdue to conflicting requirements
  --> src/main.rs:20:14
   |
20 |       points.iter().cycle()
   |              ^^^^
   |
note: first, the lifetime cannot outlive the anonymous lifetime #2 defined on the body at 19:10...
  --> src/main.rs:19:10
   |
19 |       .map(|points| {
   |  __________^
20 | |       points.iter().cycle()
21 | |     })
   | |_____^
note: ...so that reference does not outlive borrowed content
  --> src/main.rs:20:7
   |
20 |       points.iter().cycle()
   |       ^^^^^^
   = note: but, the lifetime must be valid for the static lifetime...
   = note: ...so that the expression is assignable:
           expected [std::iter::Cycle<std::slice::Iter<'static, i32>>; 2]
              found [std::iter::Cycle<std::slice::Iter<'_, i32>>; 2]

Here is a REPL with the code trying to make use of the arraymap : https://repl.it/repls/ShadowyStrikingFirm .这是一个尝试使用arraymap的代码的 REPL: https : arraymap

In your type declaration:在您的类型声明中:

type IntegerCycle = Cycle<std::slice::Iter<'static, i32>>;

You say that you the underlying slices you use to build your iterators must have 'static lifetime, that is, they must live forever.您说用于构建迭代器的底层切片必须具有'static生命周期”,即它们必须永远存在。 Then you use literal arrays such as [1, 2] that, as all literals, have 'static' lifetime and all goes well:然后您使用文字数组,例如[1, 2] ,与所有文字一样,具有'static'生命周期并且一切顺利:

let r: &'static [i32; 2] = &[1, 2]; //Ok

But then, you try a code similar to this simpler one:但是,您尝试使用类似于这个更简单的代码的代码:

let a = [1, 2].map(|x| 2 * x);
let r: &'static [i32; 2] = &a; //error: borrowed value does not live long enough

That is the result of arraymap::map is a normal array, not a literal one, so it does not have a 'static lifetime.那是arraymap::map的结果是一个普通数组,而不是文字数组,因此它没有'static生命周期”。 It cannot be static because you are computing the values in runtime.它不能是静态的,因为您是在运行时计算值。 It will live as long as necessary, in my case as long as the variable a .只要有必要,它就会一直存在,在我的情况下,只要变量a

In your case, since the returns of arraymap::map are not assigned to variables, they are temporary values and they are quickly dropped.在您的情况下,由于arraymap::map的返回值未分配给变量,因此它们是临时值并且会很快被删除。 But even if you assigned it to a local variable, you could not return a reference to it, because the local variable is dropped when the function ends.但是即使你将它分配给一个局部变量,你也不能返回对它的引用,因为当函数结束时局部变量被删除了。

The solution is to return an iterator that owns the value.解决方案是返回一个拥有该值的迭代器。 Something like this works:像这样的工作:

type IntegerCycle = Cycle<std::vec::IntoIter<i32>>;

fn generate_cycles() -> [IntegerCycle; 2] {
  let cycles = [
    [1, 2],
    [2, 4],
  ];
  cycles
    .map(|points| {
      points.map(|point| point*2)
    })
    .map(|points| {
      points.to_vec().into_iter().cycle()
    })
}

Unfortunately you have to use a Vec instead of an array, because there is not an IntoIterator implementation for arrays, (there are for slices, but they do not own the values).不幸的是,您必须使用Vec而不是数组,因为数组没有IntoIterator实现(有切片,但它们不拥有值)。

If you want to avoid the extra allocation of Vec you can use the arrayvec crate that does allow to take an iterator to an array:如果你想避免Vec的额外分配,你可以使用允许将迭代器带到数组的arrayvec板条箱:

type IntegerCycle = Cycle<arrayvec::IntoIter<[i32; 2]>>;

fn generate_cycles() -> [IntegerCycle; 2] {
  let cycles = [
    [1, 2],
    [2, 4],
  ];

  cycles
    .map(|points| {
      points.map(|point| point*2)
    })
    .map(|points| {
        let a = arrayvec::ArrayVec::from(*points);
        a.into_iter().cycle()
    })
}

NOTE: It looks like there is an attempt to add a proper IntoIterator impl for arrays by value to the std , but there are still some pending issues.注意:似乎有尝试为数组按值添加适当的IntoIterator implstd ,但仍然存在一些未决问题。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 Rust:错误[E0495]:由于需求冲突,无法为 autoref 推断合适的生命周期 - Rust: error[E0495]: cannot infer an appropriate lifetime for autoref due to conflicting requirements 错误:由于需求冲突,无法推断autoref的适当生命周期[E0495] - error: cannot infer an appropriate lifetime for autoref due to conflicting requirements [E0495] 我如何解决导致错误的闭包[E0495]:无法推断适当的生存期 - How do I work around closures causing error[E0495]: cannot infer an appropriate lifetime 无法为结构内具有相同生命周期的多个引用推断生命参数的适当生命周期 [E0495] - cannot infer an appropriate lifetime for lifetime parameter with multiple references with the same lifetime inside a struct [E0495] Rust 错误 E0495 在闭包中使用 split_at_mut - Rust error E0495 using split_at_mut in a closure 作为函数参数的闭包“由于需求冲突而无法推断出适当的寿命” - Closure as function parameter “cannot infer an appropriate lifetime due to conflicting requirements” Rust:由于要求冲突,无法推断 autoref 的适当生命周期 - Rust: cannot infer an appropriate lifetime for autoref due to conflicting requirements 由于需求冲突,无法推断出合适的生命周期 - Cannot infer an appropriate lifetime due to conflicting requirements 如何在闭包的生命周期和闭包借用的变量上解释 Rust 错误 E0495 - How to interpret Rust error E0495 on the lifetimes of a closure and a variable borrowed by the closure 递归关闭作为函数参数“由于需求冲突而无法推断出适当的寿命” - Recursive closure as function parameter “cannot infer an appropriate lifetime due to conflicting requirements”
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM