From 70dd2fca27e90ff70580b0e46b18dadad1f9a5dd Mon Sep 17 00:00:00 2001 From: Richard van Velzen Date: Wed, 1 Jun 2022 07:48:04 +0200 Subject: [PATCH] Improve unresolve template type checks for complex conditional types --- src/Rules/FunctionCallParametersCheck.php | 2 +- .../Analyser/NodeScopeResolverTest.php | 1 + .../Rules/Methods/CallMethodsRuleTest.php | 10 ++++++ .../data/conditional-complex-templates.php | 33 +++++++++++++++++++ 4 files changed, 45 insertions(+), 1 deletion(-) create mode 100644 tests/PHPStan/Rules/Methods/data/conditional-complex-templates.php diff --git a/src/Rules/FunctionCallParametersCheck.php b/src/Rules/FunctionCallParametersCheck.php index bf1c545398..37be0e0d9a 100644 --- a/src/Rules/FunctionCallParametersCheck.php +++ b/src/Rules/FunctionCallParametersCheck.php @@ -355,7 +355,7 @@ public function check( TypeTraverser::map( $parametersAcceptor->getReturnTypeWithUnresolvableTemplateTypes(), static function (Type $type, callable $traverse) use (&$returnTemplateTypes): Type { - if ($type instanceof ConditionalType) { + while ($type instanceof ConditionalType && $type->isResolvable()) { $type = $type->resolve(); } diff --git a/tests/PHPStan/Analyser/NodeScopeResolverTest.php b/tests/PHPStan/Analyser/NodeScopeResolverTest.php index d13712b926..b7f7cc52bc 100644 --- a/tests/PHPStan/Analyser/NodeScopeResolverTest.php +++ b/tests/PHPStan/Analyser/NodeScopeResolverTest.php @@ -902,6 +902,7 @@ public function dataFileAsserts(): iterable yield from $this->gatherAssertTypes(__DIR__ . '/data/bug-7341.php'); yield from $this->gatherAssertTypes(__DIR__ . '/data/non-empty-string-strstr-specifying.php'); yield from $this->gatherAssertTypes(__DIR__ . '/data/non-empty-string-strrchr-specifying.php'); + yield from $this->gatherAssertTypes(__DIR__ . '/../Rules/Methods/data/conditional-complex-templates.php'); } /** diff --git a/tests/PHPStan/Rules/Methods/CallMethodsRuleTest.php b/tests/PHPStan/Rules/Methods/CallMethodsRuleTest.php index 177f403a62..8ba25a23a7 100644 --- a/tests/PHPStan/Rules/Methods/CallMethodsRuleTest.php +++ b/tests/PHPStan/Rules/Methods/CallMethodsRuleTest.php @@ -2469,4 +2469,14 @@ public function testUnresolvableParameter(): void ]); } + + public function testConditionalComplexTemplates(): void + { + $this->checkThisOnly = false; + $this->checkNullables = true; + $this->checkUnionTypes = true; + $this->checkExplicitMixed = false; + $this->analyse([__DIR__ . '/data/conditional-complex-templates.php'], []); + } + } diff --git a/tests/PHPStan/Rules/Methods/data/conditional-complex-templates.php b/tests/PHPStan/Rules/Methods/data/conditional-complex-templates.php new file mode 100644 index 0000000000..1593317e68 --- /dev/null +++ b/tests/PHPStan/Rules/Methods/data/conditional-complex-templates.php @@ -0,0 +1,33 @@ + + */ + public function then(callable $onFulfilled = null, callable $onRejected = null); +} + +/** + * @param PromiseInterface $promise + */ +function test(PromiseInterface $promise): void +{ + $passThroughBoolFn = static fn (bool $bool): bool => $bool; + + assertType('ConditionalComplexTemplates\PromiseInterface', $promise->then($passThroughBoolFn)); + assertType('ConditionalComplexTemplates\PromiseInterface', $promise->then()->then($passThroughBoolFn)); +}