将 &mut 传递给函数并返回闭包的生命周期问题
Lifetime problems passing &mut to function and returning a closure
我有一个通过分而治之递增向量的简短示例。非常基本,我只是无法正确获得生命周期。我很确定它与 &'s mut
参数生命周期和 TaskResult<'s>
return 生命周期有关,但我不确定如何让它工作。
fn main() {
let mut data = vec![1,2,3,4,5,6,7,8,9];
let t = inc_vec(data.as_mut_slice());
}
pub type MyClosure<'s> = FnMut() -> TaskResult<'s> + Send + 's;
pub enum TaskResult<'s> {
Done(usize),
Fork(Vec<Box<MyClosure<'s>>>),
}
fn inc_vec<'s>(data: &'s mut [usize]) -> TaskResult {
if data.len() <= 4 {
inc_vec_direct(data)
} else {
inc_vec_fork(data)
}
}
fn inc_vec_fork<'s>(data: &'s mut [usize]) -> TaskResult<'s> {
let mid = data.len()/2;
let (l,r) = data.split_at_mut(mid);
let task_l: Box<MyClosure<'s>> = Box::new(move || {
inc_vec(l)
});
let task_r: Box<MyClosure<'s>> = Box::new(move || {
inc_vec(r)
});
TaskResult::Fork(vec![task_l, task_r])
}
fn inc_vec_direct(data: &mut [usize]) -> TaskResult {
for d in data {
*d += 1;
}
TaskResult::Done(1)
}
它给了我以下错误(由于相同的错误产生了两次而被截断,一次是 task_l
,一次是 task_r
):
src/main.rs:26:17: 26:18 error: cannot infer an appropriate lifetime for automatic coercion due to conflicting requirements
src/main.rs:26 inc_vec(l)
^
src/main.rs:25:55: 27:6 note: first, the lifetime cannot outlive the lifetime as defined on the block at 25:54...
src/main.rs:25 let task_l: Box<MyClosure<'s>> = Box::new(move || {
src/main.rs:26 inc_vec(l)
src/main.rs:27 });
src/main.rs:26:17: 26:18 note: ...so that closure can access `l`
src/main.rs:26 inc_vec(l)
^
src/main.rs:21:62: 33:2 note: but, the lifetime must be valid for the lifetime 's as defined on the block at 21:61...
src/main.rs:21 fn inc_vec_fork<'s>(data: &'s mut [usize]) -> TaskResult<'s> {
src/main.rs:22 let mid = data.len()/2;
src/main.rs:23 let (l,r) = data.split_at_mut(mid);
src/main.rs:24
src/main.rs:25 let task_l: Box<MyClosure<'s>> = Box::new(move || {
src/main.rs:26 inc_vec(l)
...
src/main.rs:25:38: 27:7 note: ...so that trait type parameters matches those specified on the impl (expected `TaskResult<'_>`, found `TaskResult<'s>`)
src/main.rs:25 let task_l: Box<MyClosure<'s>> = Box::new(move || {
src/main.rs:26 inc_vec(l)
src/main.rs:27 });
必须有一个简单的解决方法。我想说的是,我 return 一个闭包向量,它具有对输入切片部分的可变引用。我想我必须将闭包生命周期标记为比数据切片生命周期短,只是不知道该怎么做。
你可以编译你的例子,运行 如果你改变一行:
pub type MyClosure<'s> = FnOnce() -> TaskResult<'s> + Send + 's;
// ^~~~~~
不过我还在想怎么解释呢!
这是我开始的代码。我做了一些简化来开始,主要是围绕删除不需要的生命周期引用。生命周期省略意味着 fn(foo: &T) -> &U
与 fn<'a>(foo: &'a T) -> &'a U
相同,但 与 fn<'a>(foo: &'a T) -> &U
不同 。
fn main() {
let mut data = vec![1,2,3,4,5,6,7,8,9];
let t = inc_vec(data.as_mut_slice());
}
pub type MyClosure<'s> = FnMut() -> TaskResult<'s> + Send + 's;
pub enum TaskResult<'s> {
Done(usize),
Fork(Vec<Box<MyClosure<'s>>>),
}
fn inc_vec(data: &mut [usize]) -> TaskResult {
if data.len() <= 4 {
inc_vec_direct(data)
} else {
inc_vec_fork(data)
}
}
fn inc_vec_fork(data: &mut [usize]) -> TaskResult {
let mid = data.len() / 2;
let (l, r) = data.split_at_mut(mid);
let task_l: Box<MyClosure> = Box::new(move || inc_vec(l));
let task_r: Box<MyClosure> = Box::new(move || inc_vec(r));
TaskResult::Fork(vec![task_l, task_r])
}
fn inc_vec_direct(data: &mut [usize]) -> TaskResult {
for d in data { *d += 1; }
TaskResult::Done(1)
}
大多数情况下,我只是稍微改变一下闭包就得到了结果:
let task_l: Box<MyClosure> = Box::new(move || { let a = l; inc_vec(a)});
这应该是相同的代码。但是,这有错误:
error: cannot move out of captured outer variable in an `FnMut` closure
let task_l: Box<MyClosure> = Box::new(move || { let a = l; inc_vec(a)});
^
note: attempting to move value to here
let task_l: Box<MyClosure> = Box::new(move || { let a = l; inc_vec(a)});
^
help: to prevent the move, use `ref a` or `ref mut a` to capture value by reference
这让我尝试了各种 Fn*
特征,FnOnce
有效。我 认为 解决方案归结为 Rust 不允许可变引用的别名(a.k.a。你不能指向同一个可变的东西两次)。如果您有 FnMut
或 Fn
,那么您可以多次调用闭包,这将提供创建别名的机会。不过,如果错误消息包含有关可变性的任何信息,那就太好了!
A FnOnce
保证只被调用一次,这防止了特定的别名机会。
我认为您可以从中提交 1 或 2 个错误:
- 令人惊讶的是,错误消息会根据是否存在
let
而改变。
- 最好提及可变性作为变量不能移入闭包的原因。
我有一个通过分而治之递增向量的简短示例。非常基本,我只是无法正确获得生命周期。我很确定它与 &'s mut
参数生命周期和 TaskResult<'s>
return 生命周期有关,但我不确定如何让它工作。
fn main() {
let mut data = vec![1,2,3,4,5,6,7,8,9];
let t = inc_vec(data.as_mut_slice());
}
pub type MyClosure<'s> = FnMut() -> TaskResult<'s> + Send + 's;
pub enum TaskResult<'s> {
Done(usize),
Fork(Vec<Box<MyClosure<'s>>>),
}
fn inc_vec<'s>(data: &'s mut [usize]) -> TaskResult {
if data.len() <= 4 {
inc_vec_direct(data)
} else {
inc_vec_fork(data)
}
}
fn inc_vec_fork<'s>(data: &'s mut [usize]) -> TaskResult<'s> {
let mid = data.len()/2;
let (l,r) = data.split_at_mut(mid);
let task_l: Box<MyClosure<'s>> = Box::new(move || {
inc_vec(l)
});
let task_r: Box<MyClosure<'s>> = Box::new(move || {
inc_vec(r)
});
TaskResult::Fork(vec![task_l, task_r])
}
fn inc_vec_direct(data: &mut [usize]) -> TaskResult {
for d in data {
*d += 1;
}
TaskResult::Done(1)
}
它给了我以下错误(由于相同的错误产生了两次而被截断,一次是 task_l
,一次是 task_r
):
src/main.rs:26:17: 26:18 error: cannot infer an appropriate lifetime for automatic coercion due to conflicting requirements
src/main.rs:26 inc_vec(l)
^
src/main.rs:25:55: 27:6 note: first, the lifetime cannot outlive the lifetime as defined on the block at 25:54...
src/main.rs:25 let task_l: Box<MyClosure<'s>> = Box::new(move || {
src/main.rs:26 inc_vec(l)
src/main.rs:27 });
src/main.rs:26:17: 26:18 note: ...so that closure can access `l`
src/main.rs:26 inc_vec(l)
^
src/main.rs:21:62: 33:2 note: but, the lifetime must be valid for the lifetime 's as defined on the block at 21:61...
src/main.rs:21 fn inc_vec_fork<'s>(data: &'s mut [usize]) -> TaskResult<'s> {
src/main.rs:22 let mid = data.len()/2;
src/main.rs:23 let (l,r) = data.split_at_mut(mid);
src/main.rs:24
src/main.rs:25 let task_l: Box<MyClosure<'s>> = Box::new(move || {
src/main.rs:26 inc_vec(l)
...
src/main.rs:25:38: 27:7 note: ...so that trait type parameters matches those specified on the impl (expected `TaskResult<'_>`, found `TaskResult<'s>`)
src/main.rs:25 let task_l: Box<MyClosure<'s>> = Box::new(move || {
src/main.rs:26 inc_vec(l)
src/main.rs:27 });
必须有一个简单的解决方法。我想说的是,我 return 一个闭包向量,它具有对输入切片部分的可变引用。我想我必须将闭包生命周期标记为比数据切片生命周期短,只是不知道该怎么做。
你可以编译你的例子,运行 如果你改变一行:
pub type MyClosure<'s> = FnOnce() -> TaskResult<'s> + Send + 's;
// ^~~~~~
不过我还在想怎么解释呢!
这是我开始的代码。我做了一些简化来开始,主要是围绕删除不需要的生命周期引用。生命周期省略意味着 fn(foo: &T) -> &U
与 fn<'a>(foo: &'a T) -> &'a U
相同,但 与 fn<'a>(foo: &'a T) -> &U
不同 。
fn main() {
let mut data = vec![1,2,3,4,5,6,7,8,9];
let t = inc_vec(data.as_mut_slice());
}
pub type MyClosure<'s> = FnMut() -> TaskResult<'s> + Send + 's;
pub enum TaskResult<'s> {
Done(usize),
Fork(Vec<Box<MyClosure<'s>>>),
}
fn inc_vec(data: &mut [usize]) -> TaskResult {
if data.len() <= 4 {
inc_vec_direct(data)
} else {
inc_vec_fork(data)
}
}
fn inc_vec_fork(data: &mut [usize]) -> TaskResult {
let mid = data.len() / 2;
let (l, r) = data.split_at_mut(mid);
let task_l: Box<MyClosure> = Box::new(move || inc_vec(l));
let task_r: Box<MyClosure> = Box::new(move || inc_vec(r));
TaskResult::Fork(vec![task_l, task_r])
}
fn inc_vec_direct(data: &mut [usize]) -> TaskResult {
for d in data { *d += 1; }
TaskResult::Done(1)
}
大多数情况下,我只是稍微改变一下闭包就得到了结果:
let task_l: Box<MyClosure> = Box::new(move || { let a = l; inc_vec(a)});
这应该是相同的代码。但是,这有错误:
error: cannot move out of captured outer variable in an `FnMut` closure
let task_l: Box<MyClosure> = Box::new(move || { let a = l; inc_vec(a)});
^
note: attempting to move value to here
let task_l: Box<MyClosure> = Box::new(move || { let a = l; inc_vec(a)});
^
help: to prevent the move, use `ref a` or `ref mut a` to capture value by reference
这让我尝试了各种 Fn*
特征,FnOnce
有效。我 认为 解决方案归结为 Rust 不允许可变引用的别名(a.k.a。你不能指向同一个可变的东西两次)。如果您有 FnMut
或 Fn
,那么您可以多次调用闭包,这将提供创建别名的机会。不过,如果错误消息包含有关可变性的任何信息,那就太好了!
A FnOnce
保证只被调用一次,这防止了特定的别名机会。
我认为您可以从中提交 1 或 2 个错误:
- 令人惊讶的是,错误消息会根据是否存在
let
而改变。 - 最好提及可变性作为变量不能移入闭包的原因。