So I've seen this question which explains how serde_json
can both take Readers/Writers by reference or alternatively take ownership of them. Fair enough.
But I don't get how this works for Write
- all of Write
methods require a &mut self
, so I'd think that if I pass a method that only knows its argument is a reference to something that is Write
it can't do anything with it. But this example compiles and works just fine, even though I'm passing a non-mut ref to a method that, one way or another, ends up writing to the referenced file:
extern crate serde_json;
use std::fs::OpenOptions;
use std::error::Error;
fn main() -> Result<(), Box<dyn Error>> {
let file = OpenOptions::new()
.create(true)
.write(true)
.truncate(true)
.open("/tmp/serde.json")?;
// why does this work?
serde_json::to_writer(&file, &10)?;
Ok(())
}
I'm passing a &File
- as expected, if I were to directly call any of Write
's methods on a File
it doesn't work:
use std::io::{self, Write};
use std::fs::OpenOptions;
fn main() -> io::Result<()> {
let file = OpenOptions::new()
.create(true)
.write(true)
.truncate(true)
.open("/tmp/wtf")?;
let file_ref = &file;
// this complains about not having a mutable ref as expected
file_ref.write(&[1,2,3])?;
Ok(())
}
error[E0596]: cannot borrow `file_ref` as mutable, as it is not declared as mutable
--> test.rs:12:5
|
10 | let file_ref = &file;
| -------- help: consider changing this to be mutable: `mut file_ref`
11 | // this complains about not having a mutable ref as expected
12 | file_ref.write(&[1,2,3])?;
| ^^^^^^^^ cannot borrow as mutable
So what gives? Is serde_json
breaking the type system somehow, or is this an intentional feature of the type system? If it's the latter, how does it work and why does it work like that?