diff --git a/src/Type/ArrayType.php b/src/Type/ArrayType.php index 288caefdc63..57547091306 100644 --- a/src/Type/ArrayType.php +++ b/src/Type/ArrayType.php @@ -268,6 +268,7 @@ public function looseCompare(Type $type, PhpVersion $phpVersion): BooleanType public function hasOffsetValueType(Type $offsetType): TrinaryLogic { + $originalOffsetType = $offsetType; $offsetArrayKeyType = $offsetType->toArrayKey(); if ($offsetArrayKeyType instanceof ErrorType) { $allowedArrayKeys = AllowedArrayKeysTypes::getType(); @@ -279,6 +280,7 @@ public function hasOffsetValueType(Type $offsetType): TrinaryLogic $offsetType = $offsetArrayKeyType; if ($this->getKeyType()->isSuperTypeOf($offsetType)->no() + && $this->getKeyType()->isSuperTypeOf($originalOffsetType)->no() && ($offsetType->isString()->no() || !$offsetType->isConstantScalarValue()->no()) ) { return TrinaryLogic::createNo(); @@ -289,8 +291,10 @@ public function hasOffsetValueType(Type $offsetType): TrinaryLogic public function getOffsetValueType(Type $offsetType): Type { + $originalOffsetType = $offsetType; $offsetType = $offsetType->toArrayKey(); if ($this->getKeyType()->isSuperTypeOf($offsetType)->no() + && $this->getKeyType()->isSuperTypeOf($originalOffsetType)->no() && ($offsetType->isString()->no() || !$offsetType->isConstantScalarValue()->no()) ) { return new ErrorType(); diff --git a/tests/PHPStan/Rules/Arrays/NonexistentOffsetInArrayDimFetchRuleTest.php b/tests/PHPStan/Rules/Arrays/NonexistentOffsetInArrayDimFetchRuleTest.php index c066553f27e..91d3d7ef025 100644 --- a/tests/PHPStan/Rules/Arrays/NonexistentOffsetInArrayDimFetchRuleTest.php +++ b/tests/PHPStan/Rules/Arrays/NonexistentOffsetInArrayDimFetchRuleTest.php @@ -63,10 +63,6 @@ public function testRule(): void 'Offset 0 does not exist on array.', 111, ], - [ - 'Offset \'0\' does not exist on array.', - 112, - ], [ 'Offset int does not exist on array.', 114, diff --git a/tests/PHPStan/Rules/Variables/IssetRuleTest.php b/tests/PHPStan/Rules/Variables/IssetRuleTest.php index 045af8b58b6..85dc1926672 100644 --- a/tests/PHPStan/Rules/Variables/IssetRuleTest.php +++ b/tests/PHPStan/Rules/Variables/IssetRuleTest.php @@ -513,4 +513,11 @@ public function testBug9503(): void $this->analyse([__DIR__ . '/data/bug-9503.php'], []); } + public function testBug4296(): void + { + $this->treatPhpDocTypesAsCertain = true; + + $this->analyse([__DIR__ . '/data/bug-4296.php'], []); + } + } diff --git a/tests/PHPStan/Rules/Variables/data/bug-4296.php b/tests/PHPStan/Rules/Variables/data/bug-4296.php new file mode 100644 index 00000000000..109db786128 --- /dev/null +++ b/tests/PHPStan/Rules/Variables/data/bug-4296.php @@ -0,0 +1,28 @@ +id = $id; + } + + public function getId(): string + { + return $this->id; + } +} + +$map = []; +foreach ([new Test('1234')] as $test) { + $map[$test->getId()] = $test; +} + +foreach (['1234'] as $value) { + if (isset($map[$value])) { + $found = 1; + } +}