Rust:错误 [E0495]:由于闭包中的需求冲突,无法推断出自动引用的适当生命周期
Rust: error[E0495]: cannot infer an appropriate lifetime for autorefdue to conflicting requirements in closure
原始想法
在我的虚拟项目中,我想使用循环迭代器(例如生成整数)。
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();
// ...
}
重构
虽然前面的代码按预期工作,但我的真实世界示例有点复杂,因此我希望调整 generate_cycles
函数以能够执行更多操作(在以下示例中,乘以 2,然后生成循环迭代器)。
为此,我尝试使用 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();
// ...
}
问题
上述解决方案不起作用,而且,作为最近接触"lifetime"概念的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]
这是一个 REPL,其中的代码试图利用 arraymap
:https://repl.it/repls/ShadowyStrikingFirm .
在你的类型声明中:
type IntegerCycle = Cycle<std::slice::Iter<'static, i32>>;
你说你用来构建迭代器的底层切片必须有 'static
生命周期,也就是说,它们必须永远存在。然后你使用像 [1, 2]
这样的文字数组,与所有文字一样,它有 'static'
生命周期并且一切顺利:
let r: &'static [i32; 2] = &[1, 2]; //Ok
但是,您尝试使用与这个更简单的代码类似的代码:
let a = [1, 2].map(|x| 2 * x);
let r: &'static [i32; 2] = &a; //error: borrowed value does not live long enough
那是 arraymap::map
的结果是一个普通数组,而不是文字数组,所以它没有 'static
生命周期。它不能是静态的,因为您是在运行时计算值。只要有必要,它就会存在,在我的例子中,只要变量 a
.
在您的情况下,由于 arraymap::map
的 return 未分配给变量,因此它们是临时值,很快就会被删除。但是即使你把它赋值给一个局部变量,你也不能 return 引用它,因为局部变量在函数结束时被删除。
解决方案是 return 拥有该值的迭代器。像这样的东西有效:
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()
})
}
不幸的是,您必须使用 Vec
而不是数组,因为数组没有 IntoIterator
实现(有切片,但它们不拥有值)。
如果你想避免 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()
})
}
注意: 看起来有人试图将适当的 IntoIterator
impl for arrays by value 添加到 std
,但仍有一些悬而未决的问题。
原始想法
在我的虚拟项目中,我想使用循环迭代器(例如生成整数)。
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();
// ...
}
重构
虽然前面的代码按预期工作,但我的真实世界示例有点复杂,因此我希望调整 generate_cycles
函数以能够执行更多操作(在以下示例中,乘以 2,然后生成循环迭代器)。
为此,我尝试使用 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();
// ...
}
问题
上述解决方案不起作用,而且,作为最近接触"lifetime"概念的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]
这是一个 REPL,其中的代码试图利用 arraymap
:https://repl.it/repls/ShadowyStrikingFirm .
在你的类型声明中:
type IntegerCycle = Cycle<std::slice::Iter<'static, i32>>;
你说你用来构建迭代器的底层切片必须有 'static
生命周期,也就是说,它们必须永远存在。然后你使用像 [1, 2]
这样的文字数组,与所有文字一样,它有 'static'
生命周期并且一切顺利:
let r: &'static [i32; 2] = &[1, 2]; //Ok
但是,您尝试使用与这个更简单的代码类似的代码:
let a = [1, 2].map(|x| 2 * x);
let r: &'static [i32; 2] = &a; //error: borrowed value does not live long enough
那是 arraymap::map
的结果是一个普通数组,而不是文字数组,所以它没有 'static
生命周期。它不能是静态的,因为您是在运行时计算值。只要有必要,它就会存在,在我的例子中,只要变量 a
.
在您的情况下,由于 arraymap::map
的 return 未分配给变量,因此它们是临时值,很快就会被删除。但是即使你把它赋值给一个局部变量,你也不能 return 引用它,因为局部变量在函数结束时被删除。
解决方案是 return 拥有该值的迭代器。像这样的东西有效:
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()
})
}
不幸的是,您必须使用 Vec
而不是数组,因为数组没有 IntoIterator
实现(有切片,但它们不拥有值)。
如果你想避免 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()
})
}
注意: 看起来有人试图将适当的 IntoIterator
impl for arrays by value 添加到 std
,但仍有一些悬而未决的问题。