2015-07-19 5 views
6

Se si controlla lo docs for Read, la maggior parte dei metodi accetta uno &mut self. Ciò ha senso, poiché la lettura da qualcosa di solito aggiorna un offset interno in modo che la lettura successiva restituisca dati diversi. Tuttavia, questo compila:Perché è possibile implementare Read su un riferimento immutabile a File?

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); 
} 

Il file non è mutevole, ma i dati sono certamente in corso la lettura in questo sembra non corretto per me.. It was pointed out that there is an impl<'a> Read for &'a File, ma il fatto che un'istanza immutabile sia apparentemente mutata sembra ancora strano.

+1

La risposta a [Perché è possibile chiamare File.take() su un riferimento?] (Http://stackoverflow.com/q/31503429/395760) risolvere questo problema o si sta chiedendo * perché * 'Leggi' è implementato su '& File'? – delnan

+1

@delnan La domanda qui è: perché '& file' è sufficiente? Ci si dovrebbe aspettare che sia richiesto "e mut file". – mdup

+1

@delnan (Non ho fatto la domanda, ma) Non penso che risponda a questa domanda. Deve esserci qualcos'altro che sta succedendo. 'read_to_end' dovrebbe funzionare su' & mut File' o '& mut & File', ma' (& file) 'non è nessuno di quelli. – fjh

risposta

7

Come indicato da @kennytm, a.read_to_end(vec) equivale a Read::read_to_end(&mut a, vec), quindi (&file).read_to_end(vec) si espande a Read::read_to_end(&mut &file, vec). Nell'ultima espressione, &file è un nuovo valore temporaneo di tipo &File. Non c'è alcun problema nel prendere riferimenti mutabili a un'espressione (ad esempio &mut 42). Questo è esattamente quello che succede qui. Il fatto che l'espressione sia un riferimento a un valore immutabile non ha importanza perché non possiamo effettivamente mutare il valore tramite uno &mut &T.

Per quanto riguarda la questione del perché non abbiamo bisogno del File di essere mutevole: File è fondamentalmente solo un descrittore di file newtyped, vale a dire un indice in una tabella open-file che viene gestito dal sistema operativo. read e gli amici non cambieranno affatto questo descrittore, ed è per questo che lo File non ha bisogno di essere modificato. Ovviamente c'è una mutazione, ma il sistema operativo si basa sulle proprie strutture dati e non sul codice ruggine dell'utente.

+3

+1 per "la mutazione [...] viene eseguita dal sistema operativo sulle proprie strutture dati e non nel codice di ruggine dell'utente". Credevo che avere un (immut) '& File' significava che non poteva accadere nulla al tuo file; questa risposta mostra che non è il caso, che è IMO contro-intuitivo. Forse questo merita un chiarimento nei documenti. – mdup

+1

@mdup forse è meglio per noi pensare a 'File' come se avesse una [cella] (http://doc.rust-lang.org/std/cell/index.html) di qualche tipo. – Shepmaster

+2

@Shepmaster: Sì, è come se un file avesse il suo mutex incorporato. Il sistema operativo si occupa della sua sincronizzazione. – sellibitze