Skip to content

Commit 7b0d777

Browse files
authored
Fix ErrorType after ArrayDimFetch
1 parent 8d87c67 commit 7b0d777

File tree

2 files changed

+30
-4
lines changed

2 files changed

+30
-4
lines changed

src/Type/Constant/ConstantArrayType.php

Lines changed: 18 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -652,23 +652,33 @@ public function hasOffsetValueType(Type $offsetType): TrinaryLogic
652652

653653
public function getOffsetValueType(Type $offsetType): Type
654654
{
655+
if (count($this->keyTypes) === 0) {
656+
return new ErrorType();
657+
}
658+
655659
$offsetType = $offsetType->toArrayKey();
656660
$matchingValueTypes = [];
657661
$all = true;
662+
$maybeAll = true;
658663
foreach ($this->keyTypes as $i => $keyType) {
659664
if ($keyType->isSuperTypeOf($offsetType)->no()) {
660665
$all = false;
666+
667+
if (
668+
$keyType instanceof ConstantIntegerType
669+
&& !$offsetType->isString()->no()
670+
&& $offsetType->isConstantScalarValue()->no()
671+
) {
672+
continue;
673+
}
674+
$maybeAll = false;
661675
continue;
662676
}
663677

664678
$matchingValueTypes[] = $this->valueTypes[$i];
665679
}
666680

667681
if ($all) {
668-
if (count($this->keyTypes) === 0) {
669-
return new ErrorType();
670-
}
671-
672682
return $this->getIterableValueType();
673683
}
674684

@@ -681,6 +691,10 @@ public function getOffsetValueType(Type $offsetType): Type
681691
return $type;
682692
}
683693

694+
if ($maybeAll) {
695+
return $this->getIterableValueType();
696+
}
697+
684698
return new ErrorType(); // undefined offset
685699
}
686700

tests/PHPStan/Rules/Variables/data/bug-10577.php

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,10 +20,22 @@ public function validate(string $value): void
2020
throw new \RuntimeException();
2121
}
2222

23+
assertType("non-empty-string", $value);
24+
assertType("'Test1'|'Test2'", self::MAP[$value]);
25+
2326
$value = self::MAP[$value] ?? $value;
2427

28+
assertType("non-empty-string", $value);
2529
assertType("'Test1'|'Test2'", self::MAP[$value]);
2630

2731
// ...
2832
}
33+
34+
public function validateNumericString(string $value): void
35+
{
36+
if (!is_numeric($value)) return;
37+
38+
assertType("numeric-string", $value);
39+
assertType("'Test1'|'Test2'", self::MAP[$value]);
40+
}
2941
}

0 commit comments

Comments
 (0)