Deal with final types specially when constructing unions
commit462ce43b4aebb056d5819d5b485081b96bb9536f
authorAndrew Kennedy <akenn@fb.com>
Fri, 6 Aug 2021 19:25:01 +0000 (6 12:25 -0700)
committerFacebook GitHub Bot <facebook-github-bot@users.noreply.github.com>
Fri, 6 Aug 2021 19:26:37 +0000 (6 12:26 -0700)
tree1c94fe32716b6748acf6dc91a62b03b205e1b2b6
parent78e1a0b7e21e866a8c7da1d3ab3ab03f530aa5bd
Deal with final types specially when constructing unions

Summary:
Constructing a union of n types involves potentially O(n^2) subtype operations as elements are union'ed pairwise. A common case that performs badly is
```
vec[C1::class, ... , Cn::class]
```
that produces a type
```
vec<classname<exact C1> | ... | classname<exact Cn>>
```
with n incomparable components, but requires O(n^2) operations in order to discover this!

An easy fix is the following: first split the types into "final" and "non-final" elements, where "final" means "there are no non-empty subtypes". This is the case for final and exact classes, and `classname<C>` where `C` is itself final. Use quadratic simplification on the non-final elements, but for the final elements, compare them against the non-final elements and eliminate any that are subtypes. Overall, this is O(n^2 + mn) where m is the number of final types and n is the number of non-final types.

Differential Revision: D30132822

fbshipit-source-id: 6ab36818ec2a7d73c8f723401480918ad0c12e44
hphp/hack/src/typing/typing_union.ml
hphp/hack/test/tast/initializer.php.exp
hphp/hack/test/typecheck/classname/array_literal_bad.php.exp
hphp/hack/test/unit/server_tests.ml