diff --git a/src/Type/Php/FilterFunctionReturnTypeHelper.php b/src/Type/Php/FilterFunctionReturnTypeHelper.php index ca242a964e..e0d7f63cdf 100644 --- a/src/Type/Php/FilterFunctionReturnTypeHelper.php +++ b/src/Type/Php/FilterFunctionReturnTypeHelper.php @@ -139,10 +139,11 @@ public function getType(Type $inputType, ?Type $filterType, ?Type $flagsType): T } if ($inputType->isScalar()->no() && $inputType->isNull()->no()) { - return $defaultType; + $exactType = $defaultType; + } else { + $exactType = $this->determineExactType($inputType, $filterValue, $defaultType, $flagsType); } - $exactType = $this->determineExactType($inputType, $filterValue, $defaultType, $flagsType); $type = $exactType ?? $this->getFilterTypeMap()[$filterValue] ?? $mixedType; $type = $this->applyRangeOptions($type, $options, $defaultType); @@ -156,16 +157,19 @@ public function getType(Type $inputType, ?Type $filterType, ?Type $flagsType): T $type = TypeCombinator::intersect($type, $accessory); } - if ($hasRequireArrayFlag) { - $type = new ArrayType($inputArrayKeyType ?? $mixedType, $type); - } - if ($exactType === null || $hasOptions->maybe() || (!$inputType->equals($type) && $inputType->isSuperTypeOf($type)->yes())) { if ($defaultType->isSuperTypeOf($type)->no()) { $type = TypeCombinator::union($type, $defaultType); } } + if ($hasRequireArrayFlag) { + $type = new ArrayType($inputArrayKeyType ?? $mixedType, $type); + if (!$inputIsArray->yes()) { + $type = TypeCombinator::union($type, $defaultType); + } + } + if (!$hasRequireArrayFlag && $hasForceArrayFlag) { return new ArrayType($inputArrayKeyType ?? $mixedType, $type); } diff --git a/tests/PHPStan/Analyser/nsrt/discussion-9134.php b/tests/PHPStan/Analyser/nsrt/discussion-9134.php index 330b51cbaa..c431d86ec6 100644 --- a/tests/PHPStan/Analyser/nsrt/discussion-9134.php +++ b/tests/PHPStan/Analyser/nsrt/discussion-9134.php @@ -6,7 +6,7 @@ $var = $_GET["data"]; $res = filter_var($var, FILTER_VALIDATE_INT, FILTER_REQUIRE_ARRAY); -assertType('array|false', $res); +assertType('array|false', $res); if (is_array($res) === false) { throw new \RuntimeException(); } diff --git a/tests/PHPStan/Analyser/nsrt/filter-var.php b/tests/PHPStan/Analyser/nsrt/filter-var.php index abe5331fc6..d677b0de9c 100644 --- a/tests/PHPStan/Analyser/nsrt/filter-var.php +++ b/tests/PHPStan/Analyser/nsrt/filter-var.php @@ -23,10 +23,10 @@ public function doFoo($mixed, array $stringMixedMap): void assertType('null', filter_var(17, FILTER_VALIDATE_INT, ['flags' => FILTER_REQUIRE_ARRAY|FILTER_NULL_ON_FAILURE])); assertType('false', filter_var('foo', FILTER_VALIDATE_INT, ['flags' => FILTER_REQUIRE_ARRAY])); assertType('null', filter_var('foo', FILTER_VALIDATE_INT, ['flags' => FILTER_REQUIRE_ARRAY|FILTER_NULL_ON_FAILURE])); - assertType('array|false', filter_var($mixed, FILTER_VALIDATE_INT, ['flags' => FILTER_REQUIRE_ARRAY])); - assertType('array|null', filter_var($mixed, FILTER_VALIDATE_INT, ['flags' => FILTER_REQUIRE_ARRAY|FILTER_NULL_ON_FAILURE])); - assertType('array|false', filter_var($stringMixedMap, FILTER_VALIDATE_INT, ['flags' => FILTER_REQUIRE_ARRAY])); - assertType('array|null', filter_var($stringMixedMap, FILTER_VALIDATE_INT, ['flags' => FILTER_REQUIRE_ARRAY|FILTER_NULL_ON_FAILURE])); + assertType('array|false', filter_var($mixed, FILTER_VALIDATE_INT, ['flags' => FILTER_REQUIRE_ARRAY])); + assertType('array|null', filter_var($mixed, FILTER_VALIDATE_INT, ['flags' => FILTER_REQUIRE_ARRAY|FILTER_NULL_ON_FAILURE])); + assertType('array', filter_var($stringMixedMap, FILTER_VALIDATE_INT, ['flags' => FILTER_REQUIRE_ARRAY])); + assertType('array', filter_var($stringMixedMap, FILTER_VALIDATE_INT, ['flags' => FILTER_REQUIRE_ARRAY|FILTER_NULL_ON_FAILURE])); assertType('array<17>', filter_var(17, FILTER_VALIDATE_INT, ['flags' => FILTER_FORCE_ARRAY])); assertType('array<17>', filter_var(17, FILTER_VALIDATE_INT, ['flags' => FILTER_FORCE_ARRAY|FILTER_NULL_ON_FAILURE])); @@ -41,10 +41,10 @@ public function doFoo($mixed, array $stringMixedMap): void assertType('null', filter_var(17, FILTER_VALIDATE_INT, ['flags' => FILTER_REQUIRE_ARRAY|FILTER_FORCE_ARRAY|FILTER_NULL_ON_FAILURE])); assertType('false', filter_var('foo', FILTER_VALIDATE_INT, ['flags' => FILTER_REQUIRE_ARRAY|FILTER_FORCE_ARRAY])); assertType('null', filter_var('foo', FILTER_VALIDATE_INT, ['flags' => FILTER_REQUIRE_ARRAY|FILTER_FORCE_ARRAY|FILTER_NULL_ON_FAILURE])); - assertType('array|false', filter_var($mixed, FILTER_VALIDATE_INT, ['flags' => FILTER_REQUIRE_ARRAY|FILTER_FORCE_ARRAY])); - assertType('array|null', filter_var($mixed, FILTER_VALIDATE_INT, ['flags' => FILTER_REQUIRE_ARRAY|FILTER_FORCE_ARRAY|FILTER_NULL_ON_FAILURE])); - assertType('array|false', filter_var($stringMixedMap, FILTER_VALIDATE_INT, ['flags' => FILTER_REQUIRE_ARRAY|FILTER_FORCE_ARRAY])); - assertType('array|null', filter_var($stringMixedMap, FILTER_VALIDATE_INT, ['flags' => FILTER_REQUIRE_ARRAY|FILTER_FORCE_ARRAY|FILTER_NULL_ON_FAILURE])); + assertType('array|false', filter_var($mixed, FILTER_VALIDATE_INT, ['flags' => FILTER_REQUIRE_ARRAY|FILTER_FORCE_ARRAY])); + assertType('array|null', filter_var($mixed, FILTER_VALIDATE_INT, ['flags' => FILTER_REQUIRE_ARRAY|FILTER_FORCE_ARRAY|FILTER_NULL_ON_FAILURE])); + assertType('array', filter_var($stringMixedMap, FILTER_VALIDATE_INT, ['flags' => FILTER_REQUIRE_ARRAY|FILTER_FORCE_ARRAY])); + assertType('array', filter_var($stringMixedMap, FILTER_VALIDATE_INT, ['flags' => FILTER_REQUIRE_ARRAY|FILTER_FORCE_ARRAY|FILTER_NULL_ON_FAILURE])); assertType('0|int<17, 19>', filter_var($mixed, FILTER_VALIDATE_INT, ['options' => ['default' => 0, 'min_range' => 17, 'max_range' => 19]])); diff --git a/tests/PHPStan/Rules/Functions/CallToFunctionParametersRuleTest.php b/tests/PHPStan/Rules/Functions/CallToFunctionParametersRuleTest.php index c3dc4df606..33eb1e655c 100644 --- a/tests/PHPStan/Rules/Functions/CallToFunctionParametersRuleTest.php +++ b/tests/PHPStan/Rules/Functions/CallToFunctionParametersRuleTest.php @@ -2329,6 +2329,11 @@ public function testBug13434(): void $this->analyse([__DIR__ . '/data/bug-13434.php'], []); } + public function testBug11863(): void + { + $this->analyse([__DIR__ . '/data/bug-11863.php'], []); + } + public function testBug13556(): void { $this->checkExplicitMixed = true; diff --git a/tests/PHPStan/Rules/Functions/data/bug-11863.php b/tests/PHPStan/Rules/Functions/data/bug-11863.php new file mode 100644 index 0000000000..1b86b35fb3 --- /dev/null +++ b/tests/PHPStan/Rules/Functions/data/bug-11863.php @@ -0,0 +1,13 @@ +