Scope and Shadowing

RustRustBeginner
Practice Now

This tutorial is from open-source community. Access the source code

Introduction

In this lab, we learn about variable bindings, their scope, and the concept of shadowing in Rust. Variable bindings are confined to a block, which is a collection of statements enclosed by braces. There are two examples provided to illustrate these concepts. The first example shows how a variable binding declared inside a block is limited to that block's scope and is not accessible outside of it. The second example demonstrates variable shadowing, where a new binding with the same name is declared inside a block, effectively shadowing the outer binding.

Note: If the lab does not specify a file name, you can use any file name you want. For example, you can use main.rs, compile and run it with rustc main.rs && ./main.


Skills Graph

%%%%{init: {'theme':'neutral'}}%%%% flowchart RL rust(("`Rust`")) -.-> rust/BasicConceptsGroup(["`Basic Concepts`"]) rust(("`Rust`")) -.-> rust/DataTypesGroup(["`Data Types`"]) rust(("`Rust`")) -.-> rust/FunctionsandClosuresGroup(["`Functions and Closures`"]) rust(("`Rust`")) -.-> rust/MemorySafetyandManagementGroup(["`Memory Safety and Management`"]) rust/BasicConceptsGroup -.-> rust/variable_declarations("`Variable Declarations`") rust/DataTypesGroup -.-> rust/string_type("`String Type`") rust/FunctionsandClosuresGroup -.-> rust/function_syntax("`Function Syntax`") rust/FunctionsandClosuresGroup -.-> rust/expressions_statements("`Expressions and Statements`") rust/MemorySafetyandManagementGroup -.-> rust/lifetime_specifiers("`Lifetime Specifiers`") subgraph Lab Skills rust/variable_declarations -.-> lab-99292{{"`Scope and Shadowing`"}} rust/string_type -.-> lab-99292{{"`Scope and Shadowing`"}} rust/function_syntax -.-> lab-99292{{"`Scope and Shadowing`"}} rust/expressions_statements -.-> lab-99292{{"`Scope and Shadowing`"}} rust/lifetime_specifiers -.-> lab-99292{{"`Scope and Shadowing`"}} end

Scope and Shadowing

Variable bindings have a scope, and are constrained to live in a block. A block is a collection of statements enclosed by braces {}.

fn main() {
    // This binding lives in the main function
    let long_lived_binding = 1;

    // This is a block, and has a smaller scope than the main function
    {
        // This binding only exists in this block
        let short_lived_binding = 2;

        println!("inner short: {}", short_lived_binding);
    }
    // End of the block

    // Error! `short_lived_binding` doesn't exist in this scope
    println!("outer short: {}", short_lived_binding);
    // FIXME ^ Comment out this line

    println!("outer long: {}", long_lived_binding);
}

Also, variable shadowing is allowed.

fn main() {
    let shadowed_binding = 1;

    {
        println!("before being shadowed: {}", shadowed_binding);

        // This binding *shadows* the outer one
        let shadowed_binding = "abc";

        println!("shadowed in inner block: {}", shadowed_binding);
    }
    println!("outside inner block: {}", shadowed_binding);

    // This binding *shadows* the previous binding
    let shadowed_binding = 2;
    println!("shadowed in outer block: {}", shadowed_binding);
}

Summary

Congratulations! You have completed the Scope and Shadowing lab. You can practice more labs in LabEx to improve your skills.

Other Rust Tutorials you may like