I get that "&mut T" means it's borrowed mutably, but doesn't that automatically mean that "&T" means it's borrowed immutably?
In the days of yore, an event called the "mutpocalypse" occurred where by (pre Rust 1.0) there was a huge discussion about potentially changing "&mut T" to "&only T" or "&uniq T" because the more precise model was one of sharing vs exclusivity, rather than immutability vs mutability. The immutability vs mutability model is still useful, it's just wrong in more circumstances. However, it does have the benefit of (IMO) being more accessible by describing borrows in terms of the most common effect: to mutate or not. I don't know which choice would have been the right one, but I am at peace with it.
"Rust Atomics and Locks" by Mara Bos has a great discussion of these points toward the beginning of her book, and specifically grounds the choice of which terminology to use in concrete and practical terms, which I really appreciated.
So, "&mut T" is a bit of a misnomer, then? I can roll with remembering that.
If something is a misnomer here, I'd probably say pronouncing "&T" as "immutable reference" is it. But it really is not entirely wrong either. I can craft a Rust API that only exposes a "&T" and I can make it so you cannot mutate it. Or I can make it so it looks like you aren't mutating anything, but under the covers, mutation is happening.
Take "Regex" for example. All of its methods take "&self." From the perspective of users of that API, thinking of "Regex" as immutable is absolutely the correct model. You, as a user, cannot do anything to that "Regex" to mutate it directly in a way that you can observe via the API. You can't swap out its internal NFA. You can't change its capture group names. You can't change the prefilters it uses. You can't do anything other than use APIs that purportedly tell you "nothing is changing."
Under the covers, stuff is definitely changing. The regex engines need mutable space to operate. But all of that is hidden from you, and there's no way to observe those mutations from the public API. (You can technically make observations in the most strictest sense and make an inference from them that things are being mutated internally. For example, by measuring how long it takes for certain regexes to execute. The first search might be measurably slower than the second. But this is clearly not something that is an API guarantee or is something you can directly observe through the API of the regex. I only mention it for completeness, and because this is the Internet.)
With all that said, in my mind's eye, when I see "&T" do I think "immutable"? No. My internal conception of it is "shared."
> So the fact that it gives you mutability is not wrong. It's just incomplete.
I understand. It means nothing to anybody outside my head, but if I think of "&mut" as a misnomer, that will help me to remember that it's not telling me the whole story.
I think the hardest part of learning any language is those little bits that are "hidden" by the syntax, so I need to find where to hang the lampshades so I remember them.
With a `&T` on the other hand, the entire point is to allow more than one to exist. That means that arbitrarily many parts of the program could be accessing the data at the same time. If you allow unsynchronized mutation in that situation, you can end up with data races and mangled data from those different parts making changes at the same time.
That's where types such as the single-threaded `Cell` and `RefCell`, and the thread-safe `Mutex` and `RwLock` come in. They force you to go through them, and therefore synchronization, in order to mutate.
They're duals. Neither is more or less of a misnomer than the other. It's like one of those sculptures where if you look at it one way, it looks like one thing, but from another angle, it looks like something else.
I also think that Rust had no realistic option other than &mut in order to succeed. Rust already has enough weird stuff in it, and while &mut is a little weird, &uniq or similar would be too weird, and the weirdness would be too exposed to new developers too early.
I kind of believe that, as this kind of thing gets more popular, and more people become familiar with this conception of the dual nature of mutability and exclusivity, that future languages could experiment with terminology around exclusivity, and that they would not pay the same sort of price that Rust would have had to pay.
I understand. But, at least for now, I need to conceptualize it as a misnomer to guard against me being confused by it.
Naming things is very hard. I'm sympathetic.
It's really hard to say because of set of people for whom "&uniq T" would have helped more is non-empty. But what is the size of the set of people for whom "&mut T" actually helps more? I have no clue. But it could be large.