From 787c1e2b46a40ccac9bb254fd45204a310f6ff2f Mon Sep 17 00:00:00 2001 From: Ondrej Mirtes Date: Wed, 13 Mar 2024 12:28:11 +0100 Subject: [PATCH] Make `@param-out` work even if it is the only conditional type in a function signature --- src/Reflection/ParametersAcceptorSelector.php | 8 ++++++++ tests/PHPStan/Analyser/data/bug-10699.php | 19 +++++++++++++++++++ 2 files changed, 27 insertions(+) diff --git a/src/Reflection/ParametersAcceptorSelector.php b/src/Reflection/ParametersAcceptorSelector.php index 054ee15597..c11e767b73 100644 --- a/src/Reflection/ParametersAcceptorSelector.php +++ b/src/Reflection/ParametersAcceptorSelector.php @@ -267,6 +267,14 @@ private static function hasAcceptorTemplateOrLateResolvableType(ParametersAccept } foreach ($acceptor->getParameters() as $parameter) { + if ( + $parameter instanceof ParameterReflectionWithPhpDocs + && $parameter->getOutType() !== null + && self::hasTemplateOrLateResolvableType($parameter->getOutType()) + ) { + return true; + } + if (!self::hasTemplateOrLateResolvableType($parameter->getType())) { continue; } diff --git a/tests/PHPStan/Analyser/data/bug-10699.php b/tests/PHPStan/Analyser/data/bug-10699.php index 1c75b5b13c..de06986e90 100644 --- a/tests/PHPStan/Analyser/data/bug-10699.php +++ b/tests/PHPStan/Analyser/data/bug-10699.php @@ -28,3 +28,22 @@ function (): void { assertType('20', $res); assertType('20', $out); }; + +/** + * @param int $flags + * @param mixed $out + * + * @param-out ($flags is 2 ? 20 : 10) $out + */ +function test2(int $flags, &$out): void +{ + $out = $flags === 2 ? 20 : 10; +} + +function (): void { + test2(1, $out); + assertType('10', $out); + + test2(2, $out); + assertType('20', $out); +};