Skip to content

Commit 0345d3c

Browse files
committed
Properties with native types can be used in isset() in case they are uninitialized
1 parent 06b6dbf commit 0345d3c

File tree

3 files changed

+51
-0
lines changed

3 files changed

+51
-0
lines changed

src/Rules/IssetCheck.php

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
use PHPStan\Analyser\Scope;
88
use PHPStan\Rules\Properties\PropertyDescriptor;
99
use PHPStan\Rules\Properties\PropertyReflectionFinder;
10+
use PHPStan\Type\MixedType;
1011
use PHPStan\Type\NullType;
1112
use PHPStan\Type\Type;
1213
use PHPStan\Type\VerbosityLevel;
@@ -93,6 +94,13 @@ public function check(Expr $expr, Scope $scope, string $operatorDescription, ?Ru
9394
return null;
9495
}
9596

97+
$nativeType = $propertyReflection->getNativeType();
98+
if (!$nativeType instanceof MixedType) {
99+
if (!$scope->isSpecified($expr)) {
100+
return null;
101+
}
102+
}
103+
96104
$propertyDescription = $this->propertyDescriptor->describeProperty($propertyReflection, $expr);
97105
$propertyType = $propertyReflection->getWritableType();
98106

tests/PHPStan/Rules/Variables/IssetRuleTest.php

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,4 +81,24 @@ public function testRule(): void
8181
]);
8282
}
8383

84+
public function testNativePropertyTypes(): void
85+
{
86+
if (PHP_VERSION_ID < 70400) {
87+
$this->markTestSkipped('Test requires PHP 7.4.');
88+
}
89+
$this->analyse([__DIR__ . '/data/isset-native-property-types.php'], [
90+
/*[
91+
// no way to achieve this with current PHP Reflection API
92+
// There's ReflectionClass::getDefaultProperties()
93+
// but it cannot differentiate between `public int $foo` and `public int $foo = null`;
94+
'Property IssetNativePropertyTypes\Foo::$hasDefaultValue (int) in isset() is not nullable.',
95+
17,
96+
],*/
97+
[
98+
'Property IssetNativePropertyTypes\Foo::$isAssignedBefore (int) in isset() is not nullable.',
99+
20,
100+
],
101+
]);
102+
}
103+
84104
}
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
<?php
2+
3+
namespace IssetNativePropertyTypes;
4+
5+
class Foo
6+
{
7+
8+
public int $hasDefaultValue = 0;
9+
10+
public int $isAssignedBefore;
11+
12+
public int $canBeUninitialized;
13+
14+
}
15+
16+
function (Foo $foo): void {
17+
echo isset($foo->hasDefaultValue) ? $foo->hasDefaultValue : null;
18+
19+
$foo->isAssignedBefore = 5;
20+
echo isset($foo->isAssignedBefore) ? $foo->isAssignedBefore : null;
21+
22+
echo isset($foo->canBeUninitialized) ? $foo->canBeUninitialized : null;
23+
};

0 commit comments

Comments
 (0)