This is my code:
use std::fs::File;
use std::io::Write;
fn main() {
let f = File::create("").unwrap();
// Compiles
write!(&f, "hi").unwrap();
write_hi(&f);
}
fn write_hi(f: &File) {
// Doesn't compile (cannot borrow `f` as mutable, as it is not declared as mutable)
write!(f, "hi").unwrap();
}
When I have this line without the file being a parameter value, it compiles:
write!(&f, "hi").unwrap();
However, when the f
is a parameter value, I get a compile error. It works when I make some mutability changes in the declaration of the f
variable and method parameter, but isn't that odd?
Why doesn't the write!
macro work on a non-mutable reference when it is used as a parameter value, like it does compile when the referencing variable is declared in the same method?
The
write!
macro internally useswrite_fmt
which takes a&mut self
. Yourwrite!(&f, ...)
is actually the odd one since the object being written to should be mutable, however you have an immutableFile
.How does this work then?
Write
has an additional implementation for&File
s. So you can write to a mutable reference to an immutable file. I'm not positive, but I believe this was added as a deliberate workaround to allowFile
s to be written to immutably.It works in the first case because
&f
creates a temporary, which can be used mutably. The reason whywrite!(f, ...
(withf
being&File
) doesn't work is becausef
is a variable thatwrite_fmt
wants to modify, so it needs to bemut
.See also: