2015-08-25 3 views
6

ich einen Zug auf einem &'a [u8] umzusetzen versuche und es in einer Implementierung zu verwenden, die einen höheren Rang Lebensdauer verwendet, zum Beispiel:Ärger Umsetzung höherrangigen Typ Lebensdauer für ein Byte Scheibe gebunden

pub trait IntoTest<'a, T> { 
    fn into_test(&'a self) -> T where Self: Sized; 
} 

impl<'a> IntoTest<'a, &'a [u8]> for &'a [u8] { 
    fn into_test(&'a self) -> &'a [u8] { 
     self 
    } 
} 

fn higher_ranked_lifetime<T>(test: T) where T: for<'a> IntoTest<'a, &'a [u8]> { 
    let _t = test.into_test(); 
} 

fn main() { 
    println!("Hello, world!"); 
    let vec = vec![1u8]; 
    let slice = &vec[..]; 
    higher_ranked_lifetime(slice); 
} 

Short URL: http://is.gd/1QKhYk

Der Fehler ich erhalte ist:

<anon>:19:5: 19:27 error: the trait `for<'a> IntoTest<'a, &'a [u8]>` is not implemented for the type `&[u8]` [E0277] 
<anon>:19  higher_ranked_lifetime(slice); 

Wie soll ich das tun? Ist das überhaupt richtig? Ich möchte meine nicht auf eine bestimmte Lebensdauer beschränken, aber sie muss auf alle Byte-Slices anwendbar sein, die an sie übergeben werden.

+0

Eine allgemeine Faustregel für Lebensdauern: Es ist selten, dass mehrere Eingänge die gleiche Lebensdauer haben. –

+0

@MatthieuM. Ich bin mir nicht sicher, ob ich dem zustimme. Wenn Sie mehrere Verweise auf die gleiche Lebensdauer zusammenfassen, kann dies die Auswahl der Dinge, die Sie tun können, sicherlich einschränken, aber es erleichtert Ihnen auch, darüber nachzudenken. Ich denke, mein Prozess ist das Gegenteil von Ihrem Vorschlag - ich gehe davon aus, dass alles die gleiche Lebenszeit ist, bis ich auf einen Fall stoße, in dem mehrere unterschiedliche Leben benötigt werden. – Shepmaster

Antwort

6

Dies ist kein richtiger Weg, und der Compiler hat Recht.

Eine Möglichkeit, Sie sehen, warum es so ist, ist auf die Art zu suchen (die Scheibe) und der Zug Sie denken, es Seite an Seite implementiert:

for<'a> IntoTest<'a, &'a [u8]> 
&'a [u8] 

Hier habe ich auf ein Leben lang Parameter hinzugefügt haben die Scheibe für Klarheit. Sie können sehen, dass in der Eigenschaft gebunden der Lebensdauerparameter 'abound durch den Qualifier for ist, mit anderen Worten, diese Deklaration ist in sich abgeschlossen, es hängt von nichts im externen Bereich ab.

In der Scheibe ist jedoch der Lebensdauer-Parameter 'afrei - es ist in einigen externen Bereich definiert, zum Beispiel durch lebenslange Elision. Daher gibt es einfach keine Möglichkeit, dass das Slice Ihre Trait-Implementierung erfüllen kann. Denn es ist Ihr Zug zur Arbeit sollte wie folgt umgesetzt werden:

impl<'a, 'b> IntoTest<'a, &'a [u8]> for &'b [u8] { 
    fn into_test(&'a self) -> &'a [u8] { 
     unimplemented!() 
    } 
} 

die compiles, obwohl es nicht und konnte es nicht tun, was Sie wollen. Sie können sehen, dass in dieser Deklaration Lebensdauern des Slice und in der Merkmalssignatur disjunkt sind, daher erfüllen Slices die for<'a> -basierte Grenze.

Es gibt eine andere Möglichkeit, dieses Problem zu betrachten. T: for<'a> IntoTest<'a, &'a [u8]> gebunden bedeutet, dass der Typ T das Merkmal für jeden möglichen Lebensdauerparameter dieses Merkmals implementiert, sodass die Funktion selbst entscheiden kann, welche Lebensdauer sie wünscht. Zum Beispiel könnte es 'static anfordern. Aber natürlich in Ihrem Code ist &[u8] an den Vektor in der Hauptmethode gebunden und kann nicht 'static sein. Daher wird die Korrektheit verletzt - diese &[u8] kann keine Lebensdauer bieten, die der Benutzer wünscht, und implementiert daher for<'a> IntoTest<'a, &'a [u8]> nicht.

Beachten Sie, dass nur eine Lebensdauer Parameter an die generische Funktion hinzugefügt wird nicht funktionieren:

fn higher_ranked_lifetime<'a, T>(test: T) where T: IntoTest<'a, &'a [u8]> { 
    let _t = test.into_test(); 
} 

Es wird dieser Fehler:

<anon>:12:14: 12:18 error: `test` does not live long enough 
<anon>:12  let _t = test.into_test(); 
         ^~~~ 
<anon>:11:79: 13:2 note: reference must be valid for the lifetime 'a as defined on the block at 11:78... 
<anon>:11 fn higher_ranked_lifetime<'a, T>(test: T) where T: IntoTest<'a, &'a [u8]> { 
<anon>:12  let _t = test.into_test(); 
<anon>:13 } 
<anon>:11:79: 13:2 note: ...but borrowed value is only valid for the scope of parameters for function at 11:78 
<anon>:11 fn higher_ranked_lifetime<'a, T>(test: T) where T: IntoTest<'a, &'a [u8]> { 
<anon>:12  let _t = test.into_test(); 
<anon>:13 } 

Und das ist wieder richtig. Denken Sie daran, dass Ihre Eigenschaft wie folgt definiert ist:

pub trait IntoTest<'a, T> { 
    fn into_test(&'a self) -> T where Self: Sized; 
} 

Hier können Sie verlangen, dass self durch Verweis mit der gleichen Lebensdauer als die Lebensdauer Parameter des Merkmals übergeben wird.Jedoch macht es die obige Erklärung der generischen Funktion diese Methode nicht aufrufbar im Prinzip:

fn higher_ranked_lifetime<'a, T>(test: T) where T: IntoTest<'a, &'a [u8]> 

hier das Merkmal angegeben Lebensdauer Parameter gleich die Lebensdauer Parameter der Funktion zu haben. test Parameter selbst lebt jedoch nur durch den Körper der Funktion. Daher ist jede Bezugnahme auf test genommen, einschließlich der impliziten beim Aufruf into_test():

let _t = (&test).into_test(); 

Lebensdauer haben wird streng kleiner als die Lebensdauer Parameter, und so kann es nicht als Parameter für into_test() Verfahren verwendet werden. Genau darum geht es im Fehler.

Da Sie nicht erklärt haben, was Sie wirklich brauchen, ist es schwer zu sagen, was Sie tun sollten. Ich denke, eine der allgemeinsten Wege wäre, nur auf einem Merkmal Ihres Lebens Parameter fallen und das Merkmal Methode self von Wert annehmen zu machen, und befestigen Sie die generische Funktion entsprechend:

pub trait IntoTest<T> { 
    fn into_test(self) -> T; 
} 

impl<'a> IntoTest<&'a [u8]> for &'a [u8] { 
    fn into_test(self) -> &'a [u8] { 
     self 
    } 
} 

fn higher_ranked_lifetime<'a, T>(test: T) where T: IntoTest<&'a [u8]> { 
    let _t = test.into_test(); 
} 

fn main() { 
    println!("Hello, world!"); 
    let vec = vec![1u8]; 
    let slice = &vec[..]; 
    higher_ranked_lifetime(slice); 
} 

Diese does work weil jetzt das Merkmal selbst hat keine Lebensdauerparameter und fügt keine Anforderungen an den Aufruf hinzu. Lebensdauerparameter werden jetzt in Typen verschoben, die sie implementieren.

+0

Danke, das hilft sehr. Mir war nicht klar, was es bedeutet, eine für <'a> gebundene auf meinen Typ zu haben. – crhino

Verwandte Themen