Why does std::io::stdin().read_line expect a &mut string?

Total beginner here: I can understand it accepting a &string, as read_line should mutate the variable’s data, but why would it need to change where the variable is pointing to?

1 Like

It’s not; &mut String is a reference to a mutable string; mut &String would be a mutable reference to an immutable string.

2 Likes

interesting. I was going through the tutorial and the “guess” variable was already stated to be mutable. Why is it necessary to do so again?

1 Like

The String is owned by its binding: guess. & and &mut let you borrow that String.

&guess is an immutable reference. It gives you a “read access” but that’s all.
&mut guess is a mutable reference. It lets you mutate the object owned by the binding guess.

You may want to lookup the chapter 4 of the book on Ownership.

2 Likes

How mutability works in Rust is central to its design, so I guess you will see more of it and understand it in its context as you go along.

In brief, mutable access means exclusive access, and even if you have a mutable variable for a string, you might not want to give a particular function you call exclusive access to it – not if you need something else to read from the same variable concurrently, for example.

Rust has already chosen to make passing references explicit (must use & / &mut syntax to pass a reference to a variable), and which kind of reference is also explicit — maybe because it matters for the borrow checker (the part of the compiler that checks the rules for references).

1 Like

You can replace a &mut reference using std::mem::replace, which is safe.

1 Like

Others have already said this, but the mut modifier is for the owner of the value - it allows them to mutate the value. They can also lend it out immutably to other places, but those cannot modify it. They can also lend it out mutably, which allows modification by a single possessor of the mutable borrow. If the owner doesn’t declare the value as mutable to begin with, no mutable borrows are allowed either. So ownership and mutability are front and center in Rust, it’s very explicit about them.

1 Like

And replace is a safe wrapper around unsafe code, which I specifically said could do that. My point was that references should be thought of as borrowings, not as pointers, although they are.

Ok fair enough :thumbsup:

Sorry, but that’s misleading. With that argument all of std is a safe wrapper around unsafe code somewhere.

Fact is, mem::replace is a safe standard function and there is nothing at all unsafe about using it to replace the object referenced by a &mut reference.

1 Like

That’s how I looked at it initially as well, but technically it’s right - it requires unsafe code internally; if no such function existed, you’d implement it via unsafe since it’s not expressible in the language itself.

It’s just the swapping out of the old value that’s not expressible without the function. If you just want to replace the referenced object, *ref = newvalue does not need a function.

2 Likes

That’s true. For some reason I thought we were talking about replacement in the mem::replace sense, but maybe I read too much into it.

I guess we come from different perspectives. In Rust I find you’re often not supposed to think in terms of pointers. I meant to provide a proper thought model and have it contrast with the way C and C++ do things. Sort of a “pedagogy comes before technically-correct” if you will.

That’s a good perspective to have, but with respect to mutable references, I’d leave the comparison to raw pointers in C/C++ at “guaranteed non-null and guaranteed to be unique (i.e. no other read/write aliasing)” (with “guaranteed” being modulo nobody doing unsafe things). That alone is quite powerful. The replacement portion is confusing and possibly inaccurate, depending on how one interprets it (as witnessed in this thread).

Yeah, fair enough. I’ve edited my answer not to mislead anyone.

2 Likes

Well, the whole point of read_line is that it gets the command line input and it puts it in the location specified by "string", like you said. "Mut &string" means the reference can be changed while "&mut string" means that the actual string can be changed.

I like to think of references as portals into the actual variable, so this means that you can change the variable that you have the portal to!

I had the same question - thank you so much for asking!

Please do not bump old threads.

This topic was automatically closed 7 days after the last reply. We invite you to open a new topic if you have further questions or comments.