From 74b397dfe4e441fcccf19b08e1cff3ed2f57af0f Mon Sep 17 00:00:00 2001 From: Vincent Langlet Date: Sat, 4 Oct 2025 16:34:58 +0200 Subject: [PATCH 1/2] Fix oversizeArrayType->isSubTypeOf --- src/Type/IntersectionType.php | 10 +-- tests/PHPStan/Analyser/nsrt/bug-13509.php | 88 +++++++++++++++++++++++ 2 files changed, 94 insertions(+), 4 deletions(-) create mode 100644 tests/PHPStan/Analyser/nsrt/bug-13509.php diff --git a/src/Type/IntersectionType.php b/src/Type/IntersectionType.php index 07f2aca42c..4c6bb98302 100644 --- a/src/Type/IntersectionType.php +++ b/src/Type/IntersectionType.php @@ -247,10 +247,12 @@ public function isSubTypeOf(Type $otherType): IsSuperTypeOfResult } $result = IsSuperTypeOfResult::maxMin(...array_map(static fn (Type $innerType) => $otherType->isSuperTypeOf($innerType), $this->types)); - if ($this->isOversizedArray()->yes()) { - if (!$result->no()) { - return IsSuperTypeOfResult::createYes(); - } + if ( + !$result->no() + && $this->isOversizedArray()->yes() + && !$otherType->isIterableAtLeastOnce()->no() + ) { + return IsSuperTypeOfResult::createYes(); } return $result; diff --git a/tests/PHPStan/Analyser/nsrt/bug-13509.php b/tests/PHPStan/Analyser/nsrt/bug-13509.php new file mode 100644 index 0000000000..6ff710ae4b --- /dev/null +++ b/tests/PHPStan/Analyser/nsrt/bug-13509.php @@ -0,0 +1,88 @@ + */ +function alert(): ?array +{ + $alerts = []; + + if (rand()) { + $alerts[] = [ + 'message' => "Foo", + 'details' => "bar", + 'duration' => rand() ?: null, + 'severity' => 100, + ]; + } + + if (rand()) { + $alerts[] = [ + 'message' => 'Offline', + 'duration' => rand() ?: null, + 'severity' => 99, + ]; + } + + if (rand()) { + $alerts[] = [ + 'message' => 'Running W/O Operator', + 'duration' => rand() ?: null, + 'severity' => 75, + ]; + } + + if (rand()) { + $alerts[] = [ + 'message' => 'No Queue', + 'duration' => rand() ?: null, + 'severity' => 60, + ]; + } + + if (rand()) { + if (rand()) { + $alerts[] = [ + 'message' => 'Not Scheduled', + 'duration' => null, + 'severity' => 25, + ]; + } + + if (rand()) { + $alerts[] = [ + 'message' => 'On Lunch', + 'duration' => rand() ?: null, + 'severity' => 24, + ]; + } + + if (rand()) { + $alerts[] = [ + 'message' => 'On Break', + 'duration' => rand() ?: null, + 'severity' => 24, + ]; + } + } + + if (rand()) { + $alerts[] = [ + 'message' => 'Idle', + 'duration' => rand() ?: null, + 'severity' => 23, + ]; + } + + if ($alerts === []) { + return null; + } + + assertType('non-empty-list&oversized-array>&oversized-array', $alerts); + + usort($alerts, fn ($a, $b) => $b['severity'] <=> $a['severity']); + + return $alerts[0]; +} From 2661d96cbdb3f9713283dd51df6b7ff2df6bdc10 Mon Sep 17 00:00:00 2001 From: Vincent Langlet Date: Sat, 4 Oct 2025 16:42:18 +0200 Subject: [PATCH 2/2] More --- tests/PHPStan/Type/TypeCombinatorTest.php | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/tests/PHPStan/Type/TypeCombinatorTest.php b/tests/PHPStan/Type/TypeCombinatorTest.php index 7cfe7237ab..a7d0c6448f 100644 --- a/tests/PHPStan/Type/TypeCombinatorTest.php +++ b/tests/PHPStan/Type/TypeCombinatorTest.php @@ -5331,6 +5331,12 @@ public static function dataRemove(): array ObjectShapeType::class, 'object{foo?: int}', ], + [ + new IntersectionType([new ArrayType(new StringType(), new StringType()), new OversizedArrayType()]), + new ConstantArrayType([], []), + IntersectionType::class, + 'non-empty-array&oversized-array', + ], ]; }