How do global consts that are not copy or clone work in Rust?

Say I have the following snippet (playground)

struct A {
    pub val: u32
}

const GLOBAL_A: A = A {val: 2};

fn main() {
    let some_a: A = GLOBAL_A;
    let other_a: A = GLOBAL_A;

    println!("double val = {}", some_a.val + other_a.val);
}

Since A is neither Clone nor Copy, I would assume the value of GLOBAL_A would be moved. That does not make much sense for a const and as shown cannot be the case anyways since it can be "moved" twice.

What are the rules that allow the above snippet to work considering A is not Clone nor Copy?

Upvotes: 21

Views: 1201

Answers (1)

mcarton
mcarton

Reputation: 30061

Constants are always inlined. Your example is essentially the same as

struct A {
    pub val: u32
}

fn main() {
    let some_a: A = A {val: 2};
    let other_a: A = A {val: 2};

    println!("double val = {}", some_a.val + other_a.val);
}

The value is reconstructed twice, so it doesn't need to be Copy or Clone.

On the other hand, statics are not inlined:

struct A {
    pub val: u32
}

static GLOBAL_A: A = A {val: 2};

fn main() {
    let some_a: A = GLOBAL_A;
}

results in

error[E0507]: cannot move out of static item `GLOBAL_A`
 --> src/main.rs:8:21
  |
8 |     let some_a: A = GLOBAL_A;
  |                     ^^^^^^^^
  |                     |
  |                     move occurs because `GLOBAL_A` has type `A`, which does not implement the `Copy` trait
  |                     help: consider borrowing here: `&GLOBAL_A`

Upvotes: 24

Related Questions