Add hh_expect and hh_expect_equivalent pseudo function for testing
Summary:
Calling `hh_expect<t>(e)` checks that the type of `e` is a sub-type of `t`. This is intended for use in tests of the type checker. It is a more streamlined version of defining function `function expect_int(int $i) : void` or having to define a more generic `function expect<T>(T $x) : void`.
Calling `hh_expect_equivalent<t>(e)` checks that the type of `e` is both a sub-type and super-type of `t`, i.e., that they are equivalent up-to subtyping. This is intended for use in tests of the type checker where you need to check that the type is exactly something. It is more self-contained than using `hh_show` and checking that the printed output is the desired type, and more readable than the equivalent idiom that doesn't rely on special syntax:
```
function expect<T>(T $x):void { }
...
$w = Vector { e };
expect<Vector<C>>($w);
}
```
This will support testing primitive operations, for example `[]` on `vec`. I need to check that `vec<t>[e]` is exactly `t`. It is a type checker bug if it starts returning a subtype of `t` (soundness) or supertype (completeness).
There is some flexibility in the design. Here we are just using sub-typing to make the given type both an upper and lower bound of the expression's type. That means that is the expression has an unsolved type variable in its type, the `hh_expect_equivalent` could succeed because the type variable _can_ be instantiated to satisfy the expected type, not that it _must_ be instantiated that way. For example,
```
$v = Vector {};
hh_expect_equivalent<Vector<int>>($v);
```
Even for fully resolved types, `hh_expect_equivalent` can differ from using `hh_show` to test. For example, if we were testing type union operations, we might want to check for the exact type syntactically, and not up-to-sub-typing equivalence:
```
if (...) {
$x = 1;
} else {
$x = "1";
}
hh_expect_equivalent<arraykey>($x);
```
With the current implementation of `hh_expect_equivalent` this will pass even if internally union failed to simplify the type of `$x` (what we'd like to be testing for), and so `$x : string | int`.
Reviewed By: madgen
Differential Revision:
D32178417
fbshipit-source-id:
b23cc645cf976a4e20d48baabd7164d63e3d6e01