Почему "явное ограничение времени жизни" для Box<T> в структуре?
Примечание редактора: этот код больше не выдает ту же ошибку после внедрения 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
и не вижу, как это время подходит здесь. Что мне нужно сделать, чтобы компилятор был доволен?
Моя версия Rust:
rustc --version
rustc 0.12.0-pre-nightly (79a5448f4 2014-09-13 20:36:02 +0000)
2 ответа
Проблема здесь в том, что черта может быть реализована и для ссылок, поэтому, если вы не укажете требуемое время жизни для Box, там может храниться что угодно.
Вы можете узнать о пожизненных требованиях в этом RFC.
Таким образом, одним из возможных решений является привязка времени жизни так, Send
(мы ставим I в 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
) но вам требуется параметр времени жизни везде, где используется тип.
(Слегка педантичный момент: это 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
объект будет захвачен в некотором кадре стека).