Зачем нужна явная привязка времени жизни для Box <T> в struct?
Примечание редактора: этот код больше не производит такую же ошибку после RFC 599, но концепции, обсуждаемые в ответах, по-прежнему действительны.
Я пытаюсь скомпилировать этот код:
trait A {
fn f(&self);
}
struct S {
a: Box<A>,
}
и я получаю эту ошибку:
a.rs:6:13: 6:14 error: explicit lifetime bound required
a.rs:6 a: Box<A>,
Я хочу, чтобы S.a
имел экземпляр A
и не видел, как это время жизни здесь подходит. Что мне нужно сделать, чтобы сделать компилятор счастливым?
Моя версия ржавчины:
rustc --version
rustc 0.12.0-pre-nightly (79a5448f4 2014-09-13 20:36:02 +0000)
Ответы
Ответ 1
Проблема здесь в том, что черта может быть реализована и для ссылок, поэтому, если вы не укажете требуемое время жизни для "Коробки", можно сохранить что-нибудь там.
Вы можете узнать о жизненных требованиях в этом rfc.
Итак, одно из возможных решений - связать время жизни так Send
(мы помещаем я в S):
trait A {
fn f(&self);
}
struct I;
impl A for I {
fn f(&self) {
println!("A for I")
}
}
struct S {
a: Box<A + Send>
}
fn main() {
let s = S {
a: box I
};
s.a.f();
}
Другой устанавливает время жизни на 'a
(мы можем поместить ссылку & я или я в S):
trait A {
fn f(&self);
}
struct I;
impl A for I {
fn f(&self) {
println!("A for I")
}
}
impl <'a> A for &'a I {
fn f(&self) {
println!("A for &I")
}
}
struct S<'a> {
a: Box<A + 'a>
}
fn main() {
let s = S {
a: box &I
};
s.a.f();
}
Обратите внимание, что это более общее, и мы можем хранить как ссылки, так и имеющиеся данные (Send
вид, который имеет время жизни 'static
), но вам нужен параметр lifetime везде, где используется тип.
Ответ 2
(Слегка педантичная точка: A
является признаком, поэтому S
не владеет экземпляром A
, он владеет экземпляром в штучной упаковке некоторого типа, который реализует A
.)
Объект-объект представляет данные с неизвестным типом, то есть единственное, что известно о данных, это то, что он реализует признак A
. Поскольку тип неизвестен, компилятор не может напрямую рассуждать о времени жизни содержащихся данных и поэтому требует, чтобы эта информация явно указывалась в типе объекта признаков.
Это делается через Trait+'lifetime
. Самый простой путь - просто использовать 'static
, то есть полностью запретить хранение данных, которые могут стать недействительными из-за областей:
a: Box<A + 'static>
Раньше (до появления объектов с объектами с ограничением по времени и этого сообщения об ошибке explicit lifetime bound required
) все объекты объектов с боксами были неявно 'static
, то есть эта ограниченная форма была единственным выбором.
Наиболее гибкой формой является внешний вид жизни:
struct S<'x> {
a: Box<A + 'x>
}
Это позволяет S
хранить объект-объект любого типа, который реализует A
, возможно, с некоторыми ограничениями областей, в которых допустим S
(т.е. для типов, для которых 'x
меньше 'static
объект S
будет помещен в некоторый кадр стека).