[ hh_client --lint | Lint[5607] ] False negative, comparing an interface to a scalar does not emit a warning #9563
Description
Describe the bug
Comparing a scalar to an interface (other than Stringish
and XHPChild
), should emit a warning Lint[5607] Invalid comparison: This expression will always return false.
.
Standalone code, or other way to reproduce the problem
interface SomeInterface {}
class SomeClass {}
function caught(string $string, SomeClass $class)[]: bool {
return $string === $class;
}
function uncaught(string $string, SomeInterface $interface)[]: bool {
return $string === $interface;
}
Steps to reproduce the behavior:
hh_client --lint filename.hack
Expected behavior
Two lint errors (one in caught, and one in uncaught)
Actual behavior
Lint[5607] Invalid comparison: This expression will always return false.
A value of type string can never be equal to a value of type SomeClass [1]
src/bug.hack:5:12
3 |
4 | function caught(string $string, SomeClass $class)[]: bool {
[1] 5 | return $string === $class;
6 | }
7 |
Environment
- Operating system 'Ubuntu'
- Installation method 'hhvm/hhvm on dockerhub'
- HHVM Version
HipHop VM 4.168.2 (rel) (non-lowptr)
Compiler: 1674167390_239081398
Repo schema: b20d78caba71435cd4028326fcf28ee798279c8e
hackc-af2b2722e8cac3d0bc5fe213eeb16d7296da458f-4.168.2
Additional context
I think there may be a special case for Stringish
and/or XHPChild
that is tripping this linter up.
Stringish === string
is a valid comparison,
since string ""implements"" Stringish
.
Even though interfaces are non-exclusive, string
only implements
XHPChild
and Stringish
, so for the purposes of this check,
implementing SomeInterface
implies not string
.
This issue also reproduces for all scalars (int, bool, float, string),
so int === SomeInterface
should always be false.
The only common interface between a value of SomeInterface
and int
is XHPChild
, which can be eliminated with the same logic that
Stringish
could for the string case above.