liveBook · Manning

Scope

As explained in Idiomatic Rust

A scope is a region of program text that determines where bindings are valid and when their associated values are destroyed.

A scope determines where a binding is usable and when its local value leaves use. A function creates a scope; braces can create a smaller block scope inside it. Scope also gives resource cleanup a predictable boundary: a local pointer may disappear when a function returns, but the resource it points to needs its own cleanup. section 4.1.1

A block can shadow a binding

In `int a = 0; { int a = 1; printf("%d", a); } printf("%d", a);`, the first print uses the inner `a` and produces `1`. After the block ends, the outer `a` is visible again, so the second produces `0`. section 4.1.1

In C, leaving a function releases its local pointer but does not free heap memory allocated with `malloc`. An early return can therefore skip both `free` and `fclose`. C++ RAII ties cleanup to objects such as `std::shared_ptr` and `std::ifstream`, so leaving scope also runs their cleanup. section 4.1.1

void leaky_func() {
    FILE *fp;
    int *a = malloc(sizeof(int));
    *a = 0;                           #1

    // try to open a file for reading
    fp = fopen("file.txt", "r");
    if (fp == NULL) {
        // there was an error!
        return;
    }

    // Now we can read from the file at fp.
    // ...

    fclose(fp);        #2
    free(a);           #3
}

Follow the error return: it occurs after allocation but before `free(a)`, leaving the allocated memory unreleased. section 4.1.1

Rust also uses scope for RAII cleanup. When an owned value goes out of scope, its destructor runs; a container such as `Vec` cleans up its contents too. Ownership moves matter: after a `String` is moved into a `Vec`, the vector owns it. The notable exceptions here are `Copy` values, which cannot have destructors, and unsafe code. section 4.1.2

Listing 4.1 Resource acquisition
fn main() {
    let status = String::from("Active");      #1
    let statuses = vec![status];              #2
    println!("{:?}", statuses);
}  #3

Trace `status` into `statuses`: the move transfers ownership, and the vector and its contents are cleaned up when `main` ends. section 4.1.2

How Idiomatic Rust covers it

How deep it goes
Works through function and block scope, shadowing, resource leaks, and destructor-driven cleanup.
Examples
Illustrates block shadowing, a C early-return leak, and a Rust String moved into a Vec.
What it assumes
Assumes familiarity with variables and functions while introducing RAII through small C, C++, and Rust examples.
What you can do after
Diagnose/debug with it by spotting skipped C cleanup and tracing when Rust-owned values are destroyed.
How it connects
Links scope to RAII, ownership, move semantics, destructors, and the borrow checker.

Also explained in

Compare how 21 books explain scope →

Related concepts

This explainer was generated by Manning's knowledge graph from the text of Idiomatic Rust. The section links point to the parts of the book it draws on.