Kind of a weird one, but as I was programming a Rust application, I found that weird case that compiles but it's not clear to me why it does:
use std::thread;
use std::sync::Arc;
pub fn main() {
let vec = Arc::new(vec![1, 2, 3]);
for _i in 0..10 {
let var = Arc::clone(&vec);
thread::spawn(move || test(&var));
}
}
fn test(var: &Vec<i32>) {
println!("{var:?}");
}
So here we pass var
to the test
function as a &Arc<Vec<>>
(rust-analyzer confirms that), and even though the function is expecting a &Vec<>
, this works.
Now this implies that &Vec
and &Arc<Vec>
are equivalent, which is super weird to me (especially since that doesn't seem to work with Vec
and Arc<Vec>
)
I thought that maybe since Arc is a reference counter, it can be represented as &
as syntaxic sugar, but surely that's not it since the same maneuver doesn't compile with &Vec<>
and Arc<Vec>
.
Does that mean that Arc
s can be implicit, but only in certain conditions? This is my leading theory because Arc
s let the user access the data without getting in the way but that still looks weird to me, because we aren't getting the information that the reference is being counted.
If one of you could explain to me why a reference to a reference counter that points to a vector is equivalent to a reference to a vector, it would be much appreciated!
Edit: So a commenter (thank you PitaJ) pointed out that a deref was happening. I'm still curious about losing that Arc
qualifier.
The testing I did before posting seemed to show that the reference counter is still working (which is expected, I didn't think that there was a bug in Rust), so that means that Arc
still does its thing even after it derefs to its inner value?