Skip to content

Commit edd54db

Browse files
committed
Fix false positive about offset that's ensured with array_key_exists
1 parent b19af48 commit edd54db

File tree

3 files changed

+60
-2
lines changed

3 files changed

+60
-2
lines changed

src/Analyser/MutatingScope.php

Lines changed: 29 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4571,8 +4571,35 @@ public function addTypeToExpression(Expr $expr, Type $type): self
45714571
if ($originalExprType->equals($nativeType)) {
45724572
$newType = TypeCombinator::intersect($type, $originalExprType);
45734573
if ($newType->isConstantScalarValue()->yes() && $newType->equals($originalExprType)) {
4574-
// don't add the same type over and over again to improve performance
4575-
return $this;
4574+
$exprString = $this->getNodeKey($expr);
4575+
if (array_key_exists($exprString, $this->expressionTypes)) {
4576+
// don't add the same type over and over again to improve performance
4577+
return $this;
4578+
}
4579+
4580+
$expressionTypes = $this->expressionTypes;
4581+
$expressionTypes[$exprString] = new ExpressionTypeHolder($expr, $type, TrinaryLogic::createYes());
4582+
$nativeTypes = $this->nativeExpressionTypes;
4583+
$nativeTypes[$exprString] = new ExpressionTypeHolder($expr, $nativeType, TrinaryLogic::createYes());
4584+
4585+
return $this->scopeFactory->create(
4586+
$this->context,
4587+
$this->isDeclareStrictTypes(),
4588+
$this->getFunction(),
4589+
$this->getNamespace(),
4590+
$expressionTypes,
4591+
$nativeTypes,
4592+
$this->conditionalExpressions,
4593+
$this->inClosureBindScopeClasses,
4594+
$this->anonymousFunctionReflection,
4595+
$this->inFirstLevelStatement,
4596+
$this->currentlyAssignedExpressions,
4597+
$this->currentlyAllowedUndefinedExpressions,
4598+
$this->inFunctionCallsStack,
4599+
$this->afterExtractCall,
4600+
$this->parentScope,
4601+
$this->nativeTypesPromoted,
4602+
);
45764603
}
45774604
return $this->specifyExpressionType($expr, $newType, $newType, TrinaryLogic::createYes());
45784605
}

tests/PHPStan/Rules/Arrays/NonexistentOffsetInArrayDimFetchRuleTest.php

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1000,4 +1000,9 @@ public function testBug10492(): void
10001000
]);
10011001
}
10021002

1003+
public function testBug13526(): void
1004+
{
1005+
$this->analyse([__DIR__ . '/data/bug-13526.php'], []);
1006+
}
1007+
10031008
}
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
<?php
2+
3+
namespace Bug13526;
4+
5+
class Foo
6+
{
7+
public function foo(string $item, bool $a): ?int
8+
{
9+
$map1 = [
10+
'MAP_1_ITEM_1' => 1,
11+
'MAP_1_ITEM_2' => 2,
12+
];
13+
$map2 = [
14+
'MAP_2_ITEM_1' => 1,
15+
'MAP_2_ITEM_2' => 2,
16+
];
17+
18+
$map = $a ? $map1 : $map2;
19+
20+
if (array_key_exists($item, $map)) {
21+
return $map[$item];
22+
}
23+
24+
return null;
25+
}
26+
}

0 commit comments

Comments
 (0)