It has been said that the Borrow Checker has only a limited ability to analyse code and therefore needs hints in the form of lifetime parameters. So, I had a play with this simple piece of code.
fn pick_first(x: &i32, y: &i32) -> &i32 {
println!("first parameter {}; second parameter {}", x, y);
x
}
fn main() {
let x = 42;
let y = 43;
let r = pick_first(&x, &y);
println!("the first number was {}", r);
}
For obvious reasons I get a compiler error:
error[E0106]: missing lifetime specifier
--> src/main.rs:1:36
|
1 | fn pick_first(x: &i32, y: &i32) -> &i32 {
| ---- ---- ^ expected named lifetime parameter
|
= help: this function's return type contains a borrowed value, but the signature does not say whether it is borrowed from `x` or `y`
So, I introduce lifetime parameters for both input parameters and the output; I pick different lifetimes 'x
and 'y
for both x
and y
, respectively. As you would expect that compiles and runs just fine.
fn pick_first<'x, 'y>(x: &'x i32, y: &'y i32) -> &'x i32 { ... }
However, then I got curious and wondered whether I could lie to the Borrow Checker and pretend that the result was borrowed from y
rather than x
...
fn pick_first<'x, 'y>(x: &'x i32, y: &'y i32) -> &'y i32 {
println!("first parameter {}; second parameter {}", x, y);
x
}
...and as it turns out, I cannot:
error[E0623]: lifetime mismatch
--> src/main.rs:3:5
|
1 | fn pick_first<'x, 'y>(x: &'x i32, y: &'y i32) -> &'y i32 {
| ------- -------
| |
| this parameter and the return type are declared with different lifetimes...
2 | println!("first parameter {}; second parameter {}", x, y);
3 | x
| ^ ...but data from `x` is returned here
So, somehow the Borrow Checker does analyse the code and can tell me that I am lying. Given that, why do I need the lifetime parameters at all in this case? It seems like the Burrow Checker is fully aware of what's going on here.
I guess more generally, I am wondering: Can the Borrow Checker be lied to? That is, can I specify lifetimes that pass the Borrow Checker that will ultimately lead to a dangling pointer?