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 uses write_fmt
which takes a &mut self
. Your write!(&f, ...)
is actually the odd one since the object being written to should be mutable, however you have an immutable File
.
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 allow File
s to be written to immutably.
It works in the first case because &f
creates a temporary, which can be used mutably. The reason why write!(f, ...
(with f
being &File
) doesn't work is because f
is a variable that write_fmt
wants to modify, so it needs to be mut
.
fn write_hi(mut f: &File) {
// ^^^
write!(f, "hi").unwrap();
}
See also:
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With