Verwendung habe ich ein Problem mit dem Checker borrow, wenn Zügen als Typparameter in einer Struktur mit:Borrow Prüfung versagt, wenn Züge als Typ-Parameter
trait Trait {}
struct FooBar;
impl Trait for FooBar{}
struct Observer<Arg> {
action: Box<Fn(Arg) + Send>,
// Other fields
}
impl <Arg> Observer<Arg> {
fn new(action: Box<Fn(Arg) + Send>) -> Observer<Arg> {
Observer{action: action}
}
fn execute(&self, arg: Arg) {
(*self.action)(arg);
}
}
fn test() {
let mut foobar = FooBar;
{
let mut observer = Observer::new(Box::new(|&: param: &mut Trait| {
// do something with param here
}));
observer.execute(&mut foobar); // First borrow passes ...
observer.execute(&mut foobar); // This fails as "foobar" is already borrowed
} // The previous borrow ends here (lifetime of "observer")
}
Die Ausgabe lautet:
error: cannot borrow `foobar` as mutable more than once at a time
observer.execute(&mut foobar); // This fails as "foobar" is already borrowed
^~~~~~
note: previous borrow of `foobar` occurs here; the mutable borrow prevents subsequent moves, borrows, or modification of `foobar` until the borrow ends
observer.execute(&mut foobar); // First borrow passes ...
^~~~~~
note: previous borrow ends here
{
...
} // The previous borrow ends here (lifetime of "observer")
^
Doch die folgendes Beispiel funktioniert:
trait Trait {}
struct FooBar;
impl Trait for FooBar{}
struct Observer {
action: Box<Fn(&mut Trait) + Send>,
// Other fields
}
impl Observer {
fn new(action: Box<Fn(&mut Trait) + Send>) -> Observer {
Observer{action: action}
}
fn execute(&self, arg: &mut Trait) {
(*self.action)(arg);
}
}
fn test() {
let mut foobar = FooBar;
{
let mut observer = Observer::new(Box::new(|&: param: &mut Trait| {
// do something with param here
}));
observer.execute(&mut foobar);
observer.execute(&mut foobar);
}
}
Das sieht wirklich komisch aus, denn das zweite Beispiel ist nur ein Instanti des ersten Beispiels, und ich könnte wahrscheinlich (schmerzlich) dasselbe mit Makros implementieren.
Ich denke, das ziemlich schwierig ist, da ich den Typen der von der Schließung genommen Parameter muß wissen, aber ich brauche nicht diese Referenz zu speichern ...
Ist das ein Fehler in den borrow Checker? Oder mache ich etwas falsch?
rustc 1.0.0-nightly (44a287e6e 2015-01-08 17:03:40 -0800)
EDIT 1: präzisierte der Anwendungsfall
EDIT 2: Wie unten in der Antwort erläutert, ist das Problem, dass die borrow checker die Lebensdauer von Observer<&mut Type>
zwingt die gleiche wie die &mut Type
zu sein, also in Tatsache ist, dass das Problem nicht damit zusammenhängt, dass wir ein Merkmal als Typparameter verwenden (dasselbe gilt für eine tatsächliche Struktur).
Also in meinem Fall kann ich durch die Definition Observer<Arg>
wie diese eine Abhilfe haben:
struct Observer<Arg> {
action: Box<Fn(&mut Arg) + Send>,
}
so der Typ-Parameter Arg selbst keine Referenz ist, aber das macht den Code weniger generisch. Hat jemand eine bessere Lösung?