Permalink
Browse files

Handle saved_envs on lambdas in Tast_visitor

Summary: Previously, we only restored the typing environment from a function's saved_env for toplevel function definitions. This meant that we ignored the saved_env for lambda expressions. In order to make use of it, this change adds an on_fun_ override to all Tast_visitor classes, which properly sets up the typing environment for lambda expressions.

Reviewed By: pittsw

Differential Revision: D6973297

fbshipit-source-id: 82e58758fe437ef8dd025f183b21be3b01699e5d
  • Loading branch information...
Jake Bailey authored and hhvm-bot committed Feb 28, 2018
1 parent 82c5ab8 commit cae78d25d8be9aeaaf585d9b310434ab59b23d4b
@@ -29,7 +29,7 @@ end
module StringNAST = Nast.AnnotatedAST(StringNASTAnnotations)
module TASTStringMapper =
Aast_mapper.MapAnnotatedAST(Tast.Annotations)(StringNASTAnnotations)
Aast_mapper.MapAnnotatedAST(Tast_expand.ExpandedTypeAnnotations)(StringNASTAnnotations)
module TASTTypeStripper =
Aast_mapper.MapAnnotatedAST(Tast.Annotations)(Nast.Annotations)
@@ -772,21 +772,21 @@ let handle_mode mode filename tcopt popt files_contents files_info errors =
Printf.printf "Errors:\n";
List.iter errors (fun err ->
List.iter (Errors.to_list err) (fun (pos, msg) ->
Format.printf " %a %s\n" Pos.pp pos msg))
Format.printf " %a %s" Pos.pp pos msg;
Format.print_newline ()))
);
let env = Typing_env.empty tcopt filename ~droot:None in
let stringify_types =
TASTStringMapper.map_program
~map_env_annotation:(fun _ -> ())
~map_expr_annotation:begin fun saved_env (pos, ty) ->
let env = Tast_expand.restore_saved_env env saved_env in
let stringify_types tast =
let tast = Tast_expand.expand_program tast in
TASTStringMapper.map_program tast
~map_env_annotation:(fun () -> ())
~map_expr_annotation:begin fun () (pos, ty) ->
match ty with
| None -> Format.asprintf "(%a, None)" Pos.pp pos
| Some ty ->
Format.asprintf "(%a, Some %s)" Pos.pp pos (Typing_print.full env ty)
end
~map_class_id_annotation:begin fun saved_env ty ->
let env = Tast_expand.restore_saved_env env saved_env in
~map_class_id_annotation:begin fun () ty ->
match ty with
| None -> "(None)"
| Some ty -> Printf.sprintf "(Some %s)" (Typing_print.full env ty)
@@ -104,13 +104,19 @@ let expand_ty env ty =
let expand_annotation env (pos, tyopt) =
(pos, Option.map tyopt (expand_ty env))
let restore_saved_env env saved_env =
let module Env = Typing_env in
{env with
Env.genv = {env.Env.genv with Env.tcopt = saved_env.Tast.tcopt};
Env.tenv = saved_env.Tast.tenv;
Env.subst = saved_env.Tast.subst;
}
class ['self] expander = object (_ : 'self)
inherit [_] Tast_visitor.endo
method! on_expr_annotation = expand_annotation
method! on_class_id_annotation env tyopt = Option.map tyopt (expand_ty env)
end
module ExpandAST =
Aast_mapper.MapAnnotatedAST(Tast.Annotations)(ExpandedTypeAnnotations)
(* Replace all types in a program AST by their expansions *)
let expand_program tast =
let tast = new expander#go tast in
ExpandAST.map_program tast
~map_env_annotation:(fun _ -> ())
~map_class_id_annotation:(fun _ x -> x)
~map_expr_annotation:(fun _ x -> x)
@@ -12,24 +12,35 @@ module EnvFromDef = Typing_env_from_def.EnvFromDef(Tast.Annotations)
open Tast
let restore_saved_env env saved_env =
let module Env = Typing_env in
{env with
Env.genv = {env.Env.genv with Env.tcopt = saved_env.Tast.tcopt};
Env.tenv = saved_env.Tast.tenv;
Env.subst = saved_env.Tast.subst;
}
let restore_fun_env env f =
restore_saved_env env f.f_annotation
let restore_method_env env m =
restore_saved_env env m.m_annotation
let fun_env f =
let env = EnvFromDef.fun_env f.f_annotation.tcopt f in
Tast_expand.restore_saved_env env f.f_annotation
restore_fun_env env f
let class_env c =
let env = EnvFromDef.class_env c.c_annotation.tcopt c in
Tast_expand.restore_saved_env env c.c_annotation
restore_saved_env env c.c_annotation
let typedef_env t =
let env = EnvFromDef.typedef_env t.t_annotation.tcopt t in
Tast_expand.restore_saved_env env t.t_annotation
restore_saved_env env t.t_annotation
let gconst_env cst =
let env = EnvFromDef.gconst_env cst.cst_annotation.tcopt cst in
Tast_expand.restore_saved_env env cst.cst_annotation
let method_env env m =
Tast_expand.restore_saved_env env m.m_annotation
restore_saved_env env cst.cst_annotation
class virtual ['self] iter = object (self : 'self)
inherit [_] Tast.iter as super
@@ -49,7 +60,8 @@ class virtual ['self] iter = object (self : 'self)
method go_Typedef x = self#on_Typedef (typedef_env x) x
method go_Constant x = self#on_Constant (gconst_env x) x
method! on_method_ env x = super#on_method_ (method_env env x) x
method! on_fun_ env x = super#on_fun_ (restore_fun_env env x) x
method! on_method_ env x = super#on_method_ (restore_method_env env x) x
method! on_static_var env x =
super#on_static_var (Typing_env.set_static env) x
@@ -75,7 +87,8 @@ class virtual ['self] reduce = object (self : 'self)
method go_Typedef x = self#on_Typedef (typedef_env x) x
method go_Constant x = self#on_Constant (gconst_env x) x
method! on_method_ env x = super#on_method_ (method_env env x) x
method! on_fun_ env x = super#on_fun_ (restore_fun_env env x) x
method! on_method_ env x = super#on_method_ (restore_method_env env x) x
method! on_static_var env x =
super#on_static_var (Typing_env.set_static env) x
@@ -101,7 +114,8 @@ class virtual ['self] map = object (self : 'self)
method go_Typedef x = self#on_Typedef (typedef_env x) x
method go_Constant x = self#on_Constant (gconst_env x) x
method! on_method_ env x = super#on_method_ (method_env env x) x
method! on_fun_ env x = super#on_fun_ (restore_fun_env env x) x
method! on_method_ env x = super#on_method_ (restore_method_env env x) x
method! on_static_var env x =
super#on_static_var (Typing_env.set_static env) x
@@ -127,7 +141,8 @@ class virtual ['self] endo = object (self : 'self)
method go_Typedef def x = self#on_Typedef (typedef_env x) def x
method go_Constant def x = self#on_Constant (gconst_env x) def x
method! on_method_ env x = super#on_method_ (method_env env x) x
method! on_fun_ env x = super#on_fun_ (restore_fun_env env x) x
method! on_method_ env x = super#on_method_ (restore_method_env env x) x
method! on_static_var env x =
super#on_static_var (Typing_env.set_static env) x
@@ -0,0 +1,12 @@
<?hh // strict
async function genString(string $s): Awaitable<string> { return $s; }
function test(): void {
$f0 = async () ==> {
$str = await genString('foo');
};
$f1 = async $x ==> {
$str = await genString($x);
};
}
@@ -0,0 +1,127 @@
[(AnnotatedAST.Fun
{ AnnotatedAST.f_annotation = (); f_mode = <opaque>;
f_ret =
(Some ([3:38-3:47],
(Happly (([3:38-3:47], "\\Awaitable"),
[([3:48-3:54], (Hprim Tstring))]))));
f_name = ([3:16-3:25], "\\genString"); f_tparams = [];
f_where_constraints = []; f_variadic = AnnotatedAST.FVnonVariadic;
f_params =
[{ AnnotatedAST.param_hint = (Some ([3:26-3:32], (Hprim Tstring)));
param_is_reference = false; param_is_variadic = false;
param_pos = [3:33-3:35]; param_name = "$s"; param_expr = None;
param_callconv = None; param_user_attributes = [] }
];
f_body =
(AnnotatedAST.NamedBody
{ AnnotatedAST.fnb_nast =
[(AnnotatedAST.Return ([3:58-3:68],
(Some (([3:65-3:67], Some string),
(AnnotatedAST.Lvar ([3:65-3:67], $s))))
))
];
fnb_unsafe = false });
f_fun_kind = FAsync; f_user_attributes = []; f_ret_by_ref = false });
(AnnotatedAST.Fun
{ AnnotatedAST.f_annotation = (); f_mode = <opaque>;
f_ret = (Some ([5:18-5:22], (Hprim Tvoid)));
f_name = ([5:10-5:14], "\\test"); f_tparams = [];
f_where_constraints = []; f_variadic = AnnotatedAST.FVnonVariadic;
f_params = [];
f_body =
(AnnotatedAST.NamedBody
{ AnnotatedAST.fnb_nast =
[(AnnotatedAST.Expr
(([6:3-6:14], Some (function(): \Awaitable<void>)),
(AnnotatedAST.Binop ((Eq None),
(([6:3-6:6], Some (function(): \Awaitable<void>)),
(AnnotatedAST.Lvar ([6:3-6:6], $f0))),
(([6:9-6:14], Some \Awaitable<void>),
(AnnotatedAST.Efun (
{ AnnotatedAST.f_annotation = (); f_mode = <opaque>;
f_ret = None; f_name = ([Pos.none], ";anonymous");
f_tparams = []; f_where_constraints = [];
f_variadic = AnnotatedAST.FVnonVariadic;
f_params = [];
f_body =
(AnnotatedAST.NamedBody
{ AnnotatedAST.fnb_nast =
[(AnnotatedAST.Expr
(([7:5-7:34], Some string),
(AnnotatedAST.Binop ((Eq None),
(([7:5-7:9], Some string),
(AnnotatedAST.Lvar ([7:5-7:9], $str))),
(([7:12-7:34], Some string),
(AnnotatedAST.Await
(([7:18-7:34], Some \Awaitable<string>),
(AnnotatedAST.Call (Cnormal,
(([7:18-7:27], Some (function(string $s): \Awaitable<string>)),
(AnnotatedAST.Id
([7:18-7:27],
"\\genString"))),
[],
[(([7:28-7:33], Some string),
(AnnotatedAST.String
([7:28-7:33], "foo")))
],
[])))))
))))
];
fnb_unsafe = false });
f_fun_kind = FAsync; f_user_attributes = [];
f_ret_by_ref = false },
[])))
))));
(AnnotatedAST.Expr
(([9:3-9:14], Some [fun]),
(AnnotatedAST.Binop ((Eq None),
(([9:3-9:6], Some [fun]),
(AnnotatedAST.Lvar ([9:3-9:6], $f1))),
(([9:9-9:14], Some _),
(AnnotatedAST.Efun (
{ AnnotatedAST.f_annotation = (); f_mode = <opaque>;
f_ret = None; f_name = ([Pos.none], ";anonymous");
f_tparams = []; f_where_constraints = [];
f_variadic = AnnotatedAST.FVnonVariadic;
f_params =
[{ AnnotatedAST.param_hint = None;
param_is_reference = false;
param_is_variadic = false;
param_pos = [9:15-9:17]; param_name = "$x";
param_expr = None; param_callconv = None;
param_user_attributes = [] }
];
f_body =
(AnnotatedAST.NamedBody
{ AnnotatedAST.fnb_nast =
[(AnnotatedAST.Expr
(([10:5-10:31], Some string),
(AnnotatedAST.Binop ((Eq None),
(([10:5-10:9], Some string),
(AnnotatedAST.Lvar
([10:5-10:9], $str))),
(([10:12-10:31], Some string),
(AnnotatedAST.Await
(([10:18-10:31], Some \Awaitable<string>),
(AnnotatedAST.Call (Cnormal,
(([10:18-10:27], Some (function(string $s): \Awaitable<string>)),
(AnnotatedAST.Id
([10:18-10:27],
"\\genString"))),
[],
[(([10:28-10:30], Some _),
(AnnotatedAST.Lvar
([10:28-10:30], $x)))
],
[])))))
))))
];
fnb_unsafe = false });
f_fun_kind = FAsync; f_user_attributes = [];
f_ret_by_ref = false },
[])))
))))
];
fnb_unsafe = false });
f_fun_kind = FSync; f_user_attributes = []; f_ret_by_ref = false })
]

0 comments on commit cae78d2

Please sign in to comment.