Monday, February 1, 2016

Statics in Rust aren't that simple

1) Suppose we have this:

static MY_STATIC = 123;
fn main() {
  println!("MY_STATIC = {}", MY_STATIC);
}
That gives a compilation error: expected ':', found '=' The type of a static has to be defined, let's fix that:

static MY_STATIC: i32 = 123;
And it gives us:

// =>
MY_STATIC = 123
2) Let's create 2 static variables with the same name but in the different lexical scopes:

static MY_STATIC: i32 = 123;
fn main() {
  println!("MY_STATIC = {}", MY_STATIC);
  
  static MY_STATIC: i32 = 456;
  println!("MY_STATIC = {}", MY_STATIC);
}
And it compiles well and only a single warning implies that something is a little wrong:

warning: static item is never used: `MY_STATIC`, #[warn(dead_code)] on by default
static MY_STATIC: i32 = 123;

// =>
MY_STATIC = 456
MY_STATIC = 456
3) Let's add one more function and print the value of the global static variable in it:

static MY_STATIC: i32 = 123;
fn main() {
  println!("MY_STATIC = {}", MY_STATIC);
  
  static MY_STATIC: i32 = 456;
  println!("MY_STATIC = {}\n", MY_STATIC);
  func2();
}

fn func2() {
  println!("MY_STATIC = {}", MY_STATIC);
}

// =>
MY_STATIC = 456
MY_STATIC = 456
MY_STATIC = 123
 
4) Let's create 2 different static variables:

static MY_STATIC: i32 = 123;
fn main() {
  println!("MY_STATIC = {}", MY_STATIC);
  
  static MY_STATIC2: i32 = 456;
  println!("MY_STATIC2 = {}\n", MY_STATIC2);
  func2();
}

fn func2() {
  println!("MY_STATIC = {}", MY_STATIC);
}

// =>
MY_STATIC = 456
MY_STATIC = 456
MY_STATIC = 123
5) Let's create 2 same static variables in different scopes in the same function:

fn main() {
  println!("MY_STATIC = {}", MY_STATIC);
  static MY_STATIC: i32 = 456;
  {
    static MY_STATIC: i32 = 789;
  }

  println!("MY_STATIC = {}\n", MY_STATIC);
}

// =>
MY_STATIC = 456
MY_STATIC = 456
6) Simirally

fn main() {
  println!("MY_STATIC = {}", MY_STATIC);
  static MY_STATIC: i32 = 456;
  {
    println!("MY_STATIC = {}", MY_STATIC);
  }

  println!("MY_STATIC = {}", MY_STATIC);
}

// =>
MY_STATIC = 456
MY_STATIC = 456
MY_STATIC = 456
7) Moving on:

fn main() {
  println!("MY_STATIC = {}", MY_STATIC); // error: unresolved name `MY_STATIC` [E0425]
  {
    static MY_STATIC: i32 = 456;
    println!("MY_STATIC = {}", MY_STATIC);
  }   
  
  println!("MY_STATIC = {}", MY_STATIC);
}

// =>
error: unresolved name `MY_STATIC` [E0425]
println!("MY_STATIC = {}", MY_STATIC);
8)

static MY_STATIC: i32 = 123;
fn main() {
  println!("MY_STATIC = {}", MY_STATIC);
  {
    static MY_STATIC: i32 = 456;
    println!("MY_STATIC = {}", MY_STATIC);
  }   
  
  println!("MY_STATIC = {}", MY_STATIC);
}

// =>
MY_STATIC = 123
MY_STATIC = 456
MY_STATIC = 123
9) We can't create a mutable static variable:

fn main() {
  println!("MY_STATIC = {}", MY_STATIC); // error: use of mutable static requires unsafe function or block [E0133]
  static mut MY_STATIC: i32 = 456;
}

// =>
error: use of mutable static requires unsafe function or block [E0133]
println!("MY_STATIC = {}", MY_STATIC);
10) Therefore we can do this:

fn main() {
  unsafe {
    println!("MY_STATIC = {}", MY_STATIC);
  }

  static mut MY_STATIC: i32 = 456;
}

MY_STATIC = 456
11) But this will compile with an error:

fn main() {
  unsafe {
    println!("MY_STATIC = {}", MY_STATIC);
    static mut MY_STATIC: i32 = 456;
  }
  
  println!("MY_STATIC = {}", MY_STATIC); // error: unresolved name `MY_STATIC`
}
12) Thus we have to make the static variable global:

static mut MY_STATIC: i32 = 123;
fn main() {
  unsafe {
    println!("MY_STATIC = {}", MY_STATIC);
  }
}

// =>
MY_STATIC = 123
13)

static MY_STATIC: i32 = 123;
fn main() {
  let x1 = &MY_STATIC;
  println!("MY_STATIC = {}", MY_STATIC);
  println!("MY_STATIC x1 as * = {}", *x1);
  println!("&MY_STATIC as :p = {:p}", &MY_STATIC);
  println!("MY_STATIC x1 as :p = {:p}", x1);
}

// =>
MY_STATIC = 123
MY_STATIC x1 as * = 123
&MY_STATIC as :p = 0x7ff462d69d40
MY_STATIC x1 as :p = 0x7ff462d69d40

No comments :

Post a Comment