@@ -95,13 +95,35 @@ let expr_mapper ~async_context ~in_function_def (self : mapper)
9595 | Pexp_newtype (s , body ) ->
9696 let res = self.expr self body in
9797 {e with pexp_desc = Pexp_newtype (s, res)}
98- | Pexp_fun {arg_label = label ; lhs = pat ; rhs = body ; async} -> (
98+ | Pexp_fun {arg_label = label; lhs = pat; rhs = body; async; arity; default}
99+ -> (
99100 match Ast_attributes. process_attributes_rev e.pexp_attributes with
100101 | Nothing , _ ->
101102 (* Handle @async x => y => ... is in async context *)
102103 async_context := (old_in_function_def && ! async_context) || async;
104+ (* The default mapper would descend into nested [Pexp_fun] nodes (used for
105+ additional parameters) before visiting the function body. Those
106+ nested calls see [async = false] and would reset [async_context] to
107+ false, so by the time we translate the body we incorrectly think we are
108+ outside of an async function. This shows up with function-level
109+ [@directive] (GH #7974): the directive attribute lives on the outer
110+ async lambda, while extra parameters are represented as nested
111+ functions. Rebuild the function manually to keep the async flag alive
112+ until the body is processed. *)
113+ let attrs = self.attributes self e.pexp_attributes in
114+ let default = Option. map (self.expr self) default in
115+ let lhs = self.pat self pat in
116+ let saved_in_function_def = ! in_function_def in
103117 in_function_def := true ;
104- Ast_async. make_function_async ~async (default_expr_mapper self e)
118+ (* Keep reporting nested parameters as part of a function definition so
119+ they propagate async context exactly like the original mapper. *)
120+ let rhs = self.expr self body in
121+ in_function_def := saved_in_function_def;
122+ let mapped =
123+ Ast_helper.Exp. fun_ ~loc: e.pexp_loc ~attrs ~arity ~async label default
124+ lhs rhs
125+ in
126+ Ast_async. make_function_async ~async mapped
105127 | Meth_callback _ , pexp_attributes ->
106128 (* FIXME: does it make sense to have a label for [this] ? *)
107129 async_context := false ;
0 commit comments