我正在尝试编写一个返回盒装闭包的函数,该函数可以处理对任何类型的引用
寿命。当编写特定实例时,一切正常。但是在编写泛型时
版本,我遇到了终身问题。
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| {})
}
我不明白为什么闭包需要类型参数的寿命比它长(没有存储或任何东西......)。它适用于带有 HRTB 的非通用版本,只是感觉应该可以使其与通用版本一起工作。
另外,如果我尝试使用通用版本编写特定版本,则会收到类型错误
// 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
关于如何进行这项工作有什么想法吗?
()
类型参数有生命周期限制。该生命周期界限是所有实现者生命周期参数中最短的一个。你忽略了它generate_closure_gen
,所以编译器推断它,但如果我们显式地写出来,函数定义将如下所示:
fn generate_closure_gen<'a, C: 'a>() -> Box<Fn(&C)> {
Box::new(|c: &C| {})
}
但是,进行此更改并不能解决我们的问题。
要理解为什么,我们需要弄清楚什么C
被推断为。你用一个来调用闭包&'y Parameter<'x>
,并且闭包接受for<'b> &'b C
, so C
is Parameter<'x>
. Parameter<'x>
有一个生命周期参数,它将影响生命周期界限C
.
泛型函数中的生命周期参数必须替换为在函数调用之前开始的生命周期。在这种情况下,这意味着任何的生命周期C
我们传递给闭包的调用必须在调用之前有效generate_closure_gen
。那是因为C
绑定到特定的生命周期,而不是任何生命周期;即当C
is Parameter<'x>
, the 'x
必须提前知道;我们不能有不同的'x
每次我们调用闭包时。换句话说,您想要的是这样的:
fn generate_closure_gen<C: for<'a> 'a>() -> Box<Fn(&C)> {
Box::new(|c| {})
}
但不幸的是,从 Rust 1.7 开始,这是不合法的。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)