diff --git a/src/Rules/FunctionCallParametersCheck.php b/src/Rules/FunctionCallParametersCheck.php index 042ee038a9..abd022d27f 100644 --- a/src/Rules/FunctionCallParametersCheck.php +++ b/src/Rules/FunctionCallParametersCheck.php @@ -5,6 +5,7 @@ use PhpParser\Node\Expr; use PHPStan\Analyser\Scope; use PHPStan\Php\PhpVersion; +use PHPStan\Reflection\ParameterReflection; use PHPStan\Reflection\ParametersAcceptor; use PHPStan\Reflection\ResolvedFunctionVariant; use PHPStan\Type\ErrorType; @@ -409,8 +410,11 @@ private function processArguments( $namedArgumentAlreadyOccurred = true; $parametersCount = count($parameters); + $requiredParametersByName = array_filter($unusedParametersByName, static function (ParameterReflection $parameter): bool { + return !$parameter->isOptional(); + }); if ( - count($unusedParametersByName) !== 0 + count($requiredParametersByName) !== 0 || !$parametersAcceptor->isVariadic() || $parametersCount <= 0 || $isBuiltin diff --git a/tests/PHPStan/Rules/Methods/CallMethodsRuleTest.php b/tests/PHPStan/Rules/Methods/CallMethodsRuleTest.php index 478d885a44..11d62fcc15 100644 --- a/tests/PHPStan/Rules/Methods/CallMethodsRuleTest.php +++ b/tests/PHPStan/Rules/Methods/CallMethodsRuleTest.php @@ -1903,4 +1903,17 @@ public function testBug3546(): void $this->analyse([__DIR__ . '/data/bug-3546.php'], []); } + public function testBug4800(): void + { + if (!self::$useStaticReflectionProvider) { + $this->markTestSkipped('Test requires static reflection.'); + } + + $this->checkThisOnly = false; + $this->checkNullables = true; + $this->checkUnionTypes = true; + $this->phpVersion = 80000; + $this->analyse([__DIR__ . '/data/bug-4800.php'], []); + } + } diff --git a/tests/PHPStan/Rules/Methods/data/bug-4800.php b/tests/PHPStan/Rules/Methods/data/bug-4800.php new file mode 100644 index 0000000000..2604c35cc6 --- /dev/null +++ b/tests/PHPStan/Rules/Methods/data/bug-4800.php @@ -0,0 +1,20 @@ += 8.0 + +namespace Bug4800; + +class HelloWorld +{ + /** + * @param string|int ...$arguments + */ + public function a(string $bar = '', ...$arguments): string + { + return ''; + } + + public function b(): void + { + $this->a(bar: 'baz', foo: 'bar', c: 3); + $this->a(foo: 'bar', c: 3); + } +}