facebook / facebook/hhvm

[ hh_client --lint ] False positive for 5607, equality checks a generic value to a typed value is not always false

Open
#8,940 1 comment 0 reactions 0 assignees View on GitHub
Dominant language
C++
Stars
18.7k
Forks
3.1k
Avg merge
1h 47m
Merged PRs (30d)
2

Description

**Describe the bug**
Given the expression `$expression_resolving_to_generic_type === $expression_resolving_to_a_known_type`, lint rule 5607 should not emit an error if the generic type has any overlap with the known type.

**Standalone code, or other way to reproduce the problem**

```HACK
function is_life(T $t): (bool, T) {
return tuple($t === 42, $t);
}
```

Steps to reproduce the behavior:
1. `hh_client --lint file.hack`

**Expected behavior**

No linter errors! Because `T` does not have a constraint that says it can not be an int, therefore it can be an int. `$t === 42` is not always false.

**Actual behavior**

```
Lint[5607] Invalid comparison: This expression will always return false.
A value of type T can never be equal to a value of type int [1]

file.hack:2:16
1 | function is_life(T $t): (bool, T) {
[1] 2 | return tuple($t === 42, $t);
3 | }
```

**Environment**
- Operating system
> Ubuntu 20.04.
- Installation method
> apt-get with dl.hhvm.com repository
- HHVM Version
> Please include the output of `hhvm --version` and `hh_client --version`
```
HipHop VM 4.137.0 (rel) (non-lowptr)
Compiler: 1637698090_520463089
Repo schema: d90319777b5acb5402a80af5652b95f8dcdd4048
hackc-261ee251a4f119d21a986be5fb0c88d2e404b515-4.137.0
```

**Additional context**
This version compares `?T` to `?int`, which is also a false positive.
```
Lint[5607] Invalid comparison: This expression will always return false.
A value of type ?T can never be equal to a value of type ?int [1]

file.hack:3:16
1 | function is_life(bool $unknown_to_typechecker, ?T $t): (bool, ?T) {
2 | $maybe_null = $unknown_to_typechecker ? null : 42;
[1] 3 | return tuple($t === $maybe_null, $t);
4 | }
```

But this false positive goes away for always-null checks.
```
function is_life(bool $unknown_to_typechecker, ?T $t): (bool, ?T) {
$maybe_null = $unknown_to_typechecker ? null : null;
return tuple($t === $maybe_null, $t);
}
```

```
No lint errors!
```

Contributor guide

Open the contributing guide

Research direction

Start with the standalone Hack examples and run `hh_client --lint file.hack` to reproduce lint 5607 for `T` versus `int`, and for `?T` versus `?int`. Trace the generic-type comparison behavior in the typechecker; done means both overlap cases produce no lint error while the always-null example remains unchanged.

Written by the indexing model from the issue text.

Assessment

Domain
compilers
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
35/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.