DEV Community

Cover image for Variables, Shadowing, and Constants in Rust
Francesco Ciulla
Francesco Ciulla

Posted on

Variables, Shadowing, and Constants in Rust

Understanding Variables in Rust

Rust is a statically and strongly typed language. This means that the compiler must know the type of all variables at compile time. The compiler can usually infer what type we want to use based on the value and how we use it. In cases when many types are possible, we must add a type annotation.

In this article, we will learn about the following:

  • variables and mutability
  • shadowing
  • constants

If you prefer a video version

Variables and mutability

Let's start with understanding variables and mutability.

Let's declare a variable and print it:

fn main() {
    let x = 5;
    println!("x is {}", x);
}
Enter fullscreen mode Exit fullscreen mode

Here, we are using string interpolation to print the value of x. The curly braces are placeholders for the value of x. The value of x is then passed as an argument to println!().

You should see the following output:

Variables in Rust - Rust programming tutorial

This is an implicit declaration of type, but at compile time, Rust infers the type of x to be i32. This is because we assigned the value 3 to x, and integer literals default to i32 unless otherwise specified.

If you want to declare the variable type explicitly, you can use a type annotation, which is the colon (:) followed by a type name.

Let's try something that seems we can do but we actually can't:

fn main() {
    let x = 5;
    println!("x is {}", x);

    x = 6;
    println!("x is {}", x);
}
Enter fullscreen mode Exit fullscreen mode

In Rust, variables are immutable by default. This means that once we assign a value to a variable, we can't change it. If we try to change the value of a variable, we get an error:

Variables in Rust - Rust programming tutorial

the mut keyword

If we want to change a variable's value, we must declare it as mutable. We do this by adding the mut keyword before the variable name, as shown here:

fn main() {
    let mut x = 5;
    println!("x is {}", x);

    x = 6;
    println!("x is {}", x);
}
Enter fullscreen mode Exit fullscreen mode

Now we can change the value of x without getting an error.

Shadowing

Now, let's see the concept of shadowing.

We can change the value of an immutable variable by shadowing it. Shadowing is when we declare a new variable with the same name as a previous variable. The new variable shadows the previous variable, and we can assign a new value to the new variable while the old variable remains unchanged.

fn main() {
    let x = 5;
    println!("x is {}", x);

    let x = 6;
    println!("x is {}", x);
}
Enter fullscreen mode Exit fullscreen mode

You might think that we would get an error here, but we don't. This is because we are declaring a new variable, not changing the value of the old one. The old variable is still there, but the new variable shadows it. We can't use the old variable anymore, but we can use the new one.

Variables in Rust - Rust programming tutorial

I can even use the previous variable's value to initialize the new variable:

fn main() {
    let x = 5;
    println!("x is {}", x);

    let x = x + 2;
    println!("x is {}", x);
}
Enter fullscreen mode Exit fullscreen mode

Variables in Rust - Rust programming tutorial

Name shadowing in a different scope

Name shadowing is when we declare a new variable with the same name as a previous variable. The new variable shadows the previous variable, and we can assign a new value to the new variable while the old variable remains unchanged.

Let's see an example:

fn main() {
    let x = 5;
    println!("x is {}", x);

    {
        let x = 8;
        println!("x is {}", x);
    }

    let x = x + 2;
    println!("x is {}", x);
}
Enter fullscreen mode Exit fullscreen mode

Variables in Rust - Rust programming tutorial

Changing the type

When you use shadowing, you can change the type of a variable. This is because you are declaring a new variable, not changing the value of the old one.

You can use it to change the type of a variable:

fn main() {
    let x = 5;
    println!("x is {}", x);

    let x = "hello world!";
    println!("x is {}", x);
}
Enter fullscreen mode Exit fullscreen mode

Variables in Rust - Rust programming tutorial

But you can't change the type of a variable without shadowing it:

fn main() {
    let mut x = 5;
    println!("x is {}", x);

    x = "hello world!";
    println!("x is {}", x);
}
Enter fullscreen mode Exit fullscreen mode

We will get an error.

Variables in Rust - Rust programming tutorial

This means that if we use shadowing, we can change the type, but if a variable is mutable, we can't change the type without shadowing it.

Constants Example

Constants are variables that are immutable and have a fixed value.

They are declared using the const` keyword. They must be annotated with a type, and they can only be set to a constant expression, not the result of a function call or any other value that could only be computed at runtime.

rust
fn main() {
const MAX_LEVEL:i32 = 100_000;
println!("The maximum level is: {}", MAX_LEVEL);
}

Recapt for constants:

  • you must declare the type of the value
  • you must assign a value to the constant on the declaration
  • you cannot redefine or mutate a constant (shadowing doesn't work, can't use mut keyword, can't reassign)

This ends the article.

I hope you enjoyed it and learned something new. If you have any questions, feel free to leave a comment below.

If you prefer a video version

ALL the links here: https://francescociulla.com

Top comments (6)

Collapse
 
pradumnasaraf profile image
Pradumna Saraf

Good read, Francesco!

Collapse
 
francescoxx profile image
Francesco Ciulla

Pradumna the best!

Collapse
 
rdarrylr profile image
Darryl Ruggles • Edited

It’s great to see more and more Rust content. I’m always learning more every day but I admit it’s a tough language to understand. 🦀🦀

Collapse
 
francescoxx profile image
Francesco Ciulla

to be honest, I love it. It's just not beginner friendly

Collapse
 
shricodev profile image
Shrijal Acharya

I am also on my Rust learning journey, and I must say this is a very well-written article. Decoding everything from the video in an article is a tough job. Great read, @francescoxx!

Collapse
 
francescoxx profile image
Francesco Ciulla

glad you appreciate the effort. I am trying to promote videos as much as I can