Comment on Rust is Eating JavaScript

<- View Parent
sugar_in_your_tea@sh.itjust.works ⁨4⁩ ⁨days⁩ ago

I assume you’re talking about runtime. AddCleanup()? That’s certainly nice, but it’s not the same as a destructor since it only runs at GC time. It’s useful for cleaning up data used by a shared library or something (e.g. something malloc’d by a C lib), but it only solves part of the problem.

I’m talking about scope guards. In Rust, here’s how you deal with mutexes:

{
    let value = mutex.Lock();
    ... use value ...
    // mutex.Unlock() automatically called
} 

The closest thing in Go is defer():

mutex.Lock()
defer mutex.Unlock()

That works most of the time, but it doesn’t handle more complex use cases, like selectively unlocking a mutex early while still guaranteeing it eventually gets unlocked.

Rust fixes this with the Drop trait, so basically I can drop something early conditionally, but it’ll get dropped automatically when going out of scope. For example:

struct A(String);

impl Drop for A {
    fn drop(&mut self) {
        println!("dropping {}", self.0)
    }
}

fn main() {
    let a = A("a".into());
    let b = A("b".into());
    let c = A("c".into());
    drop(b);
}

Without the last line, this prints c, b, a, i.e. stack order. With the last line, it instead prints b, c, a, because I drop b early.

This is incredibly useful when dealing with complex logic, especially with mutexes, because it allows you to cleanly and correctly handle edge cases. Things are dropped at block scope too, giving even more control of semantically releasing things like locks.

That said, 1.24 added WASM, which is really cool, so thanks for encouraging me to look at the release notes.

source
Sort:hotnewtop