diff --git a/src/Type/ArrayType.php b/src/Type/ArrayType.php index 288caefdc6..5754709130 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 c066553f27..91d3d7ef02 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 045af8b58b..85dc192667 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 0000000000..dd81534e3a --- /dev/null +++ b/tests/PHPStan/Rules/Variables/data/bug-4296.php @@ -0,0 +1,30 @@ +id = $id; + } + + public function getId(): string + { + return $this->id; + } +} + +function (): void { + $map = []; + foreach ([new Test('1234')] as $test) { + $map[$test->getId()] = $test; + } + + foreach (['1234'] as $value) { + if (isset($map[$value])) { + $found = 1; + } + } +};