Named/labeled scopes

Here's a small, mostly meaningless, feature I'd like to see: Named/labeled scopes

Sometimes I want to create explicit scopes which have the singular purpose of having things go out of the scope so that resources are released at a particular time (tends to happen in multithreaded applications, for instance). But rather than this:

fn bar() {
  //  ... blah ...
  {
    let foo = resource.lock();
    log("locked the file");
    // ... blah ...
  }
  // ... blah ...
}

I would like to be able to do something like this:

fn bar() {
  //  ... blah ...
  lock_the_file {
    let foo = resource.lock()
    log(scope_name);  // expands to "lock_the_file"
    // ... blah ...
  }
  // ... blah ...
}

The scope name/label would be nothing more than a name/label, and could be useful in trace outputs to identify code blocks.

Is there already a way to accomplish this? (I'm explicitly looking for something that doesn't affect the output (unless the name/label is referenced within the block).

My first thought would be that you can hack a solution using

let _lock_the_file = {
   // do stuff
};

However I'm not sure how practical that is.

1 Like

There is something on loops and there is an RFC to make it possible on scopes too, but I don't think you can get the name to log it.

1 Like

A bit verbose, but you could do something like:

fn trace<F, R>(label: &str, block: F) -> R
where
    F: FnOnce() -> R,
{
    println!("entered {}", label);
    let ret = block();
    println!("exited {}", label);
    ret
}

fn main() {
    let four = trace("2 + 2", || {
        2.0 + 2.0
    });
    println!("2 + 2 = {}", four);
}

Of course, you can replace the println calls with timing/debugging, etc.

1 Like

You may also find Diagnostics with tracing interesting.

It takes this concept of a named scope and uses it to help you track what your application is doing. This is especially useful in async/threaded code where normal log statements would become interleaved or confusing.

2 Likes