2016-04-09 9 views
2

Ich habe folgende struct:Warum benötigt dieses Strukturelement zwei Lebenszeiten?

struct PeekableRead<'a, R: Read> { 
    reader: &'a mut R, 
    peeked_octet: Option<u8>, 
} 

Welche rustc nicht mag:

…:27:1: 30:2 error: the parameter type `R` may not live long enough [E0309] 
…:27 struct PeekableRead<'a, R: Read> { 
…:28 reader: &'a mut R, 
…:29 peeked_octet: Option<u8>, 
…:30 } 
…:27:1: 30:2 help: run `rustc --explain E0309` to see a detailed explanation 
…:27:1: 30:2 help: consider adding an explicit lifetime bound `R: 'a`... 
…:27:1: 30:2 note: ...so that the reference type `&'a mut R` does not outlive the data it points at 
…:27 struct PeekableRead<'a, R: Read> { 
…:28 reader: &'a mut R, 
…:29 peeked_octet: Option<u8>, 
…:30 } 

Wenn ich hinzufügen, um die Lebensdauer zu R, wie in, R: Read + 'a, es funktioniert. Aber warum? Gibt die 'a auf der Referenz nicht die Lebensdauer an? Muss nicht reader: &'a mut R, in einer struct PeekableRead<'a> leben so lange wie die Struktur selbst, und damit "lang genug"?

Seltsamerweise brauche ich beide; Wenn ich 'a zu R hinzufüge und es von der Referenz entferne, bekomme ich immer noch error: missing lifetime specifier. Die einzige Art und Weise, wie ich eine erfolgreiche Kompilierung bekomme, ist bei beiden, aber für mich scheinen sie dasselbe redundant zu spezifizieren.

(Auch, warum tut rustc Ausgang der struct zweimal in der Ausgabe? Die zweite sieht aus wie ein Vorschlag, was zu tun ist, aber genau das gleiche zu sein scheint als das, was ich habe ...)

Antwort

2

Doesn't the 'a on the reference specify the lifetime?

Sie gibt die Lebensdauer von der Referenz an, nicht jedoch die Lebensdauer des Wertes, auf den verwiesen wird. Welche Ihre Beobachtung erklärt, dass

if I add 'a to R and remove it from the reference, I still get error: missing lifetime specifier.

Für die Struktur gültig sein müssen wir beide: der Wert darauf wird noch am Leben sein zu müssen, und muss so die Referenz. (Obwohl logisch die erste Bedingung von der Sekunde impliziert wird, da eine Referenz niemals den Wert überleben kann, auf den sie zeigt.).

+1

Sie können 'struct PeekableRead <'a, R:' a + Lesen>' die extern sichtbare API für die Struktur betrachten, während die Felder Implementierungsdetails sind. Diese Motivation ist jedoch keine allgemeine Regel, da wir uns einige Eigenschaften der Struktur vorstellen können, die nicht explizit so geschrieben sind (Varianz jedes generischen Parameters und Auto-Traits). – bluss

0

Der Lebensdauerparameter für eine Referenz bezeichnet die Lebensdauer des Referenzobjekts (d. H. Das Objekt, auf das die Referenz verweist). Dieses Objekt kann eine Referenz oder ein komplexes Objekt sein, das eine oder mehrere Referenzen enthält. Wenn Sie jedoch ein Merkmal verwenden, ist die Lebensdauer der Objekte hinter diesen Referenzen etwas versteckt (das Merkmal selbst kennt diese Lebenszeiten nicht); Lebenszeitgrenzen sind, was der Compiler richtig über diese Lebenszeiten begründet.

Wenn Sie einen generischen Typ hinter einer Referenz verwenden, müssen Sie eine Grenze hinzufügen, um sicherzustellen, dass Instanzen dieses Typs keine Referenzen enthalten, die kürzer sind als die Referenz auf diese Instanzen. Grenzen werden nicht implizit nur basierend auf der Verwendung von Typen hinzugefügt: Die Grenzen sollten nicht basierend auf den Details der Felder in der Struktur und dem Typ, den Sie definieren, geändert werden.

Zum Beispiel implementiert der Typ &'f File (für jeden 'f) Read. Wir können PeekableRead mit diesem Typ instanziieren: das gibt uns eine PeekableRead<&'f File>. PeekableRead<&'f File> speichert eine veränderbare Referenz auf eine &'f File, daher ist der konkrete Typ des reader-Felds &'a mut &'f File. Damit eine solche Referenz gültig ist, muss 'a kürzer oder gleich 'f sein. Wenn 'f kürzer als 'a ist, können Sie die &'f File durch eine ersetzen, die gelöscht wird, bevor die Referenz gelöscht wird, was zu einem ungeeigneten Zeiger führt. Wenn Sie die 'a gebunden an R (d. H.Wenn Sie schreiben R: Read + 'a), sagen Sie "Instanzen von R müssen überleben 'a" (d. h. R enthält möglicherweise keine Referenzen kürzer als 'a).