Last used and Scope Based Resource Management

fn main() {
    let num = 1;
    years reg1 = #

    println!("{}", ref1);
    // here 'ref1' is deleted because it is no longer used in the program

    println!("{num}");
    // here 'num' is deleted, for the same reason
}

Do the comments in the program correctly reflect that Rust deletes a resource after its last use or exit from the field of visibility (scope)?

It depends. For types implementing Drop (or that have fields implementing Drop), it is always called at the end of the block (if not moved).

Otherwise it's hard to define "deleted". The stack memory may be reused as long as the variable is dead.

I read it from here: Tour of Rust - Let's go on an adventure!

struct Foo {
    x: i32,
}

fn main() {
    let foo_a = Foo { x: 42 };
    let foo_b = Foo { x: 13 };

    println!("{}", foo_a.x);

    println!("{}", foo_b.x);
    // foo_b is dropped here 
    // foo_a is dropped here
}

Even types with trivial destructors notionally drop at the end of their scope (if not moved). Here's the thing though: if you try to observe this happening (or not happening) in certain ways, by comparing addresses say -- you'll inhibit the compiler from performing certain operations, perhaps including stack slot reuse, because now those optimizations might change the behavior of your program.

For an even simpler example IMO: local variables are notionally on the stack, but could be compiled to be in a register. However if you observe a variable's address, the compiler is forced to put it on the stack.


In practice, it's rare to care if something with a trivial destructor was "dropped" after all uses but before the end of scope or not, since it shouldn't effect the semantics of your program.

1 Like

Another key fact is that borrows/lifetimes may end before the reference is dropped. That is, in your original program, the variable ref1 is dropped at the end of the block (function body), but despite that, you are still allowed to mutate num after the last use of ref1, making ref1 invalid but not actually dropped yet.

This is a special feature (“non-lexical lifetimes”) that exists to make Rust more usable, and it's only possible because dropping a reference doesn’t perform any operation on the referent.

References (& and &mut), and certain types that contain references, are the only thing that has this behavior of caring about their last point of usage.

3 Likes

So does Last used resource management apply only to references?

ref1 is not deleted after the last use? There is no Last used based resource management?

It doesn't apply to anything, including references.

Borrow checking cares about last uses (and all other uses), but that's not a "resource management" concern. Borrow checking can't change the semantics of your program, such as when things drop.

Borrow checking figures out where and how places (such as variables) are borrowed, compares this against every use of every place, and makes sure there are no conflicts. Going out of scope is a use, but when a reference goes out of scope, the use is very shallow - it doesn't force the referent to still be borrowed for example. (Basically the use conflicts with the reference itself being borrowed - a reference to a reference - but nothing else.)

So it may seem like references drop after the last use, but that's not how the compiler actually works. They still drop at the end of scope. They just don't impose the borrow they hold to stay alive after their last use.

4 Likes

Thank you very much! Now I understand :blush:

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.