Следующий код завершается ошибкой, как и ожидалось:
struct T<'a> {
f: &'a Fn(&'a i32),
}
fn test<'a>(_: &'a i32) {}
fn main() {
let t = T { f: &test };
{
let v = 4;
(t.f)(&v);
}
let v1 = 5;
(t.f)(&v1);
}
выдает ошибку:
error[E0597]: `v` does not live long enough
--> src/main.rs:12:15
|
12 | (t.f)(&v);
| ^^ borrowed value does not live long enough
13 | }
| - `v` dropped here while still borrowed
...
16 | (t.f)(&v1);
| ----- borrow later used here
Причина в том, что объекты признаков являются инвариантными по отношению к своим родовым типам. В результате 'a
, во время разговора t.f()
не будет сокращено для звонка. Я понял это. Однако, если я удалю следующий фрагмент кода:
let v1 = 5;
(t.f)(&v1);
код компилируется нормально, и я тоже это понимаю, так как считаю, что это связано с нелексическими временами жизни.
Вещи становятся интересными, когда я одалживаю t
(или какое-то поле внутри него). Рассмотрим слегка модифицированную версию приведенного выше кода:
struct T<'a> {
f: &'a Fn(&'a i32),
i: i32,
}
fn test<'a>(_: &'a i32) {}
fn main() {
let t = T { f: &test, i: 1 };
let n = &t.i;
{
let v = 4;
(t.f)(&v);
}
println!("{:?}", n);
}
Этот код компилируется, но я не понимаю, почему! Здесь t.i
заимствовано, и в результате t
заимствовано, и оно используется после окончания внутренней области видимости. Я ожидал, что это потерпит неудачу с вышеупомянутой ошибкой компилятора.
В качестве контрапункта следующий код занимает все t
и не компилируется с тем же сообщением, что и выше.
struct T<'a> {
f: &'a Fn(&'a i32),
i: i32,
}
fn test<'a>(_: &'a i32) {}
fn main() {
let t = T { f: &test, i: 1 };
let n = &t;
{
let v = 4;
(t.f)(&v);
}
println!("{:?}", n.i);
}