Why does the compiler complain about Vec<mut TcpStream>?


#1

I have a bunch of different computers that I would like to connect to, then hold open a TcpStream to so I can later send them messages.

Here is the function I’m trying to compile:
http://is.gd/whFPaQ

So, I’m creating them all and adding them to a Vec as such:
for peer in peer_array {
let mut stream = TcpStream::connect(&*peer).unwrap();
peer_connections.push(stream);
connection_count += 1;
}

Then I’m returning peer_connections.

If I only make the function signature:
pub fn connect_to_peers() -> (u16, Vec)

Then I get a warning:
src\network.rs:53:13: 53:23 warning: variable does not need to be mutable, #[warn(unused_mut)] on by default
src\network.rs:53 let mut stream = TcpStream::connect(&*peer).unwrap();

Which makes sense, because it doesn’t think it needs the mut to match the function signature.

However if I try to change the function signature, as it seems it should be changed so that I can later write to the returned streams, I get an error:
Compiling fractal v0.1.0 (file:///C:/Projects/Fractal)
src\network.rs:42:40: 42:43 error: expected identifier, found keyword mut
src\network.rs:42 pub fn connect_to_peers() -> (u16, Vec) {
^~~
src\network.rs:42:44: 42:53 error: expected one of (, +, ,, ::, <, or>, found TcpStream
src\network.rs:42 pub fn connect_to_peers() -> (u16, Vec) {

I’m thinking the issue is that I’m specifying the vector wrong? Is there a way to pass back a Vec of muts?

Thank you!


#2

I think you misunderstand mutability in rust. When passing things by value (without & or &mut), mutability is completely a concept on variables, not on types.

There is no Vec<mut TcpStream>, because mutability is a concept on the outermost variable, in this case the Vec. If the Vec is mut, anything inside it can also be accessed mutably. If the Vec isn’t mut, everything inside it can only be accessed immutably (without some sort of lock).

One other thing: because you are returning a Vec itself, instead of a reference, you don’t decide the mutability. When you pass full ownership of something, the new owner has full control over whether it’s mutable or not, so there’s no need to declare it mut at all. You’ll only need to when you assign the result of the function to a variable.


#3

Hm, saying it like that is probably confusing in the presence of & and &mut references.


#4

Edited to try to take that into account


#5

Makes sense, I thought it was like a type or a way for the function to tell whoever is calling it that it requires this variable to be mutable or else it won’t work. Guess there is no way to do that and just have to wait for the compiler to flag it?

Thanks guys.


#6

Well, taking ownership, by using TcpStream instead of something like &TcpStream, means that something is mutable. If you own something, you can do whatever you want to it. There’s no way to express “You take ownership of this thing, but you can’t mutate it” because that’s contrary to the definition of ownership. Does that make sense?