That's not quite fully accurate; it depends significantly on how you're defining "absolutely." To the amount we can ensure any property of our code under optimizations, static
items are not copied unless you use them by-value.
The address of a static
item is guaranteed to be consistent (unlike const
items).
Namely, if I have
const ARR: [usize; 5] = [1, 2, 3, 4, 5];
// somewhere
println!("{:p}", &ARR);
// somewhere else
println!("{:p}", &ARR);
then there is no guarantee that the printed addresses are the same. Similarly, with
const ARR: &[usize; 5] = &[1, 2, 3, 4, 5];
// somewhere
println!("{:p}", ARR);
// somewhere else
println!("{:p}", ARR);
or even with &[usize]
, there's still no guarantee that the shown addresses are the same.
Within a single codegen unit (roughly, a single crate), it's likely that they are the same address. From different codegen units (roughly, separate crates), it's likely that they aren't.
However, with
static ARR: [usize; 5], [1, 2, 3, 4, 5];
// somewhere
println!("{:p}", &ARR);
// somewhere else
println!("{:p}", &ARR);
it is guaranteed that both println!
will see and print the same static at the same address.
This isn't a 100% guarantee that all compilers will never introduce a spurious copy; under the as-if rule of optimization, the compiled program is free to do whatever extra work it wants to do so long as that doesn't change the behavior of the code you wrote, and only changes "trivial" details such as how quickly it executes, or how much memory it allocates (stack or heap) or copies around.
What puts a bound on behavior is that the compiler wants to produce good code. Since the address of a static
is guaranteed to be consistent, a reference to that static
must have the same address. If you never actually observe the address (and the compiler is able to determine this), then it's allowable for the reference to be to a different address. But what benefit is there to that? It's simpler and just more efficient in essentially all cases for the compiler to just give you a reference to the shared static
memory when you take a reference to the static
.
To answer the OP question directly, given
static ARR: /* type */ = /* expression */;
&ARR
you semantically get a reference to the static
, and no copy of the static
is performed; the reference is to the same "allocated object" with the same address as every other reference to the static
. If it does not change the behavior of the code, the compiler/optimizer is allowed to introduce a spurious copy, but it has no reason to.
If you wrote const ARR
instead, a copy is semantically performed every time you mention ARR
, even if the type is not Copy
, and even if you just immediately take a reference. If it does not change the behavior of the code, the compiler/optimizer is allowed to remove unnecessary copies, and it's typically quite eager to do so.