What are the drop order guarantees for local and captured variables in async functions/blocks?

I'm trying to understand the exact drop order guarantees for variables in async functions and async blocks. Specifically, I'm confused about how two different categories of variables behave:

  1. Captured variables (including async fn parameters captured by the implicit async move block).
  2. Local variables declared inside the async body (especially those held across .await points).

Context & References

1. Captured Variables:
According to the Rust Reference on Async Blocks:

Executing an async block is similar to executing a closure expression: its immediate effect is to produce and return an anonymous type.

And for closures, the Rust Reference on Closure Types states:

The variables that a closure captures by move are dropped in an unspecified order.

Since an async fn parameters are captured by the desugared async move block, this suggests their drop order might be unspecified.

2. Local Variables inside the async body:
In standard synchronous functions, local variables are dropped in reverse declaration order. However, inside an async block, local variables that live across .await points are compiled into fields of the underlying generator/Future state machine struct.

Questions

  1. Captured Variables / Function Parameters: Is the drop order of captured variables (and async fn parameters) strictly unspecified, just like closures?
  2. Local Variables declared inside: Are local variables inside an async block still strictly guaranteed to drop in reverse declaration order?
  3. Interactions: What is the relative drop order between local variables and captured variables when a Future is dropped? (e.g., are locals dropped before captures?)

Code Example

Consider this scenario:

struct Guard(&'static str);
impl Drop for Guard {
    fn drop(&mut self) {
        println!("Dropped: {}", self.0);
    }
}

async fn test_drop_order(param1: Guard, param2: Guard) {
    let local1 = Guard("local1");
    
    let local2 = Guard("local2");
}

If the Future returned by test_drop_order is dropped:

  • Is local2 guaranteed to drop before local1?
  • Is the drop order between param1 and param2 unspecified?