und*_*ain 5 rust borrow-checker
我有以下代码:
struct Solver<'a> {
guesses: Vec<&'a str>,
}
impl<'a> Solver<'a> {
fn register_guess(&mut self, guess: &'a str) {
self.guesses.push(guess);
}
}
fn foo(mut solver: Solver, guess: &str) {
solver.register_guess(guess)
}
Run Code Online (Sandbox Code Playgroud)
它不编译:
|
11 | fn foo(mut solver: Solver, guess: &str) {
| ---------- - let's call the lifetime of this reference `'1`
| |
| has type `Solver<'2>`
12 | solver.register_guess(guess)
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ argument requires that `'1` must outlive `'2`
Run Code Online (Sandbox Code Playgroud)
错误消息表明该参数guess必须超过生存期solver。对我来说很明显这是真的:solverends的生命周期在函数的末尾,而of的生命周期则guess不然。这似乎是编译器应该能够推断出来的,并且编译时不会出错。
为什么不是这样呢?这段代码真的有办法solver继续存在吗guess?或者只是编译器根本不尝试进行这种推理?
我知道如何修复它 --- 将功能更改为fn foo<'a>(mut solver: Solver<'a>, guess: &'a str)--- 但我问为什么我必须这样做。
虽然solver它本身无法存活guess,但它所指的生命周期却可以。例如,想象一下foo()使用Solver<'static>. 这种求解器会期望猜测&'static str并可能将所引用的数据存储guess在全局变量中。(请记住,编译器不会考虑register_guess()借用检查时的作用foo(),它只考虑其签名。)
更一般地说,可能包含对比自身寿命更长的数据的Solver<'a>引用。没有什么可以阻止将猜测的内容存储在此类引用中。如果不能保证至少活到,那么就根本不合理。例如,采用以下替代定义:'asolverregister_guess()guess'afoo()Solver
struct Solver<'a> {
guesses: &'a mut Vec<&'a str>,
}
Run Code Online (Sandbox Code Playgroud)
如果 , 的签名未更改register_guess(),foo()将允许出现如下不健全的代码:
fn main() {
let mut guesses = vec![];
let solver = Solver { guesses: &mut guesses };
{
let guess = "foo".to_string();
// stores temporary "foo" to guesses, which outlives it
foo(solver, guess.as_str());
}
println!("{}", guesses[0]); // UB: use after free
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
880 次 |
| 最近记录: |