diff --git a/src/PHPStan/PregMatchFlags.php b/src/PHPStan/PregMatchFlags.php index 9cd3598..ace3e8a 100644 --- a/src/PHPStan/PregMatchFlags.php +++ b/src/PHPStan/PregMatchFlags.php @@ -7,13 +7,14 @@ use PHPStan\Type\TypeCombinator; use PHPStan\Type\Type; use PhpParser\Node\Arg; +use PHPStan\Type\Php\RegexArrayShapeMatcher; final class PregMatchFlags { static public function getType(?Arg $flagsArg, Scope $scope): ?Type { if ($flagsArg === null) { - return new ConstantIntegerType(PREG_UNMATCHED_AS_NULL); + return new ConstantIntegerType(PREG_UNMATCHED_AS_NULL | RegexArrayShapeMatcher::PREG_UNMATCHED_AS_NULL_ON_72_73); } $flagsType = $scope->getType($flagsArg->value); @@ -29,7 +30,7 @@ static public function getType(?Arg $flagsArg, Scope $scope): ?Type return null; } - $internalFlagsTypes[] = new ConstantIntegerType($constantScalarValue | PREG_UNMATCHED_AS_NULL); + $internalFlagsTypes[] = new ConstantIntegerType($constantScalarValue | PREG_UNMATCHED_AS_NULL | RegexArrayShapeMatcher::PREG_UNMATCHED_AS_NULL_ON_72_73); } return TypeCombinator::union(...$internalFlagsTypes); } diff --git a/tests/PHPStanTests/nsrt/preg-match.php b/tests/PHPStanTests/nsrt/preg-match.php index 8a4458e..5dd23db 100644 --- a/tests/PHPStanTests/nsrt/preg-match.php +++ b/tests/PHPStanTests/nsrt/preg-match.php @@ -22,20 +22,20 @@ function doMatch(string $s): void } assertType('array{}|array{string, string}', $matches); -// if (Preg::match('/Price: (£|€)?\d+/', $s, $matches)) { // temporarily disabled until https://github.com/phpstan/phpstan-src/pull/3229 is released -// assertType('array{0: string, 1: string|null}', $matches); -// } else { -// assertType('array{}', $matches); -// } -// assertType('array{}|array{0: string, 1: string|null}', $matches); -// -// // passing the PREG_UNMATCHED_AS_NULL should change nothing compared to above as it is always set -// if (Preg::match('/Price: (£|€)?\d+/', $s, $matches, PREG_UNMATCHED_AS_NULL)) { -// assertType('array{0: string, 1: string|null}', $matches); -// } else { -// assertType('array{}', $matches); -// } -// assertType('array{}|array{0: string, 1: string|null}', $matches); + if (Preg::match('/Price: (£|€)?\d+/', $s, $matches)) { + assertType('array{string, string|null}', $matches); + } else { + assertType('array{}', $matches); + } + assertType('array{}|array{string, string|null}', $matches); + + // passing the PREG_UNMATCHED_AS_NULL should change nothing compared to above as it is always set + if (Preg::match('/Price: (£|€)?\d+/', $s, $matches, PREG_UNMATCHED_AS_NULL)) { + assertType('array{string, string|null}', $matches); + } else { + assertType('array{}', $matches); + } + assertType('array{}|array{string, string|null}', $matches); if (Preg::isMatch('/Price: (?£|€)\d+/', $s, $matches)) { assertType('array{0: string, currency: string, 1: string}', $matches);