Correctly type spliced expressions
commit7f4a67f0f629913f9719a9def4a4dfa783ff8013
authorThomas Jiang <thomasjiang@fb.com>
Fri, 16 Oct 2020 18:27:53 +0000 (16 11:27 -0700)
committerFacebook GitHub Bot <facebook-github-bot@users.noreply.github.com>
Fri, 16 Oct 2020 18:30:42 +0000 (16 11:30 -0700)
tree9a2ef073b397c257861e14e0d682e023e98b4fcb
parent7943e905b00a14035d2976be75518102f4c3e78c
Correctly type spliced expressions

Summary:
Up to this point, we've been typing spliced expressions without special logic: That is, this works and typechecks without error:

```
Code`4 + __splice__(4)`
```

However, we want to do a couple of things here. We want to enforce that one can only splice in Expression Trees. We also want to extract the inferred type out of the Expression Tree. So in the following example:

```
$x = Code`4`;
Code`4 + __splice__($x)`
```

We want to enforce that `$x` is an Expression Tree. We also want to infer that `__splice__($x)` has the int type.

We can accomplish this by:

Making the declaration of ExprTree the following:

```
final class ExprTree<TVisitor, TResult, TInfer>{
  public function __construct(
    private (function(TVisitor): TResult) $x,
    private (function(): TInfer) $err,
  ) {}
}
```

Desugar an Expression Tree into

```
() ==> {
  // Spliced Expression Assignments
  return new ExprTree(
    (... $v) ==> { ... // Desugared tree }
    () ==> { // Original expression }
  );
}
```

Since the original expression does not need to be run or compiled in codegen path, we can replace that with a lambda that simply throws an Exception. In the typechecker path, we will then infer the correct types.

This diff implements the desugaring as well as the enforcement that spliced expressions are ExprTrees and extracts the inferred type TInfer. It does not implement the enforcement that one can only splice in Expression Trees with the same visitor yet.

Reviewed By: Wilfred

Differential Revision: D24281195

fbshipit-source-id: 3d5aa3e1cf1f97f2d8d28bce1ebfb00ad423f0c2
78 files changed:
hphp/hack/src/decl/decl_pos_utils.ml
hphp/hack/src/naming/naming_special_names.ml
hphp/hack/src/oxidized_by_ref/decl_visitor/node_impl_gen.rs
hphp/hack/src/oxidized_by_ref/gen/typing_reason.rs
hphp/hack/src/oxidized_by_ref/manual/typing_reason_impl.rs
hphp/hack/src/parser/lowerer/desugar_expression_tree.rs
hphp/hack/src/parser/lowerer/lowerer.rs
hphp/hack/src/typing/typing.ml
hphp/hack/src/typing/typing_make_type.ml
hphp/hack/src/typing/typing_reason.ml
hphp/hack/src/typing/typing_reason.mli
hphp/hack/test/nast/expression_tree.php.exp
hphp/hack/test/nast/expression_tree_assign.php.exp
hphp/hack/test/nast/expression_tree_loop.php.exp
hphp/hack/test/nast/expression_tree_splice.php.exp
hphp/hack/test/typecheck/expression_trees/add.php
hphp/hack/test/typecheck/expression_trees/assign.php
hphp/hack/test/typecheck/expression_trees/bound_variable_lambda.php
hphp/hack/test/typecheck/expression_trees/break.php
hphp/hack/test/typecheck/expression_trees/call.php
hphp/hack/test/typecheck/expression_trees/consecutive_splicing.php
hphp/hack/test/typecheck/expression_trees/continue.php
hphp/hack/test/typecheck/expression_trees/hover_type.php
hphp/hack/test/typecheck/expression_trees/hover_type.php.exp
hphp/hack/test/typecheck/expression_trees/if.php
hphp/hack/test/typecheck/expression_trees/invalid_operator.php
hphp/hack/test/typecheck/expression_trees/invalid_operator.php.exp
hphp/hack/test/typecheck/expression_trees/lambda.php
hphp/hack/test/typecheck/expression_trees/loop.php
hphp/hack/test/typecheck/expression_trees/mismatched_types.php
hphp/hack/test/typecheck/expression_trees/mismatched_types.php.exp
hphp/hack/test/typecheck/expression_trees/nested_expression_trees.php
hphp/hack/test/typecheck/expression_trees/nested_expression_trees.php.exp
hphp/hack/test/typecheck/expression_trees/nested_splicing.php
hphp/hack/test/typecheck/expression_trees/nested_splicing.php.exp
hphp/hack/test/typecheck/expression_trees/nested_splicing2.php
hphp/hack/test/typecheck/expression_trees/nested_splicing2.php.exp
hphp/hack/test/typecheck/expression_trees/null.php
hphp/hack/test/typecheck/expression_trees/parse_constants.php
hphp/hack/test/typecheck/expression_trees/parse_constants.php.exp
hphp/hack/test/typecheck/expression_trees/splice.php
hphp/hack/test/typecheck/expression_trees/splice2.php
hphp/hack/test/typecheck/expression_trees/splice2.php.like_types.exp [new file with mode: 0644]
hphp/hack/test/typecheck/expression_trees/splice_err1.php [copied from hphp/hack/test/typecheck/expression_trees/add.php with 85% similarity]
hphp/hack/test/typecheck/expression_trees/splice_err1.php.exp [new file with mode: 0644]
hphp/hack/test/typecheck/expression_trees/splice_err2.php [copied from hphp/hack/test/typecheck/expression_trees/add.php with 84% similarity]
hphp/hack/test/typecheck/expression_trees/splice_err2.php.exp [new file with mode: 0644]
hphp/hack/test/typecheck/expression_trees/splice_err3.php [copied from hphp/hack/test/typecheck/expression_trees/add.php with 80% similarity]
hphp/hack/test/typecheck/expression_trees/splice_err3.php.exp [new file with mode: 0644]
hphp/hack/test/typecheck/expression_trees/splice_err4.php [copied from hphp/hack/test/typecheck/expression_trees/add.php with 81% similarity]
hphp/hack/test/typecheck/expression_trees/splice_err4.php.exp [new file with mode: 0644]
hphp/hack/test/typecheck/expression_trees/splice_infer.php [copied from hphp/hack/test/typecheck/expression_trees/add.php with 83% similarity]
hphp/hack/test/typecheck/expression_trees/splice_infer.php.exp [new file with mode: 0644]
hphp/hack/test/typecheck/expression_trees/splice_state.php
hphp/hack/test/typecheck/expression_trees/splice_state.php.exp [copied from hphp/hack/test/typecheck/expression_trees/splice_state4.php.exp with 55% similarity]
hphp/hack/test/typecheck/expression_trees/splice_state.php.like_types.exp [new file with mode: 0644]
hphp/hack/test/typecheck/expression_trees/splice_state2.php
hphp/hack/test/typecheck/expression_trees/splice_state2.php.exp
hphp/hack/test/typecheck/expression_trees/splice_state2.php.like_types.exp [new file with mode: 0644]
hphp/hack/test/typecheck/expression_trees/splice_state3.php
hphp/hack/test/typecheck/expression_trees/splice_state3.php.exp
hphp/hack/test/typecheck/expression_trees/splice_state3.php.like_types.exp [new file with mode: 0644]
hphp/hack/test/typecheck/expression_trees/splice_state4.php
hphp/hack/test/typecheck/expression_trees/splice_state4.php.exp
hphp/hack/test/typecheck/expression_trees/splice_state4.php.like_types.exp [new file with mode: 0644]
hphp/hack/test/typecheck/expression_trees/splice_variable.php
hphp/hack/test/typecheck/expression_trees/splice_variable.php.like_types.exp [new file with mode: 0644]
hphp/hack/test/typecheck/expression_trees/splice_variable2.php
hphp/hack/test/typecheck/expression_trees/splice_variable3.php
hphp/hack/test/typecheck/expression_trees/splice_variable3.php.like_types.exp [new file with mode: 0644]
hphp/hack/test/typecheck/expression_trees/splice_variable4.php
hphp/hack/test/typecheck/expression_trees/splice_variable4.php.exp
hphp/hack/test/typecheck/expression_trees/splice_variable4.php.like_types.exp [new file with mode: 0644]
hphp/hack/test/typecheck/expression_trees/splice_variable_state.php
hphp/hack/test/typecheck/expression_trees/splice_variable_state.php.like_types.exp [new file with mode: 0644]
hphp/hack/test/typecheck/expression_trees/unbound_variables.php
hphp/hack/test/typecheck/expression_trees/unbound_variables.php.exp
hphp/test/slow/expression_trees/basic.php