Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

Tags:

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?

like image 553
RecursiveExceptionException Avatar asked Dec 28 '19 22:12

RecursiveExceptionException


People also ask

Is Clone expensive rust?

Differs from Copy in that Copy is implicit and extremely inexpensive, while Clone is always explicit and may or may not be expensive. In order to enforce these characteristics, Rust does not allow you to reimplement Copy , but you may reimplement Clone and run arbitrary code.

What is * const rust?

Rust has two different types of constants which can be declared in any scope including global. Both require explicit type annotation: const : An unchangeable value (the common case). static : A possibly mut able variable with 'static lifetime.


1 Answers

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`
like image 150
mcarton Avatar answered Sep 17 '22 19:09

mcarton