2014-09-21 8 views
18

Editor's note: This code no longer produces the same error after RFC 599 was implemented, but the concepts discussed in the answers are still valid.Perché è necessario "limite di durata esplicita obbligatorio" per la casella <T> nella struttura?

Sto cercando di compilare il codice:

trait A { 
    fn f(&self); 
} 

struct S { 
    a: Box<A>, 
} 

e sto ottenendo questo errore:

a.rs:6:13: 6:14 error: explicit lifetime bound required 
a.rs:6  a: Box<A>, 

voglio S.a di possedere un 'istanza di A, e non vedere come quella vita è appropriata qui. Cosa devo fare per rendere il compilatore felice?

La mia versione Rust:

rustc --version 
rustc 0.12.0-pre-nightly (79a5448f4 2014-09-13 20:36:02 +0000) 

risposta

16

Il problema qui è che un tratto può essere implementata per i riferimenti, quindi se non si specifica la durata necessaria per Box tutto può essere memorizzato in là.

È possibile visualizzare i requisiti di durata in questo rfc.

Così una possibile soluzione è quella di legare la durata in modo Send (abbiamo messo io in 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(); 
} 

L'altro è l'impostazione della vita per 'a (possiamo mettere un riferimento & I o I per 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(); 
} 

si noti che questo è più generale e siamo in grado di memorizzare entrambi i riferimenti ed i dati di proprietà (Send genere che ha una durata di 'static), ma avete bisogno di un Parame vita ovunque il tipo venga usato.

+0

Grazie per il collegamento RFC, fa luce sulla vita all'interno delle scatole. –

18

(punto leggermente pedante: che A è un tratto, così S non è in possesso di un un'istanza di A, esso è possedere un'istanza scatolato di qualche tipo che implementa A.)

Un oggetto tratto rappresenta i dati con un tipo sconosciuto, ovvero l'unica cosa nota sui dati è che implementa il tratto A. Poiché il tipo non è noto, il compilatore non può direttamente ragionare sulla durata dei dati contenuti, e quindi richiede che queste informazioni siano esplicitamente dichiarate nel tipo di oggetto tratto.

Questo viene effettuato tramite Trait+'lifetime. Il metodo più semplice è usare solo 'static, cioè, non consentire completamente i dati memorizzazione che può diventare validi a causa di scopi:

a: Box<A + 'static> 

In precedenza, (prima la possibilità di trait vita-delimitata oggetti ed è stato introdotto questo messaggio explicit lifetime bound required di errore) tutti gli oggetti tratto box erano implicitamente 'static, ovvero questa forma limitata era l'unica scelta.

La forma più flessibile espone la durata esternamente:

struct S<'x> { 
    a: Box<A + 'x> 
} 

Questo permette S per memorizzare un oggetto tratto di qualsiasi tipo che implementa A, possibilmente con alcune restrizioni sugli ambiti in cui il S è valido (cioè per i tipi per i quali 'x è inferiore a 'static l'oggetto S verrà intrappolato all'interno di uno stack frame).

Problemi correlati