我没有在Rust文档中找到任何可以解释生命周期elision如何应用于闭包的规则.我们举一个简单的例子:
fn foo(s: &str) {
let id = |x: &str| x;
println!("{}", id(s));
}
fn main() {
foo("string");
}
Run Code Online (Sandbox Code Playgroud)
我认为foo函数中的闭包将类似于以下代码:
fn foo(s: &str) {
struct Id; // A helper structure for closure
impl Id {
fn id(self: Self, x: &str) -> &str { &x }
}
let id = Id; // Creating a closure
println!("{}", id.id(s));
}
Run Code Online (Sandbox Code Playgroud)
后者工作正常,但前者无法编译并产生关于冲突的生命周期要求的长错误消息:
t3.rs:2:24: 2:25 error: cannot infer an appropriate lifetime due to conflicting requirements [E0495]
t3.rs:2 let id = |x: &str| x;
^
t3.rs:2:24: 2:25 note: first, the lifetime cannot outlive the anonymous lifetime #1 defined on the block at 2:23...
t3.rs:2 let id = |x: &str| x;
^
t3.rs:2:24: 2:25 note: ...so that expression is assignable (expected `&str`, found `&str`)
t3.rs:2 let id = |x: &str| x;
^
<std macros>:3:11: 3:36 note: but, the lifetime must be valid for the expression at 3:10...
<std macros>:3 print ! ( concat ! ( $ fmt , "\n" ) , $ ( $ arg ) * ) ) ;
^~~~~~~~~~~~~~~~~~~~~~~~~
<std macros>:2:25: 2:56 note: in this expansion of format_args!
<std macros>:3:1: 3:54 note: in this expansion of print! (defined in <std macros>)
t3.rs:3:5: 3:27 note: in this expansion of println! (defined in <std macros>)
<std macros>:3:11: 3:36 note: ...so type `(&&str,)` of expression is valid during the expression
<std macros>:3 print ! ( concat ! ( $ fmt , "\n" ) , $ ( $ arg ) * ) ) ;
^~~~~~~~~~~~~~~~~~~~~~~~~
<std macros>:2:25: 2:56 note: in this expansion of format_args!
<std macros>:3:1: 3:54 note: in this expansion of print! (defined in <std macros>)
t3.rs:3:5: 3:27 note: in this expansion of println! (defined in <std macros>)
error: aborting due to previous error
Run Code Online (Sandbox Code Playgroud)
我想知道为什么Rust无法在简单的闭包中推断出适当的生命周期,就像我上面写的那样.此外,为什么编译器认为生命周期中存在冲突的要求.
小智 0
闭包无法从方法签名推断生命周期。实际上,您在方法签名中定义了一个生命周期,假设它是隐式的'a,另一个生命周期是隐式的'b在闭包中定义。
匹配生命周期,它将编译。
fn foo<'a>(s: &'a str) {
let id = |x: &'a str| x;
println!("{}", id(s))
}
fn main() {
foo("string");
}
Run Code Online (Sandbox Code Playgroud)