我正在尝试使用以下简化代码进行编译:
type FunctionType<'input> = fn(input_string: &'input str) -> Result<(), &'input str>;
fn okay<'input>(_input_string: &'input str) -> Result<(), &'input str> {
Ok(())
}
fn do_stuff_with_function(function: FunctionType) {
let string = String::new();
match function(string.as_str()) {
Ok(_) => {},
Err(_) => {},
}
}
fn main() {
do_stuff_with_function(okay);
}
游乐场抱怨:
error[E0597]: `string` does not live long enough
--> src/main.rs:13:20
|
13 | match function(string.as_str()) {
| ^^^^^^ does not live long enough
...
18 | }
| - borrowed value only lives until here
|
note: borrowed value must be valid for the anonymous lifetime #1 defined on the function body at 11:1...
--> src/main.rs:11:1
|
11 | / fn do_stuff_with_function(function: FunctionType) {
12 | | let string = String::new();
13 | | match function(string.as_str()) {
14 | | Ok(_) => {},
... |
17 | |
18 | | }
| |_^
我理解为什么错误会在其他情况下触发:string
只能执行do_stuff_with_function
,但do_stuff_with_function
返回function
调用的值,该调用包括对其输入值的相同生命周期的引用,即string
。
但是,我对三点感到困惑:
match
函数调用的结果,然后为两个分支返回()
。为什么function
返回的值的有效期如果被无条件抛弃则很重要?function
(具有相同签名)的直接引用替换对参数okay
的调用,则编译无需投诉。TL; DR:使用the for<'a>
syntax为函数设置特定的生命周期,而不是从使用它的上下文中取一个。
在do_stuff_with_function
的args上终身省略隐藏了这里发生的事情。你的实际生命是:
fn do_stuff_with_function<'a>(function: FunctionType<'a>) {
在函数参数中声明的这个生命周期并不意味着“我将在稍后提出一些随机的短暂生命周期”,而是“在调用此函数时已经存在的生命周期”。
这些生命周期注释不是通配符,而更像是标识符,用于跟踪值来自何处以及它们将去往何处。例如,可以使用它们来澄清这样的情况:
fn do_stuff_with_function<'a>(function: FunctionType<'a>, t: &'a str) {
match function(t) {
Ok(_) => {},
Err(_) => {},
}
}
fn main() {
let string = String::new();
do_stuff_with_function(okay, string.as_str());
}
但是,这个问题在Rust中是可以解决的,但只需要更高级的语法。出于解释的目的,首先,让我们将其更改为:
fn do_stuff_with_function<'a, F>(function: F) where F: Fn(&'a str) -> Result<(), &'a str> {
这意味着“为每个独特的do_stuff_with_function
复制F
,这可能是任何看起来像&'a str
(等等)的函数。这与你的代码基本相同(+允许闭包)。但是,我仍然必须命名为一生与do_stuff_with_function<'a>
的呼唤联系在一起。
所以这是一个freaky type magic:
fn do_stuff_with_function<F>(function: F) where F: for<'a> Fn(&'a str) -> Result<(), &'a str> {
这允许使用do_stuff_with_function
语法将生命周期的定义从Fn
移动到for<'a>
的定义。这种方式特定于F
,而不是do_stuff_with_function
论点。