Skip to content

Commit b5a6e6e

Browse files
committed
Adjust self-analysis for the more precise foreach-body narrowing
With the foreach body now narrowing the iterated expression to non-empty even when polluteScopeWithAlwaysIterableForeach is off, PHPStan's own strict-rules self-analysis proves two facts 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. Rename the second loop's variable. - ConstantArrayType::isSuperTypeOf() destructures $this->unsealed / $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 are genuine facts surfaced by the more precise analysis, independent of the flag; no behaviour changes.
1 parent 90d4a7d commit b5a6e6e

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)