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
&T
is a separate type fromT
.So, for #1, it is not saying that
T
implementsCopy
, it is saying that regardless of whatT
is,&T
implementsCopy
. This is because, by definition, it is always valid to copy a shared reference, even ifT
itself is notCopy
.Part of the reason this is confusing is that traits often include references in their function signatures; and in particular,
Clone::clone
has the signaturefn clone(&self) -> Self
. So whenT
implementsclone
, it has a method that takes&T
and returnsT
. But even though the signature takes&T
, the type that implementsClone
isT
itself. (&T
always implementsClone
as well, just as it always implementsCopy
, but as withCopy
, this is independent from whetherT
itself 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
Copy
is a marker trait, it doesn’t have any associated methods making it explicit thatCopy
affects how&T
can be used. However,Copy
requires the type to implementClone
(even though you can implementClone
in terms ofCopy
) and implies thatT
can always be automatically created from&T
without an explicit call toT::clone
, so you can think of the “signature” forCopy
as matching that ofClone
, even though there’s no actualcopy
method.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
x
isBox
. You cannot assign ani32
to aBox
; they’re different types! But the type of*x
isi32
, and thus you can assign84
to it.The trait used to make
Box
behave this way isDerefMut
, which explicitly makes*x
assignable: https://doc.rust-lang.org/std/ops/trait.DerefMut.htmlGot 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
&T
is 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!