Skip to content

Commit d17f9d9

Browse files
Michael Thomasmeta-codesync[bot]
authored andcommitted
Special case typing of top-level function- and static method pointers
Summary: The treatment of function pointers to top-level function and static methods is baked into the lowering of expression trees. The new typing as first-class polymorphic functions introduces two issues: 1) Inference behavior is changed meaning we need hints in many places we didn't before 2) Type checking performance degrades for very complex expression tree blocks This diff adds a flag to the funciton pointer AST nodes and modifies typing so that we instantiate polymorphic function types when they were generated during lowering. Reviewed By: andrewjkennedy Differential Revision: D85429843 fbshipit-source-id: 9772b6fb3c31a6b5f25dc8cb72df7db5deeecfde
1 parent 23b7516 commit d17f9d9

38 files changed

+294
-85
lines changed

hphp/hack/src/annotated_ast/aast_defs.ml

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -528,7 +528,8 @@ and ('ex, 'en) expr_ =
528528
* async { return 1; }
529529
* // lowered to:
530530
* (async () ==> { return 1; })() *)
531-
| FunctionPointer of ('ex, 'en) function_ptr_id * 'ex targ list
531+
| FunctionPointer of
532+
('ex, 'en) function_ptr_id * 'ex targ list * function_pointer_source
532533
(** A reference to a function or method.
533534
*
534535
* foo_fun<>
@@ -791,6 +792,10 @@ and hole_source =
791792
| UnsafeNonnullCast
792793
| EnforcedCast of hint list
793794

795+
and function_pointer_source =
796+
| Code
797+
| Lowered
798+
794799
and ('ex, 'en) binop = {
795800
bop: Ast_defs.bop; [@transform.opaque]
796801
lhs: ('ex, 'en) expr; [@transform.explicit]

hphp/hack/src/client_and_server/identifySymbolService.ml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -379,9 +379,9 @@ let visitor =
379379
let class_id = process_class_id cid in
380380
let xhp_attributes = process_xml_attrs (snd cid) attrs in
381381
self#plus class_id xhp_attributes
382-
| Aast.FunctionPointer (Aast.FP_id id, _targs) -> process_fun_id id
383-
| Aast.FunctionPointer (Aast.FP_class_const ((ty, _, _cid), mid), _targs)
384-
->
382+
| Aast.FunctionPointer (Aast.FP_id id, _targs, _) -> process_fun_id id
383+
| Aast.FunctionPointer
384+
(Aast.FP_class_const ((ty, _, _cid), mid), _targs, _) ->
385385
typed_method env ty mid
386386
| Aast.Method_caller (((_, cid) as pcid), mid) ->
387387
process_fun_id (pos, SN.AutoimportedFunctions.meth_caller)

hphp/hack/src/client_and_server/serverFunDepsBatch.ml

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -92,8 +92,9 @@ let collect_in_decl =
9292
| T.Method_caller ((p, cid), mid) ->
9393
process_function (p, SN.AutoimportedFunctions.meth_caller)
9494
+ process_method_cid mid cid
95-
| T.FunctionPointer (T.FP_id id, _targs) -> process_function id
96-
| T.FunctionPointer (T.FP_class_const ((ty, _, _cid), mid), _targs) ->
95+
| T.FunctionPointer (T.FP_id id, _targs, _) -> process_function id
96+
| T.FunctionPointer (T.FP_class_const ((ty, _, _cid), mid), _targs, _)
97+
->
9798
process_method env ty mid
9899
| _ -> self#zero
99100
in

hphp/hack/src/elab/pass.rs

Lines changed: 39 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
// This source code is licensed under the MIT license found in the
44
// LICENSE file in the "hack" directory of this source tree.
55
//
6-
// @generated SignedSource<<9f71ac8f6616bafee402c8b82064b9d5>>
6+
// @generated SignedSource<<6eac454cb9cb6efbd8d67a1e59cad6fb>>
77
//
88
// To regenerate this file, run:
99
// buck run @fbcode//mode/dev-nosan-lg fbcode//hphp/hack/src:oxidized_regen
@@ -288,6 +288,22 @@ pub trait Pass: PassClone {
288288
Continue(())
289289
}
290290
#[inline(always)]
291+
fn on_ty_function_pointer_source_top_down(
292+
&mut self,
293+
env: &Env,
294+
elem: &mut FunctionPointerSource,
295+
) -> ControlFlow<()> {
296+
Continue(())
297+
}
298+
#[inline(always)]
299+
fn on_ty_function_pointer_source_bottom_up(
300+
&mut self,
301+
env: &Env,
302+
elem: &mut FunctionPointerSource,
303+
) -> ControlFlow<()> {
304+
Continue(())
305+
}
306+
#[inline(always)]
291307
fn on_ty_binop_top_down(&mut self, env: &Env, elem: &mut Binop<Ex, En>) -> ControlFlow<()> {
292308
Continue(())
293309
}
@@ -1780,6 +1796,28 @@ impl Pass for Passes {
17801796
Continue(())
17811797
}
17821798
#[inline(always)]
1799+
fn on_ty_function_pointer_source_top_down(
1800+
&mut self,
1801+
env: &Env,
1802+
elem: &mut FunctionPointerSource,
1803+
) -> ControlFlow<()> {
1804+
for pass in &mut self.passes {
1805+
pass.on_ty_function_pointer_source_top_down(env, elem)?;
1806+
}
1807+
Continue(())
1808+
}
1809+
#[inline(always)]
1810+
fn on_ty_function_pointer_source_bottom_up(
1811+
&mut self,
1812+
env: &Env,
1813+
elem: &mut FunctionPointerSource,
1814+
) -> ControlFlow<()> {
1815+
for pass in &mut self.passes {
1816+
pass.on_ty_function_pointer_source_bottom_up(env, elem)?;
1817+
}
1818+
Continue(())
1819+
}
1820+
#[inline(always)]
17831821
fn on_ty_binop_top_down(&mut self, env: &Env, elem: &mut Binop<Ex, En>) -> ControlFlow<()> {
17841822
for pass in &mut self.passes {
17851823
pass.on_ty_binop_top_down(env, elem)?;

hphp/hack/src/elab/transform.rs

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
// This source code is licensed under the MIT license found in the
44
// LICENSE file in the "hack" directory of this source tree.
55
//
6-
// @generated SignedSource<<7a60ba5cdc7ba5e7590c4c75178f01a5>>
6+
// @generated SignedSource<<3af89af5cb694a41535c3f5734aec361>>
77
//
88
// To regenerate this file, run:
99
// buck run @fbcode//mode/dev-nosan-lg fbcode//hphp/hack/src:oxidized_regen
@@ -762,6 +762,22 @@ impl Transform for HoleSource {
762762
}
763763
}
764764
}
765+
impl Transform for FunctionPointerSource {
766+
fn transform(&mut self, env: &Env, pass: &mut (impl Pass + Clone)) {
767+
let mut in_pass = pass.clone();
768+
if let Break(..) = pass.on_ty_function_pointer_source_top_down(env, self) {
769+
return;
770+
}
771+
stack_limit::maybe_grow(|| self.traverse(env, pass));
772+
let _ = in_pass.on_ty_function_pointer_source_bottom_up(env, self);
773+
}
774+
fn traverse(&mut self, env: &Env, pass: &mut (impl Pass + Clone)) {
775+
match self {
776+
FunctionPointerSource::Code => {}
777+
FunctionPointerSource::Lowered => {}
778+
}
779+
}
780+
}
765781
impl Transform for Binop {
766782
fn transform(&mut self, env: &Env, pass: &mut (impl Pass + Clone)) {
767783
let mut in_pass = pass.clone();

hphp/hack/src/hackc/print_expr/print.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -635,7 +635,7 @@ fn print_expr(
635635
}
636636
Expr_::Efun(f) => print_efun(ctx, w, env, f),
637637
Expr_::FunctionPointer(fp) => {
638-
let (fp_id, targs) = &**fp;
638+
let (fp_id, targs, _) = &**fp;
639639
match fp_id {
640640
ast::FunctionPtrId::FPId(ast::Id(_, sid)) => {
641641
w.write_all(lstrip(adjust_id(env, sid).as_ref(), "\\").as_bytes())?

hphp/hack/src/naming/elaborate_namespaces_visitor.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -400,7 +400,7 @@ impl<'ast> VisitorMut<'ast> for ElaborateNamespacesVisitor {
400400
func.accept(env, self.object())?;
401401
}
402402
}
403-
Expr_::FunctionPointer(box (fpid, targs)) => {
403+
Expr_::FunctionPointer(box (fpid, targs, _)) => {
404404
if let Some(sid) = fpid.as_fpid_mut() {
405405
namespaces::elaborate_id(&env.namespace, namespaces::ElaborateKind::Fun, sid);
406406
} else if let Some(cc) = fpid.as_fpclass_const_mut() {

hphp/hack/src/naming/naming_elab_dynamic_class_name.ml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ let on_expr on_error ((ex, pos, expr_) as expr) ~ctx =
5959
Err.naming @@ Naming_error.Dynamic_class_name_in_strict_mode cg_pos
6060
in
6161
Error [err]
62-
| Aast.(FunctionPointer (FP_class_const ((_, _, ci), _), _))
62+
| Aast.(FunctionPointer (FP_class_const ((_, _, ci), _), _, _))
6363
when is_dynamic ci ->
6464
(* TODO[mjt] report error in strict mode *)
6565
Error []

hphp/hack/src/naming/naming_elaborate_namespaces_endo.ml

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -320,17 +320,20 @@ class ['a, 'b, 'c, 'd] generic_elaborator =
320320
}
321321
in
322322
handle_meth_caller env renamed_call
323-
| FunctionPointer (FP_id fn, targs) ->
323+
| FunctionPointer (FP_id fn, targs, source) ->
324324
let fn = NS.elaborate_id env.namespace NS.ElaborateFun fn in
325325
let targs = List.map targs ~f:(self#on_targ env) in
326-
FunctionPointer (FP_id fn, targs)
326+
FunctionPointer (FP_id fn, targs, source)
327327
| FunctionPointer
328-
(FP_class_const (((), p1, CIexpr ((), p2, Id x1)), meth_name), targs)
329-
->
328+
( FP_class_const (((), p1, CIexpr ((), p2, Id x1)), meth_name),
329+
targs,
330+
source ) ->
330331
let name = elaborate_type_name env x1 in
331332
let targs = List.map targs ~f:(self#on_targ env) in
332333
FunctionPointer
333-
(FP_class_const (((), p1, CIexpr ((), p2, Id name)), meth_name), targs)
334+
( FP_class_const (((), p1, CIexpr ((), p2, Id name)), meth_name),
335+
targs,
336+
source )
334337
| Obj_get (e1, (ty, p, Id x), null_safe, in_parens) ->
335338
Obj_get (self#on_expr env e1, (ty, p, Id x), null_safe, in_parens)
336339
| Id ((_, name) as sid) ->

hphp/hack/src/naming/nast.ml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -835,7 +835,7 @@ module Visitor_DEPRECATED = struct
835835
| Class_const (cid, id) -> this#on_class_const acc cid id
836836
| Call { func = e; args = el; unpacked_arg; _ } ->
837837
this#on_call acc e el unpacked_arg
838-
| FunctionPointer (fpid, targs) ->
838+
| FunctionPointer (fpid, targs, _) ->
839839
this#on_function_pointer acc fpid targs
840840
| String2 el -> this#on_string2 acc el
841841
| PrefixedString (_, e) -> this#on_expr acc e

0 commit comments

Comments
 (0)