Rust の 'a
はあくまで生存区間の情報で、どの変数を参照しているかという情報は持っていないはず。実際に、たとえば
fn foo<'a>(x: &'a mut u32) {
let r: &'a [u32] = unsafe { std::slice::from_raw_parts(x, 1) };
*x = 0;
dbg!(r)
}
はコンパイルできてしまう。しかし
fn bar<'a>(x: &'a u32) -> &'a [u32] {
unsafe { std::slice::from_raw_parts(x, 1) }
}
fn main() {
let mut x = 0;
let r = bar(&x);
x = 0;
dbg!(r);
}
はちゃんとエラーになる。次の例もうまくいく。
fn baz<'a, 'b>(x: &'a u32, y: &'b u32) -> &'b u32 { ... }
fn main() {
let mut x = 0;
let mut y = 0;
let r = baz(&x, &y);
x = 1; // ok.
y = 1; // err.
dbg!(r);
}
これらを借用チェッカーが適切に処理できるのはなぜか。関数の戻り値とライフタイムが一致する引数を参照元の変数と認識する、ということだろうか。