Destructuring of unions of tuples
commit15ec65e24115b54916034d1bff5d3d183d72784b
authorAndrew Kennedy <akenn@fb.com>
Thu, 13 Oct 2016 17:05:56 +0000 (13 10:05 -0700)
committerHhvm Bot <hhvm-bot-bot@fb.com>
Thu, 13 Oct 2016 17:16:01 +0000 (13 10:16 -0700)
treecb84a1cbe99ed71ed7cddc28b603dcb5aaa8b824
parentca168e2bc50d8e1840d9378c6e57a525a6e8d047
Destructuring of unions of tuples

Summary:
Currently we have a type hole associated with union types and tuple destructuring.
For example, Hack accepts the following:
```
function foo(bool $b): int {
  if ($b) {
      $a = tuple(42, 1);
  } else {
      $a = tuple('bar', 2);
  }
  list($x, $y) = $a;
  return $x;
}
```
Just before the `list` assignment, `$a` has type `(int,int) | (string,int)`. So
Hack should infer type `int | string` for `$x` but currently gives it the "any"
type.

The fix is to generate fresh type variables `v1` ... `vn` for the types of the
elements of the tuple, and then force a subtype `ty <: tuple(v1, ..., vn)` where
`ty` is the type of the expression on the right-hand side of the assignment.

This works for ordinary tuples (but changes some error messages slightly) as well
as unions such as in the above example. (By the way, the above example is now
legal if the return type is set to `arraykey`.)

Reviewed By: dlreeves

Differential Revision: D4014944

fbshipit-source-id: 14eed43f989b1db1b78553d649cfe07334b185ba
13 files changed:
hphp/hack/src/typing/typing.ml
hphp/hack/test/typecheck/desugar_tuple2.php.exp
hphp/hack/test/typecheck/list_generic_assign.php [new file with mode: 0644]
hphp/hack/test/typecheck/list_generic_assign.php.exp [new file with mode: 0644]
hphp/hack/test/typecheck/list_union_tuple_assign.php [new file with mode: 0644]
hphp/hack/test/typecheck/list_union_tuple_assign.php.exp [new file with mode: 0644]
hphp/hack/test/typecheck/list_union_tuple_assign_bad.php [new file with mode: 0644]
hphp/hack/test/typecheck/list_union_tuple_assign_bad.php.exp [new file with mode: 0644]
hphp/hack/test/typecheck/tconst/loader_example.php
hphp/hack/test/typecheck/tconst/loader_example.php.exp
hphp/hack/test/typecheck/tconst/lvar_expr_dependent3.php.exp
hphp/hack/test/typecheck/void_usage_placeholder.php
hphp/hack/test/typecheck/void_usage_placeholder.php.exp