pub(crate) fn from_fn(input: &'block ItemFn) -> Option<Self> {
        // are we in an async context? If yes, this isn't a async_trait-like pattern
        if input.sig.asyncness.is_some() {
            return None;
        }

        let block = &input.block;

        // list of async functions declared inside the block
        let inside_funs = block.stmts.iter().filter_map(|stmt| {
            if let Stmt::Item(Item::Fn(fun)) = &stmt {
                // If the function is async, this is a candidate
                if fun.sig.asyncness.is_some() {
                    return Some((stmt, fun));
                }
            }
            None
        });

        // last expression of the block (it determines the return value
        // of the block, so that if we are working on a function whose
        // `trait` or `impl` declaration is annotated by async_trait,
        // this is quite likely the point where the future is pinned)
        let (last_expr_stmt, last_expr) = block.stmts.iter().rev().find_map(|stmt| {
            if let Stmt::Expr(expr) = stmt {
                Some((stmt, expr))
            } else {
                None
            }
        })?;

        // is the last expression a function call?
        let (outside_func, outside_args) = match last_expr {
            Expr::Call(ExprCall { func, args, .. }) => (func, args),
            _ => return None,
        };

        // is it a call to `Box::pin()`?
        let path = match outside_func.as_ref() {
            Expr::Path(path) => &path.path,
            _ => return None,
        };
        if !path_to_string(path).ends_with("Box::pin") {
            return None;
        }

        // Does the call take an argument? If it doesn't,
        // it's not gonna compile anyway, but that's no reason
        // to (try to) perform an out of bounds access
        if outside_args.is_empty() {
            return None;
        }

        // Is the argument to Box::pin an async block that
        // captures its arguments?
        if let Expr::Async(async_expr) = &outside_args[0] {
            // check that the move 'keyword' is present
            async_expr.capture?;

            return Some(AsyncTraitInfo {
                source_stmt: last_expr_stmt,
                kind: AsyncTraitKind::Async(async_expr),
                self_type: None,
                input,
            });
        }

        // Is the argument to Box::pin a function call itself?
        let func = match &outside_args[0] {
            Expr::Call(ExprCall { func, .. }) => func,
            _ => return None,
        };

        // "stringify" the path of the function called
        let func_name = match **func {
            Expr::Path(ref func_path) => path_to_string(&func_path.path),
            _ => return None,
        };

        // Was that function defined inside of the current block?
        // If so, retrieve the statement where it was declared and the function itself
        let (stmt_func_declaration, func) = inside_funs
            .into_iter()
            .find(|(_, fun)| fun.sig.ident == func_name)?;

        // If "_self" is present as an argument, we store its type to be able to rewrite "Self" (the
        // parameter type) with the type of "_self"
        let mut self_type = None;
        for arg in &func.sig.inputs {
            if let FnArg::Typed(ty) = arg {
                if let Pat::Ident(PatIdent { ref ident, .. }) = *ty.pat {
                    if ident == "_self" {
                        let mut ty = *ty.ty.clone();
                        // extract the inner type if the argument is "&self" or "&mut self"
                        if let syn::Type::Reference(syn::TypeReference { elem, .. }) = ty {
                            ty = *elem;
                        }

                        if let syn::Type::Path(tp) = ty {
                            self_type = Some(tp);
                            break;
                        }
                    }
                }
            }
        }

        Some(AsyncTraitInfo {
            source_stmt: stmt_func_declaration,
            kind: AsyncTraitKind::Function(func),
            self_type,
            input,
        })
    }
/// Get the AST of the inner function we need to hook, if it was generated
/// by async-trait.
///
/// When we are given a function annotated by async-trait, that function
/// is only a placeholder that returns a pinned future containing the
/// user logic, and it is that pinned future that needs to be instrumented.
/// Were we to instrument its parent, we would only collect information
/// regarding the allocation of that future, and not its own span of execution.
/// Depending on the version of async-trait, we inspect the block of the function
/// to find if it matches the pattern
///
/// `async fn foo<...>(...) {...}; Box::pin(foo<...>(...))` (<=0.1.43), or if
/// it matches `Box::pin(async move { ... }) (>=0.1.44). We the return the
/// statement that must be instrumented, along with some other informations.
/// 'gen_body' will then be able to use that information to instrument the
/// proper function/future.
///
/// (this follows the approach suggested in
/// https://github.com/dtolnay/async-trait/issues/45#issuecomment-571245673)
Get the AST of the inner function we need to hook, if it was generated
by async-trait.

When we are given a function annotated by async-trait, that function
is only a placeholder that returns a pinned future containing the
user logic, and it is that pinned future that needs to be instrumented.
Were we to instrument its parent, we would only collect information
regarding the allocation of that future, and not its own span of execution.
Depending on the version of async-trait, we inspect the block of the function
to find if it matches the pattern




Get the AST of the inner function we need to hook if it was generated by async - trait . When we are given a function annotated by async - trait that function is only a placeholder that returns a pinned future containing the user logic and it is that pinned future that needs to be instrumented . Were we to instrument its parent we would only collect information regarding the allocation of that future and not its own span of execution . Depending on the version of async - trait we inspect the block of the function to find if it matches the pattern
pub(crate) fn from_fn(input: &'block ItemFn) -> Option<Self> {
        // are we in an async context? If yes, this isn't a async_trait-like pattern
        if input.sig.asyncness.is_some() {
            return None;
        }
        let block = &input.block;
        // list of async functions declared inside the block
        let inside_funs = block.stmts.iter().filter_map(|stmt| {
            if let Stmt::Item(Item::Fn(fun)) = &stmt {
                // If the function is async, this is a candidate
                if fun.sig.asyncness.is_some() {
                    return Some((stmt, fun));
                }
            }
            None
        });
        // last expression of the block (it determines the return value
        // of the block, so that if we are working on a function whose
        // `trait` or `impl` declaration is annotated by async_trait,
        // this is quite likely the point where the future is pinned)
        let (last_expr_stmt, last_expr) = block.stmts.iter().rev().find_map(|stmt| {
            if let Stmt::Expr(expr) = stmt {
                Some((stmt, expr))
            } else {
                None
            }
        })?;
        // is the last expression a function call?
        let (outside_func, outside_args) = match last_expr {
            Expr::Call(ExprCall { func, args, .. }) => (func, args),
            _ => return None,
        };
        // is it a call to `Box::pin()`?
        let path = match outside_func.as_ref() {
            Expr::Path(path) => &path.path,
            _ => return None,
        };
        if !path_to_string(path).ends_with("Box::pin") {
            return None;
        }
        // Does the call take an argument? If it doesn't,
        // it's not gonna compile anyway, but that's no reason
        // to (try to) perform an out of bounds access
        if outside_args.is_empty() {
            return None;
        }
        // Is the argument to Box::pin an async block that
        // captures its arguments?
        if let Expr::Async(async_expr) = &outside_args[0] {
            // check that the move 'keyword' is present
            async_expr.capture?;
            return Some(AsyncTraitInfo {
                source_stmt: last_expr_stmt,
                kind: AsyncTraitKind::Async(async_expr),
                self_type: None,
                input,
            });
        }
        // Is the argument to Box::pin a function call itself?
        let func = match &outside_args[0] {
            Expr::Call(ExprCall { func, .. }) => func,
            _ => return None,
        };
        // "stringify" the path of the function called
        let func_name = match **func {
            Expr::Path(ref func_path) => path_to_string(&func_path.path),
            _ => return None,
        };
        // Was that function defined inside of the current block?
        // If so, retrieve the statement where it was declared and the function itself
        let (stmt_func_declaration, func) = inside_funs
            .into_iter()
            .find(|(_, fun)| fun.sig.ident == func_name)?;
        // If "_self" is present as an argument, we store its type to be able to rewrite "Self" (the
        // parameter type) with the type of "_self"
        let mut self_type = None;
        for arg in &func.sig.inputs {
            if let FnArg::Typed(ty) = arg {
                if let Pat::Ident(PatIdent { ref ident, .. }) = *ty.pat {
                    if ident == "_self" {
                        let mut ty = *ty.ty.clone();
                        // extract the inner type if the argument is "&self" or "&mut self"
                        if let syn::Type::Reference(syn::TypeReference { elem, .. }) = ty {
                            ty = *elem;
                        }
                        if let syn::Type::Path(tp) = ty {
                            self_type = Some(tp);
                            break;
                        }
                    }
                }
            }
        }
        Some(AsyncTraitInfo {
            source_stmt: stmt_func_declaration,
            kind: AsyncTraitKind::Function(func),
            self_type,
            input,
        })
    }
pub ( crate ) fn from_fn ( input : & ' block ItemFn ) -> Option < Self > { // are we in an async context? If yes, this isn't a async_trait-like pattern if input . sig . asyncness . is_some ( ) { return None ; } let block = & input . block ; // list of async functions declared inside the block let inside_funs = block . stmts . iter ( ) . filter_map ( | stmt | { if let Stmt :: Item ( Item :: Fn ( fun ) ) = & stmt { // If the function is async, this is a candidate if fun . sig . asyncness . is_some ( ) { return Some ( ( stmt , fun ) ) ; } } None } ) ; // last expression of the block (it determines the return value // of the block, so that if we are working on a function whose // `trait` or `impl` declaration is annotated by async_trait, // this is quite likely the point where the future is pinned) let ( last_expr_stmt , last_expr ) = block . stmts . iter ( ) . rev ( ) . find_map ( | stmt | { if let Stmt :: Expr ( expr ) = stmt { Some ( ( stmt , expr ) ) } else { None } } ) ? ; // is the last expression a function call? let ( outside_func , outside_args ) = match last_expr { Expr :: Call ( ExprCall { func , args , .. } ) => ( func , args ) , _ => return None , } ; // is it a call to `Box::pin()`? let path = match outside_func . as_ref ( ) { Expr :: Path ( path ) => & path . path , _ => return None , } ; if ! path_to_string ( path ) . ends_with ( " " ) { return None ; } // Does the call take an argument? If it doesn't, // it's not gonna compile anyway, but that's no reason // to (try to) perform an out of bounds access if outside_args . is_empty ( ) { return None ; } // Is the argument to Box::pin an async block that // captures its arguments? if let Expr :: Async ( async_expr ) = & outside_args [ 0 ] { // check that the move 'keyword' is present async_expr . capture ? ; return Some ( AsyncTraitInfo { source_stmt : last_expr_stmt , kind : AsyncTraitKind :: Async ( async_expr ) , self_type : None , input , } ) ; } // Is the argument to Box::pin a function call itself? let func = match & outside_args [ 0 ] { Expr :: Call ( ExprCall { func , .. } ) => func , _ => return None , } ; // "stringify" the path of the function called let func_name = match * * func { Expr :: Path ( ref func_path ) => path_to_string ( & func_path . path ) , _ => return None , } ; // Was that function defined inside of the current block? // If so, retrieve the statement where it was declared and the function itself let ( stmt_func_declaration , func ) = inside_funs . into_iter ( ) . find ( | ( _ , fun ) | fun . sig . ident == func_name ) ? ; // If "_self" is present as an argument, we store its type to be able to rewrite "Self" (the // parameter type) with the type of "_self" let mut self_type = None ; for arg in & func . sig . inputs { if let FnArg :: Typed ( ty ) = arg { if let Pat :: Ident ( PatIdent { ref ident , .. } ) = * ty . pat { if ident == " " { let mut ty = * ty . ty . clone ( ) ; // extract the inner type if the argument is "&self" or "&mut self" if let syn :: Type :: Reference ( syn :: TypeReference { elem , .. } ) = ty { ty = * elem ; } if let syn :: Type :: Path ( tp ) = ty { self_type = Some ( tp ) ; break ; } } } } } Some ( AsyncTraitInfo { source_stmt : stmt_func_declaration , kind : AsyncTraitKind :: Function ( func ) , self_type , input , } ) }
Get the AST of the inner function we need to hook, if it was generated
by async-trait.
Get the AST of the inner function we need to hook if it was generated by async - trait .
input
&'block ItemFn