Skip to content

Commit 4d055b0

Browse files
authored
RegexArrayShapeMatcher: Fix non-emptiness of leading optional groups
1 parent c4c0269 commit 4d055b0

File tree

2 files changed

+18
-2
lines changed

2 files changed

+18
-2
lines changed

src/Type/Php/RegexArrayShapeMatcher.php

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -286,12 +286,13 @@ private function buildArrayType(
286286
$countGroups = count($captureGroups);
287287
$i = 0;
288288
foreach ($captureGroups as $captureGroup) {
289+
$isTrailingOptional = $i >= $countGroups - $trailingOptionals;
289290
$groupValueType = $this->getValueType($captureGroup->getType(), $flags);
290291

291292
if (!$wasMatched->yes()) {
292293
$optional = true;
293294
} else {
294-
if ($i < $countGroups - $trailingOptionals) {
295+
if (!$isTrailingOptional) {
295296
$optional = false;
296297
if ($this->containsUnmatchedAsNull($flags) && !$captureGroup->isOptional()) {
297298
$groupValueType = TypeCombinator::removeNull($groupValueType);
@@ -303,7 +304,7 @@ private function buildArrayType(
303304
}
304305
}
305306

306-
if (!$optional && $captureGroup->isOptional() && !$this->containsUnmatchedAsNull($flags)) {
307+
if (!$isTrailingOptional && $captureGroup->isOptional() && !$this->containsUnmatchedAsNull($flags)) {
307308
$groupValueType = TypeCombinator::union($groupValueType, new ConstantStringType(''));
308309
}
309310

tests/PHPStan/Analyser/nsrt/preg_match_shapes.php

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -525,3 +525,18 @@ function (string $s): void {
525525
assertType("array{0?: string, 1?: ''|numeric-string}", $matches);
526526
};
527527

528+
class Bug11376
529+
{
530+
public function test(string $str): void
531+
{
532+
preg_match('~^(?:(\w+)::)?(\w+)$~', $str, $matches);
533+
assertType('array{0?: string, 1?: string, 2?: non-empty-string}', $matches);
534+
}
535+
536+
public function test2(string $str): void
537+
{
538+
if (preg_match('~^(?:(\w+)::)?(\w+)$~', $str, $matches) === 1) {
539+
assertType('array{string, string, non-empty-string}', $matches);
540+
}
541+
}
542+
}

0 commit comments

Comments
 (0)