问题描述
我正在尝试编写一个函数,该函数返回一个盒装的闭包,该闭包可以处理对任何类型的引用一生.在编写特定实例时,一切正常.但是当写一个泛型版本,我遇到一生的问题.
I am trying to write a function returning a boxed closure that can work on references to types with anylifetime. When writing a specific instance, everything works fine. But when writing a genericversion, I run into lifetime problems.
struct Parameter<'a> {
s: &'a str,
}
fn main() {
let closure = generate_closure_gen();
let string = String::from("Hello World!");
let parameter = Parameter { s: &string }; // Error: string does not live long enough
closure(¶meter);
}
// This one works fine
// Desugared version for Box<Fn(&Parameter)>
fn generate_closure() -> Box<for <'a, 'r> Fn(&'r Parameter<'a>)> {
Box::new(|c: &Parameter| {})
}
// This one gives lifetime errors
fn generate_closure_gen<C>() -> Box<Fn(&C)> {
Box::new(|c: &C| {})
}
我不明白为什么闭包需要type参数的生存期比它更长(没有存储空间或其他任何东西……).它适用于HRTB的非通用版本,只是感觉应该有可能使其与通用版本一起使用.
另外,如果我尝试使用通用版本编写特定版本,则会出现类型错误
I don't see why the closure needs the type parameter to live longer than it (there is no storage or anything ...). And it works for the non-generic version with HRTB, it just feels like it should be possible to make it work with the generic version.
Also, if I try to write the specific version using the generic version, I get a type error
// Desugared version for Box<Fn(&Parameter)>
fn generate_closure_2() -> Box<for <'a, 'r> Fn(&'r Parameter<'a>)> {
generate_closure_gen()
}
src/main.rs:22:5: 22:27 error: mismatched types:
expected `Box<for<'r, 'r> core::ops::Fn(&'r Parameter<'r>) + 'static>`,
found `Box<for<'r> core::ops::Fn(&'r _) + 'static>`
(expected concrete lifetime,
found bound lifetime parameter ) [E0308]
src/main.rs:22 generate_closure_gen()
^~~~~~~~~~~~~~~~~~~~~~
src/main.rs:22:5: 22:27 help: run `rustc --explain E0308` to see a detailed explanation
关于如何进行这项工作的任何想法?
Any idea on how to make this work?
(游戏围栏链接)
推荐答案
类型参数具有生存期限制.该生命周期限制是实现者所有生命周期参数中最短的.您在generate_closure_gen
上省略了它,所以编译器会推断出它,但是如果我们明确地将其写出,函数定义将如下所示:
Type parameters have a lifetime bound. That lifetime bound is the shortest of all of the implementor's lifetime parameters. You omitted it on generate_closure_gen
, so the compiler inferred it, but if we explicitly wrote it out, the function definition would look like this:
fn generate_closure_gen<'a, C: 'a>() -> Box<Fn(&C)> {
Box::new(|c: &C| {})
}
但是,进行此更改并不能解决我们的问题.
Making this change doesn't solve our problem, though.
要了解原因,我们需要弄清楚C
是什么.您用&'y Parameter<'x>
调用闭包,闭包接受for<'b> &'b C
,因此C
是Parameter<'x>
. Parameter<'x>
有一个生存期参数,它将对C
上的生存期产生影响.
To understand why, we need to figure out what C
is inferred to be. You call the closure with a &'y Parameter<'x>
, and the closure accepts for<'b> &'b C
, so C
is Parameter<'x>
. Parameter<'x>
has a lifetime parameter, which will have an influence on the lifetime bound on C
.
泛型函数中的生存期参数必须替换为在函数调用之前开始的生存期.在这种情况下,这意味着我们传递给闭包的任何C
的生存期必须在调用generate_closure_gen
之前有效.这是因为C
绑定到特定的生存期,而不是任何生存期.即C
为Parameter<'x>
时,必须事先知道'x
;每次调用闭包时,我们都不能使用不同的'x
.换句话说,您希望拥有的是这样的东西:
Lifetime parameters in generic functions must be substituted with lifetimes that start before the function call. In this case, this means that the lifetime of any C
we pass to the closure must be valid before the call to generate_closure_gen
. That's because C
is bound to a specific lifetime, not to any lifetime; i.e. when C
is Parameter<'x>
, the 'x
must be known in advance; we can't have a different 'x
each time we call the closure. In other words, what you'd like to have is something like this:
fn generate_closure_gen<C: for<'a> 'a>() -> Box<Fn(&C)> {
Box::new(|c| {})
}
但是不幸的是,从Rust 1.7开始这是不合法的.
But unfortunately, that isn't legal as of Rust 1.7.
这篇关于特质较高的等级限制和盒装封口寿命问题的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!