diff --git a/src/Type/Php/FilterFunctionReturnTypeHelper.php b/src/Type/Php/FilterFunctionReturnTypeHelper.php index 1e920328bd..98834338b5 100644 --- a/src/Type/Php/FilterFunctionReturnTypeHelper.php +++ b/src/Type/Php/FilterFunctionReturnTypeHelper.php @@ -191,7 +191,7 @@ public function getType(Type $inputType, ?Type $filterType, ?Type $flagsType): T } if ($exactType === null || $hasOptions->maybe() || (!$inputType->equals($type) && $inputType->isSuperTypeOf($type)->yes())) { - if ($defaultType->isSuperTypeOf($type)->no()) { + if (!$defaultType->isSuperTypeOf($type)->yes()) { $type = TypeCombinator::union($type, $defaultType); } } @@ -495,11 +495,17 @@ private function hasFlag(string $flagName, ?Type $flagsType): TrinaryLogic } $type = $this->getFlagsValue($flagsType); - if (!$type instanceof ConstantIntegerType) { + $scalarValues = $type->getConstantScalarValues(); + if ($scalarValues === []) { return TrinaryLogic::createMaybe(); } - return TrinaryLogic::createFromBoolean(($type->getValue() & $flag) === $flag); + return TrinaryLogic::lazyExtremeIdentity( + $scalarValues, + static fn (bool|string|int|float|null $scalar): TrinaryLogic => TrinaryLogic::createFromBoolean( + (((int) $scalar) & $flag) === $flag, + ), + ); } private function getFlagsValue(Type $exprType): Type diff --git a/tests/PHPStan/Analyser/nsrt/filter-var.php b/tests/PHPStan/Analyser/nsrt/filter-var.php index 1935c117aa..34d23f9c8f 100644 --- a/tests/PHPStan/Analyser/nsrt/filter-var.php +++ b/tests/PHPStan/Analyser/nsrt/filter-var.php @@ -169,4 +169,15 @@ public function scalars(bool $bool, float $float, int $int, string $string, int assertType("''", filter_var(null)); } + public function randomFlag($mixed, bool $bool) { + + assertType('int|false|null', filter_var($mixed, FILTER_VALIDATE_INT, [ + 'flags' => $bool ? FILTER_NULL_ON_FAILURE : FILTER_FLAG_NONE, + ])); + + assertType('bool|null', filter_var($mixed, FILTER_VALIDATE_BOOLEAN, [ + 'flags' => $bool ? FILTER_NULL_ON_FAILURE : FILTER_FLAG_NONE, + ])); + } + }