I’m slowly starting Rust for Rustaceans, and it’s already poking holes in my understanding of Rust. Here’s a couple initial questions I have:
A shared reference, &T is , as the name implies, a pointer that may be shared. Any number of references may exist to the same value, and each shared reference is Copy, so you can trivially make more of them
I don’t understand why a shared reference has to implement copy. In fact, isn’t this not true just by the fact that references work for Strings and Strings size can’t be known at compile time?
- I’m having trouble with the idea of assigning a new value to a mutable reference.
let mut x = Box::new(42); *x = 84;
Why in this example, is the assignment dereferenced. Why not just do x=84? is it dereferenced specifically because is Boxed on the heap?
The key thing to understand is that in Rust, references are considered unique types. This means that
&Tis a separate type fromT.So, for #1, it is not saying that
TimplementsCopy, it is saying that regardless of whatTis,&TimplementsCopy. This is because, by definition, it is always valid to copy a shared reference, even ifTitself is notCopy.Part of the reason this is confusing is that traits often include references in their function signatures; and in particular,
Clone::clonehas the signaturefn clone(&self) -> Self. So whenTimplementsclone, it has a method that takes&Tand returnsT. But even though the signature takes&T, the type that implementsCloneisTitself. (&Talways implementsCloneas well, just as it always implementsCopy, but as withCopy, this is independent from whetherTitself implementsClone. See for example the error message you get when explicitly cloning a shared reference: https://play.rust-lang.org/?version=stable&mode=debug&edition=2021&gist=a1b80cc83570321868c4ad55ee3353dc)Since
Copyis a marker trait, it doesn’t have any associated methods making it explicit thatCopyaffects how&Tcan be used. However,Copyrequires the type to implementClone(even though you can implementClonein terms ofCopy) and implies thatTcan always be automatically created from&Twithout an explicit call toT::clone, so you can think of the “signature” forCopyas matching that ofClone, even though there’s no actualcopymethod.For #2, I recommend thinking in terms of explicit types. Adding annotations, you get:
let mut x: Box = Box::new(42); *x = 84_i32;The type of
xisBox. You cannot assign ani32to aBox; they’re different types! But the type of*xisi32, and thus you can assign84to it.The trait used to make
Boxbehave this way isDerefMut, which explicitly makes*xassignable: https://doc.rust-lang.org/std/ops/trait.DerefMut.htmlSo, for #1, it is not saying that T implements Copy, it is saying that regardless of what T is, &T implements Copy. This is because, by definition, it is always valid to copy a shared reference, even if T itself is not Copy.
Got it! this helps a lot, thanks. I think I was indeed thinking of it as some kind of pseudo type and not a type in of itself. I got a little lost in the further explanation, but I really need to spend more time understanding Clone and Copy in general. Thanks!
It’s totally reasonable to assume that
&Tis a “pseudo-type”; that’s very much what it is in C++, and there aren’t any other mainstream languages with that syntax to compare against!
A reference &T holds a pointer, ie. the memory adress to the actual content of T
So, in the example x doesn’t hold the value 42, it holds the memory adress to the memory there the integer value 42 is stored. So, to access the value, you need to dereference the reference. Which is why you need to use *x when you assign the value.
And the Copy question.It is not that s reference has to implement Copy. A reference IS Copy, by the simple fact that it is a primitive value on the stack.
A reference IS Copy, by the simple fact that it is a primitive value on the stack.
This seems a bit misleading, noting that unique/mutable references aren’t
Copy. Shared references areCopybecause it’s sound to have that, and it’s a huge QOL improvement over the alternative.In this context mutability is part of the type signatures. &T and &mut T are two different types, the former implements copy but not the later. It’s not really an “exception” in the type system.
I wouldn’t say it’s misleading. The question was specifically about shared references, it seemed obvious to me that’s what they were referring to in their answer.
The question was specifically about shared references
Sure, but the way I read the answer was “All primitive values on the stack are Copy”, which isn’t true (my example being mutable references, which have the same representation as shared ones, “just” a different semantic meaning). That’s what I meant by misleading.
I think where I was getting hung up here as I was still thinking of the value of the reference rather than the reference itself. That’s why I brought up Strings, it didn’t make sense that String would automatically implement Copy since they go on the heap. But I see now we’re talking about the pointer reference TO that value.
Thanks!
In fact, isn’t this not true just by the fact that references work for Strings and Strings size can’t be known at compile time?
I don’t understand this. Shared references to
StringareCopy, too. This doesn’t have to do anything with sizes. Rather, it’s implemented in the compiler, because it’s sound to have it and a huge QoL improvement over the alternative… just the same reason why e.g.usizeisCopy, really.is it dereferenced specifically because is Boxed on the heap?
No, it’s not really related to the heap.
BoximplementsDerefMut, which is in-depth explained here.Thanks, reading up a bit on DerefMut helped.
deleted by creator


