macro_rules! async_closure_mut {
    (
        { $( $field:ident : $t:ty  = $init:expr ),* $(,)? };
        async | $( $args:ident  : $a:ty ),* $(,)? | -> $out:ty
        $e:block
    ) => { ... };
}
Expand description

Generate a value that is of unnamed closure type implemented with AsyncFnMut.

Syntax

Consisted of two parts:

  1. a block {}; in which multiple assignments field_name: field_type = field_value are seperated by ,
  2. an async closure async |arg1: arg1_type, ...| -> return_type { /* any async code here */ }

Fields or arguments can be empty, i.e.

  • empty fields: {};
  • empty arguments: async | | -> return_type { /* async code and captured variables */ }
    (note it’s | | instead of ||, and the return_type is a must anyway)

Details:

componentrule / usagetrick / caveat
field_nameused as unnamed struct’s fields and variable names in async coderebind when mutation is required
field_typeowned types or referenced typesonly 'static or 'a lifetime allowed
field_valueany value expression as the initial states / captured variables
arg_nameused as variable names in async code (_ is not an ident thus disallowed)rebind when mutation is required
arg_typeowned types or referenced types (normally no need to annotate lifetimes )'a is disallowed; but '_ is allowed
return_typea must (even when () is returned)

Also note: arg_types and return_type must correspond to its AsyncFn* generic types, i.e.

#![feature(async_fn_in_trait)]
#![allow(incomplete_features)]
use async_closure::async_closure_mut;

// correspond to `capture_lifetimes::AsyncFnMut<'env, (), usize>`
// note that the concept of arguments is represented by a tuple
async_closure_mut!({}; async | | -> usize { 0 }); 

// `for<'any> capture_lifetimes::AsyncFnMut<'env, (&'any str,), usize>`
// note that single argument is represented by `(type,)` where the comma is important
async_closure_mut!({}; async |_s: &str| -> usize { 0 }); 

// `for<'any> capture_lifetimes::AsyncFnMut<'env, (&'any str, &'any mut Vec<u8>), ()>`
async_closure_mut!({}; async |_s: &str, _buf: &mut Vec<u8>| -> () {}); 

// etc.

Examples

#![feature(async_fn_in_trait)]
#![allow(incomplete_features)]
use async_closure::async_closure_mut as cb;

let mut v = vec![];

// zero arguments
cb!({
    v: &'a mut Vec<u8> = &mut v,
}; async | | -> usize {
    // to show the type; you don't have to do this
    let v: &mut &mut Vec<u8> = v;
    v.push(0);
    v.len()
});

// one argument and returns unit type
cb!({
    v: &'a mut Vec<u8> = &mut v,
}; async |_s: &mut [u8]| -> () { }); // `_` is not an ident, thus not allowed

// two arguments
// Note: you can never return the referenced captured data with lifetime 'a
use std::borrow::Cow;
cb!(
    { v: &'a mut Vec<u8> = &mut v };
    async |arg1: &mut [u8], arg2: Cow<'_, str>| -> () /* &'a mut Vec<u8> */ { /* v */ }
);

// three arguments and rebinds the variables
cb!({ v: &'a mut Vec<u8> = &mut v };
    async |arg1: &mut [u8], arg2: Cow<'_, str>, vec: Vec<u8>| -> () {
    let mut vec = vec; // rebinding
    std::mem::swap(&mut vec, v); // v: &mut &mut Vec<u8>
    std::mem::swap(&mut vec, *v);
});
cb!({ v: Vec<u8> = v };
    async |arg1: &mut [u8], arg2: Cow<'_, str>, vec: Vec<u8>| -> () {
    let mut vec = vec; // rebinding
    std::mem::swap(&mut vec, v);
});