Wenn wir this ausführen, dann erhalten wir korrekt den Fehler "nicht zu unveränderlichen Feld a.x
zuweisen".Interior Mutabilität vs Daten zu verbergen, um den Verweis auf eine veränderbare Borrow behoben
Wenn wir die zwei //
Kommentare entfernen, und diese schlechte Zeile auskommentieren, dann erhalten wir den Fehler "kann Daten in einer &
Referenz nicht zuweisen". Dies macht Sinn, weil &mut
keine innere Veränderlichkeit bietet. Wir können eine &A
frei reborrow, so dass dies keinen veränderbaren Zugang geben darf, ala &&mut
ist &&
.
Wenn wir beide die //
Kommentare und die /* */
Kommentare entfernen, dann stellt das Ganze, die schlechte Linie ermöglicht, dass unsere invariant verletzt, dass a.x
darf nie wieder etwas anderes hingewiesen werden.
pub struct A<'a> {
pub x: &'a mut [u8; 3],
}
fn main() {
let y = &mut [7u8; 3];
let /*mut*/ a = A { x: &mut [0u8; 3] };
a.x[0] = 3;
a.x = y; //// This must be prevented!
{
// let b = &/*mut*/ a;
// b.x[1] = 2;
}
println!("{:?}", a.x);
}
Wie sollte man diese Invarianten behaupten, dass x
darf nicht verändert werden? Wir könnten das Feld privat machen, während wir öffentliche Dereferenzierungsmethoden bereitstellen, außer das Schreiben von Konstruktoren für A
in inakzeptabel.
Wir können den widerlichen Konstruktor vermeiden, indem wir ein A
ein privates Mitglied eines Wrappers struct AA(A)
machen, der selbst die öffentlichen Dereferenzierungsmethoden hostet. Jetzt AA
benötigt einen trivialen Konstruktor, aber es braucht keine Argumente für alle Felder von A
, wirkt sich nicht auf die Reihenfolge der Ausführung, etc. Dies wird schmerzhaft, wenn wir einige Eigenschaften sowohl für A
als auch AA
implementiert benötigen.
Noch ein anderer Ansatz wäre, die interne Veränderlichkeit zu verwenden, indem man mit Cell<A>
arbeitet, mit Cell::replace
darauf zugreift und es später zurücksetzt. Das klingt sehr problematisch, zeigt aber, dass mehr Lösungen existieren.
Alle saubereren Ansätze?
Die andere Option ist die Verwendung einer 'Zelle' innerhalb des Arrays. Hast du das versucht? –