Skip to content

Commit 8f7ba26

Browse files
phpstan-botclaude
andcommitted
Remove dim expression coercion, fix HasOffsetValueType key coercion instead
Instead of coercing array key expressions (e.g. String_('2') → Int_(2)) when constructing intertwined ref dim expressions, use the original key expression directly and fix HasOffsetValueType to apply toArrayKey() coercion when matching offset types. This properly handles PHP's array key coercion ('2' → 2) in the type system rather than in expression construction, which works correctly for union types as well. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
1 parent e382c23 commit 8f7ba26

2 files changed

Lines changed: 4 additions & 17 deletions

File tree

src/Analyser/ExprHandler/AssignHandler.php

Lines changed: 2 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -948,9 +948,9 @@ private function processArrayByRefItems(MutatingScope $scope, string $rootVarNam
948948
foreach ($arrayExpr->items as $arrayItem) {
949949
if ($arrayItem->key !== null) {
950950
$keyType = $scope->getType($arrayItem->key)->toArrayKey();
951-
$keyValues = $keyType->getConstantScalarValues();
952951

953952
if ($implicitIndex !== null) {
953+
$keyValues = $keyType->getConstantScalarValues();
954954
if (count($keyValues) === 1) {
955955
$keyValue = $keyValues[0];
956956
if (is_int($keyValue) && $keyValue >= $implicitIndex) {
@@ -963,20 +963,7 @@ private function processArrayByRefItems(MutatingScope $scope, string $rootVarNam
963963
}
964964
}
965965

966-
// Use the coerced key value for the dim expression so that
967-
// e.g. '2' => &$b creates ArrayDimFetch with Int_(2), matching $array[2] access
968-
if (count($keyValues) === 1) {
969-
$coercedKey = $keyValues[0];
970-
if (is_int($coercedKey)) {
971-
$dimExpr = new Node\Scalar\Int_($coercedKey);
972-
} elseif (is_string($coercedKey)) {
973-
$dimExpr = new Node\Scalar\String_($coercedKey);
974-
} else {
975-
$dimExpr = $arrayItem->key;
976-
}
977-
} else {
978-
$dimExpr = $arrayItem->key;
979-
}
966+
$dimExpr = $arrayItem->key;
980967
} elseif ($implicitIndex !== null) {
981968
$dimExpr = new Node\Scalar\Int_($implicitIndex);
982969
$implicitIndex++;

src/Type/Accessory/HasOffsetValueType.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -156,7 +156,7 @@ public function isOffsetAccessLegal(): TrinaryLogic
156156

157157
public function hasOffsetValueType(Type $offsetType): TrinaryLogic
158158
{
159-
if ($offsetType->isConstantScalarValue()->yes() && $offsetType->equals($this->offsetType)) {
159+
if ($offsetType->isConstantScalarValue()->yes() && $offsetType->toArrayKey()->equals($this->offsetType)) {
160160
return TrinaryLogic::createYes();
161161
}
162162

@@ -165,7 +165,7 @@ public function hasOffsetValueType(Type $offsetType): TrinaryLogic
165165

166166
public function getOffsetValueType(Type $offsetType): Type
167167
{
168-
if ($offsetType->isConstantScalarValue()->yes() && $offsetType->equals($this->offsetType)) {
168+
if ($offsetType->isConstantScalarValue()->yes() && $offsetType->toArrayKey()->equals($this->offsetType)) {
169169
return $this->valueType;
170170
}
171171

0 commit comments

Comments
 (0)