When I wrote my very first Rust code, I was trying to write to a socket. I got stuck on this task with misleading error messages for the longest time. I finally realized I had not made the socket object mutable. I’m used to Posix where you have an integer file descriptor and I don’t tend to think of socket write as a mutable operation. At least it doesn’t mutate state that my app manages. Perhaps something in the kernel gets mutated. I believe the socket interface may have been intended to support queuing which is perhaps why it needed to be mutable. I might have needed a lower level api. I just mention this because I think it’s interesting as to how it should be typed when mutation is external to the app. I didn’t follow through on using Rust and this was long ago so I’m sure some details are wrong.

`std::net::TcpStream`? Interestingly, it doesn't need to be mutable if you know the trick.

* It implements `Write` for `TcpStream` which is likely what you were using. And `Write` requires `&mut`, probably because the same trait is used for writing to application buffers (e.g. through `BufWriter` or just to a `Vec`). So this doesn't compile: [2] I think the error message is pretty good; maybe it's improved since you tried. It doesn't though suggest the trick below.

* It also implements `Write` for `&TcpStream`. So if you use the awkward phrasing `(&stream).write_all(b"asdf")`, you don't need mutable access. [3] This allows you to use it with anything that takes the trait, without requiring mutability. You might need this if say you're reading from the socket from one thread while simultaneously writing to it from another thread.

It's a vaguely similar situation with the most common async equivalent, `tokio::net::TcpStream`. The most straightforward way to write to it is with a trait that needs mutable access, but it is possible to write to a shared reference by not using a trait. They also have these `split` and `into_split` methods to get mutable access to something that implements the read traits and something that implements the write traits.

[1] https://doc.rust-lang.org/std/net/struct.TcpStream.html

[2] https://play.rust-lang.org/?version=stable&mode=debug&editio...

[2] https://play.rust-lang.org/?version=stable&mode=debug&editio...

> got stuck on this task with misleading error messages for the longest time.

Could you elaborate on that? We consider misleading error messages to be bugs and would like to know more on case we could fix them.

I also found it really unintuitive what needs to be made mutable. And still do to some degree.

When I first had learned that rust had this concept of “opt-in” mutability, I thought that it must then be an accepted pattern that we make as little as possible be mutable in an attempt to help us better reason about the state of our program. I had come to rust after learning some clojure so I was like “ahh! Immutable by default! So everything’s a value!”

But in reality it feels like rust code is not “designed” around immutability but instead around appeasing the borrow checker - which is actually pretty easy to reason about once you get the hang of the language. But it’s a ton to learn up front

I think part of it might be just that for modeling's sake it makes it clear when something can write vs only read the socket