Skip to content

Commit 54ac5fd

Browse files
committed
Adjust self-analysis for the more precise foreach-body narrowing
The self-analysis config runs with bleedingEdge on, so the foreach body now narrows the iterated expression even under phpstan-strict-rules. That lets PHPStan prove two facts in its own source that it previously left uncertain: - UnionType::accepts() reuses $i as the value variable of a second foreach after it was the key variable of an earlier one. The reused name now reads as a foreach.valueOverwrite, so rename the second loop's variable. - ConstantArrayType::isSuperTypeOf() destructures $this->unsealed and $type->unsealed (typed array{Type, Type}|null) in branches guarded by a separate unsealedness check that PHPStan cannot connect to the property. Read the property into a local and throw ShouldNotHappenException on null, matching the file's existing impossible-state style. Both changes preserve behaviour.
1 parent a4609bb commit 54ac5fd

2 files changed

Lines changed: 14 additions & 5 deletions

File tree

‎src/Type/Constant/ConstantArrayType.php‎

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -811,7 +811,11 @@ public function isSuperTypeOf(Type $type): IsSuperTypeOfResult
811811
continue;
812812
}
813813

814-
[$thisUnsealedKey, $thisUnsealedValue] = $this->unsealed;
814+
$thisUnsealed = $this->unsealed;
815+
if ($thisUnsealed === null) {
816+
throw new ShouldNotHappenException();
817+
}
818+
[$thisUnsealedKey, $thisUnsealedValue] = $thisUnsealed;
815819
$keyCheck = $thisUnsealedKey->isSuperTypeOf($typeKey);
816820
if ($keyCheck->no()) {
817821
if ($type->isOptionalKey($i)) {
@@ -835,8 +839,13 @@ public function isSuperTypeOf(Type $type): IsSuperTypeOfResult
835839
if ($thisUnsealedness->no()) {
836840
$results[] = IsSuperTypeOfResult::createMaybe();
837841
} else {
838-
[$thisUnsealedKey, $thisUnsealedValue] = $this->unsealed;
839-
[$typeUnsealedKey, $typeUnsealedValue] = $type->unsealed;
842+
$thisUnsealed = $this->unsealed;
843+
$typeUnsealed = $type->unsealed;
844+
if ($thisUnsealed === null || $typeUnsealed === null) {
845+
throw new ShouldNotHappenException();
846+
}
847+
[$thisUnsealedKey, $thisUnsealedValue] = $thisUnsealed;
848+
[$typeUnsealedKey, $typeUnsealedValue] = $typeUnsealed;
840849
$results[] = $thisUnsealedKey->isSuperTypeOf($typeUnsealedKey);
841850
$results[] = $thisUnsealedValue->isSuperTypeOf($typeUnsealedValue);
842851
}

‎src/Type/UnionType.php‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -239,9 +239,9 @@ public function accepts(Type $type, bool $strictTypes): AcceptsResult
239239
}
240240
if ($commonReasons !== null && count($commonReasons) > 0) {
241241
$decorated = [];
242-
foreach (array_keys($innerAccepts) as $i) {
242+
foreach (array_keys($innerAccepts) as $innerAcceptsIndex) {
243243
foreach ($commonReasons as $reason) {
244-
$decorated[] = sprintf('Type #%d from the union: %s', $i + 1, $reason);
244+
$decorated[] = sprintf('Type #%d from the union: %s', $innerAcceptsIndex + 1, $reason);
245245
}
246246
}
247247
$result = new AcceptsResult($result->result, $decorated);

0 commit comments

Comments
 (0)