我试图让以下简化代码进行编译:
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
& #39; s调用,包括对其输入值的相同生命周期的引用,即string
。
然而,我对三点感到困惑:
match
函数调用的结果,然后为两个分支返回()
。为什么function
返回的值的有效期是否无条件地被抛弃?function
的调用替换为okay
(具有相同签名)的直接引用,则无需投诉即可编译。答案 0 :(得分:2)
TL; DR:使用the for<'a>
syntax为该函数设置一个特定的生命周期,而不是从使用它的上下文中取一个。
do_stuff_with_function
的生命时间缩短隐藏了这里发生的事情。你的实际生命是:
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>
(等等)的函数的任何内容。
这与您的代码基本相同(+允许闭包)。但是,我仍然必须将生命周期命名为fn do_stuff_with_function<F>(function: F) where F: for<'a> Fn(&'a str) -> Result<(), &'a str> {
的调用。
所以这是一个freaky type magic:
do_stuff_with_function
允许使用Fn
语法将生命周期的定义从for<'a>
移动到F
的定义。这种方式特定于do_stuff_with_function
,而不是@RunWith(SpringRunner.class)
@RestClientTest({XyzDaoImpl.class})
@TestPropertySource(locations = "classpath:application-test.properties")
public class XyzDaoTest {
@Autowired
XyzDaoImpl xyzDaoImpl;
@Test
public void testGetXyzDetails(){
assertThat(xyzDaoImpl.getXyzDetails("123", null)).isNotNull();
}
}
参数。