Simplify and improve type accesses through intersections and unions
commit0a6eafc12b93686565319acb5e1fef3d0ecc3afe
authorAndrew Kennedy <akenn@fb.com>
Fri, 18 Dec 2020 13:54:26 +0000 (18 05:54 -0800)
committerFacebook GitHub Bot <facebook-github-bot@users.noreply.github.com>
Fri, 18 Dec 2020 13:56:22 +0000 (18 05:56 -0800)
tree213fc043679fa06891059b69c1ca577563419609
parentf7fc6d75dff085687f89a651221dcf3aa22ee0b0
Simplify and improve type accesses through intersections and unions

Summary:
Improve the expressivity of type constant access through intersections. Currently, the following code is rejected:
```
interface IBoundedJ {
  abstract const type TP as J;
  public function get():this::TP;
}
interface IBoundedK {
  abstract const type TP as K;
}
function test3<T as (IBoundedJ & IBoundedK)>(T $x):(J & K) {
  return $x->get();
}
```
It's safe to accept, if we merge the bounds on `TP` when projecting from `(IBoundedJ & IBoundedK)`.

Although this example uses the experimental intersection type syntax, the same effect will happen for multiple bounds on generics, and type refinements.

We also tighten up the code a bit, rejecting all kinds of projections through unions, unless accessing non-abstract type constants.

Reviewed By: vsiles

Differential Revision: D25615483

fbshipit-source-id: e3540807529a6ba22cc90763bef53c554a40af7e
hphp/hack/src/typing/typing_taccess.ml
hphp/hack/test/typecheck/denotable_unions/tconst_union_intersection.php