2015-07-19 9 views
6

Wenn Sie die docs for Read überprüfen, akzeptieren die meisten Methoden eine &mut self. Dies ist sinnvoll, da das Lesen von etwas normalerweise einen internen Offset aktualisiert, so dass der nächste Lesevorgang andere Daten zurückgibt. Dies ist jedoch kompiliert:Warum ist es möglich, Read auf einen unveränderlichen Verweis auf Datei zu implementieren?

use std::io::Read; 
use std::fs::File; 

fn main() { 
    let file = File::open("/etc/hosts").unwrap(); 
    let vec = &mut Vec::new(); 
    (&file).read_to_end(vec).unwrap(); 
    println!("{:?}", vec); 
} 

Die Datei ist nicht wandelbar ist, aber die Daten sicher in gelesen werden Dies scheint falsch zu mir.. It was pointed out that there is an impl<'a> Read for &'a File, aber die Tatsache, dass eine unveränderliche Instanz scheinbar mutiert ist, erscheint immer noch seltsam.

+1

Ist die Antwort auf [Warum kann ich File.take() auf einem Referenz nennen?] (Http://stackoverflow.com/q/31503429/395760) lösen dieses oder fragen Sie * warum * 'Read' ist implementiert auf '& File'? – delnan

+1

@delnan Die Frage ist hier: Warum reicht '& file'? Man sollte erwarten, dass '& mut file' benötigt wird. – mdup

+1

@delnan (Ich habe die Frage nicht gestellt, aber) Ich denke nicht, dass diese Frage beantwortet. Es muss etwas anderes passieren. 'read_to_end' sollte entweder mit' & mut File' oder '& mut & File' arbeiten, aber' (& file) 'ist keines davon. – fjh

Antwort

7

Wie @kennytm darauf hingewiesen, a.read_to_end(vec) entspricht Read::read_to_end(&mut a, vec), also (&file).read_to_end(vec) erweitert auf Read::read_to_end(&mut &file, vec). Im letzteren Ausdruck ist &file ein neuer temporärer Wert vom Typ &File. Es gibt kein Problem mit veränderlichen Referenzen auf einen Ausdruck (z. B. &mut 42). Genau das passiert hier. Die Tatsache, dass der Ausdruck ein Verweis auf einen unveränderlichen Wert spielt keine Rolle, weil wir nicht wirklich den Wert durch ein &mut &T mutieren. Die Frage, warum wir die File nicht veränderlich machen können, ist

: File ist im Grunde nur ein newtyped Dateideskriptor, d. H. Ein Index in eine offene Datei-Tabelle, die vom Betriebssystem verwaltet wird. read und Freunde werden diese Beschreiber nicht, ändern, weshalb die File mutiert werden müssen, nicht. Es gibt natürlich Mutationen, aber das geschieht durch das Betriebssystem auf seinen eigenen Datenstrukturen und nicht in Ihrem Benutzer-Land-Rost-Code.

+3

+1 für "Mutation [...] wird vom Betriebssystem auf seinen eigenen Datenstrukturen und nicht in Ihrem Benutzer-Land-Rost-Code getan." Ich glaubte, dass ein (immut) '& File' bedeutete, dass Ihrer Datei nichts passieren konnte; Diese Antwort zeigt, dass dies nicht der Fall ist, was IMO kontraintuitiv ist. Vielleicht verdient dies eine Klarstellung in den Dokumenten. – mdup

+1

@mdup vielleicht ist es für uns am besten, wenn wir uns 'Datei' so vorstellen, als hätte man eine [Zelle] (http://doc.rust-lang.org/std/cell/index.html) irgendeiner Art. – Shepmaster

+2

@Shempmaster: Ja, es ist wie eine Datei hat einen eigenen eingebauten Mutex. Das OS kümmert sich um seine Synchronisation. – sellibitze