Generate fresh type parameters away from others in same method body
commitca8fa31e4e79b2b0254e8279303f601a33a037e7
authorAndrew Kennedy <akenn@fb.com>
Mon, 15 Jul 2019 20:20:46 +0000 (15 13:20 -0700)
committerHhvm Bot <hhvm-bot@users.noreply.github.com>
Mon, 15 Jul 2019 20:25:20 +0000 (15 13:25 -0700)
tree510ab3848e78f7fabf2d779dd7177cf0686c68e4
parent79665c9a83fdc3ad03143aed9318c4dd98230ffa
Generate fresh type parameters away from others in same method body

Summary:
When refining to a generic type, we generate "fresh" abstract types with names derived from the generic parameters. For example, `$x is C<_>` for a generic class `class C<Tc> { ... }` would generate a name such as `Tc#1`.

We generate names "away from" existing generic parameters. Unfortunately, they may clash with other names generated in the same body, and end up flowing to a common place. This is unsound. For example:
```
if ($b) {
  invariant($y is C<_>, "C");
} else {
  invariant($y is D<_>, "D");
}
```
This might generate the *same* name for the abstract type parameter in both branches of the conditional, which then leaks out at the join point. See the test in this diff for an example of a program that should be rejected but which is currently accepted.

The fix is easy: maintain in `env` a set of already-generated type parameter names. Fresh names should be generated "away" from these.

Reviewed By: kmeht

Differential Revision: D16200769

fbshipit-source-id: 9a251039d296596b732be01d8ed9052feaf9c5a5
hphp/hack/src/typing/typing_env.ml
hphp/hack/src/typing/typing_env_types.ml
hphp/hack/src/typing/typing_env_types_sig.mli
hphp/hack/src/typing/typing_log.ml
hphp/hack/test/typecheck/instanceof/instanceof_static_with_reqs.php.exp
hphp/hack/test/typecheck/is_expression/merge_is_bad.php [new file with mode: 0644]
hphp/hack/test/typecheck/is_expression/merge_is_bad.php.exp [new file with mode: 0644]