TcpStream set_nodelay and set_keepalive not taking mutable self

In the unstable tcp feature, TcpStream has two functions, that take an immutable self set_nodelay and set_keepalive. Since the function descriptions explicitly say that they change how the stream works, it seems really weird that they do not take self mutably.
Could someone explain the reason for this? It seems deliberate as the old_io version takes it mutably.

1 Like

Those options just call the setsockopt system call, which doesn't change anything to the actual data of the TcpStream (the socket file descriptor), so there is no need for these functions to take self mutably.

It changes the behavior of course, but the settings of the socket are kept in the kernel, and not in user space.

It may not change the data in the socket, but it does change the behavior of the socket. In a potentially very difficult to debug way. I thought that when passing something immutably I am guaranteed it does not change, this interface breaks that promise.

And I understand that it uses a system call, so Rust can't tell that something changed, but now there seem to be fewer guarantees on the control of the streams behavior. Since anything can change it, even if it seems it wouldn't from the type definition.

Also, I find that shutdown has the same problem. While it may be possible to argue that set_nodelay and set_keepalive don't modify the data, I find that a little hard to believe for the function that prevents you from getting or sending anymore data.

But it's not passed immutably. We've said "&T is an immutable reference" too often and it's not true. The correct way is "&T is a shared (or shareable) reference".

One example: AtomicIsize. When you .fetch_add() takes &self, which is completely natural because you understand that shared references to an atomic integer may change it.

Another example: Mutex::lock() takes &self.

I still don't like it. I feel that it should be a mutable reference to be explicit about it changing the underlying stream. If we don't use the items that rust gives to be explicit about change, then why have them.

If that is the correct way to say it, then what is the difference between "&" and "&mut"?