hhvm
hhvm copied to clipboard
Falsy checks for empty vecs break type checker soundness
Describe the bug
An empty vec[]
does not pass a truthy check but it still a vec. The typechecker incorrectly infers that values in the other branch of this check are not vecs.
Standalone code, or other way to reproduce the problem
The following code typechecks but results in a fatal error at runtime under hhvm 4.108
empty_falsey.hack
use namespace HH\Lib\C;
<<__EntryPoint>>
function example(): void {
takes_vec(vec[""]); // works for non-empty vec
takes_vec(vec[]); // runtime exception for empty vec
}
function takes_vec(?vec<string> $v): void {
// This truthy check does not pass for an empty vec, but the typechecker doesn't
// track the fact that empty vec miss this branch and are not converted to vecs
//
// If you replace the if ($v) with the next line, the typechecker can see the problem
// if ($v is nonnull && !C\is_empty($v)) {
if ($v) {
$v = 5;
}
// $v is inferred to be ?int but is `?(int | vec<string>)`
takes_int($v);
}
function takes_int(?int $i): void {}
$ hh_client
No errors!
$ hhvm empty_falsey.hack
Fatal error: Uncaught TypeError: Argument 1 to takes_int() must be of type ?int, HH\vec given in /Users/greenberg/code/hhvm_repro/empty_falsey.hack:23
Stack trace:
#0 /Users/greenberg/code/hhvm_repro/empty_falsey.hack(20): takes_int()
#1 /Users/greenberg/code/hhvm_repro/empty_falsey.hack(6): takes_vec()
#2 (): example()
#3 {main}
Expected behavior
Typechecker error on line 20 (takes_int($v);
) saying "Expected ?int, got vec
Actual behavior
(no error)
Environment
- Operating system: MacOS Big Sur 11.2.3
- Installation method:
brew install hhvm/hhvm/hhvm-4.108
$ hhvm --version
HipHop VM 4.108.0 (rel)
Compiler: 1620152370_N
Repo schema: 09d2af8dd22201dd8d48e5dcfcaed281ff9422c7
$ hh_client --version
hackc-893a8c56ba3cbd052c6cff6e404215635966a29b-4.108.0
Thanks - also repros on our internal builds which is helpful. Filed FB T91160732 for this