Почему "явное ограничение времени жизни" для 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 объект будет захвачен в некотором кадре стека).

Другие вопросы по тегам