Pattern Matching

Is there any technical differences between match and if when checking things. Consider this:

...
let resp = match some_async_fn(arg).await {
    ...
    //arms here
    ...
}
...

and this:

...
let resp = some_async_fn(arg).await;
let val = match resp {
    ...
    //arms here
    ...
}
...

Does matching directly into .await call has certain overhead over matching the returned value?

There's no overhead. match expects an expression, so either storing it in a variable or matching directly on it works the same.

There is generally no overhead, however, in certain cases the ordering of freeing resources may be different:

struct BigResource { /* … */ }

impl Drop for BigResource {
    fn drop(&mut self) {
        println!("BigResource has been released")
    }
}

struct Foo {
    number: i32,
    #[allow(dead_code)]
    big: BigResource,
}

async fn some_async_fn(arg: i32) -> Foo {
    Foo {
        number: arg + 1,
        big: BigResource { /* … */ },
    }
}

async fn foo() {
    let resp = some_async_fn(7).await;
    let val = match resp {
        Foo { number, .. } => {
            println!("Doing some work here");
            number
        }
    };
    println!("Doing more work here");
    println!("Result: {}", val);
}

async fn bar() {
    let val = match some_async_fn(7).await {
        Foo { number, .. } => {
            println!("Doing some work here");
            number
        }
    };
    println!("Doing more work here");
    println!("Result: {}", val);
}

#[tokio::main]
async fn main() {
    foo().await;
    println!("------------");
    bar().await;
}

(Playground)

Output:

Doing some work here
Doing more work here
Result: 8
BigResource has been released
------------
Doing some work here
BigResource has been released
Doing more work here
Result: 8

If that is an issue, you could also drop manually.


I think the corresponding section of the reference is "Temporary Scopes" in "Drop Scopes" in "Destructors". Difficult to read though (for me).

2 Likes

This article has a fairly thorough walkthrough of how this difference can cause bugs in real code

What kind of overhead would you expect and why?

great explanation, thanks!