From 53e25eab8562b7b11277036c2e09a49269aa56ca Mon Sep 17 00:00:00 2001 From: Markus Staab Date: Sun, 7 Sep 2025 10:18:43 +0200 Subject: [PATCH 1/3] Fix lost type when assigning variable in method argument --- src/Rules/FunctionCallParametersCheck.php | 17 ++++++++++------- .../CallToFunctionParametersRuleTest.php | 7 +++++++ .../PHPStan/Rules/Functions/data/bug-12234.php | 18 ++++++++++++++++++ 3 files changed, 35 insertions(+), 7 deletions(-) create mode 100644 tests/PHPStan/Rules/Functions/data/bug-12234.php diff --git a/src/Rules/FunctionCallParametersCheck.php b/src/Rules/FunctionCallParametersCheck.php index 57ae028018..211a34ef80 100644 --- a/src/Rules/FunctionCallParametersCheck.php +++ b/src/Rules/FunctionCallParametersCheck.php @@ -100,6 +100,10 @@ public function check( $functionParametersMaxCount = -1; } + if (!$scope instanceof MutatingScope) { + throw new ShouldNotHappenException(); + } + /** @var array $arguments */ $arguments = []; /** @var array $args */ @@ -114,6 +118,10 @@ public function check( $argumentName = $arg->name->toString(); } + if ($arg->value instanceof Expr\Assign) { + $scope = $scope->assignExpression($arg->value->var, $scope->getType($arg->value->expr), $scope->getNativeType($arg->value->expr)); + } + if ($hasNamedArguments && $arg->unpack) { $errors[] = RuleErrorBuilder::message('Named argument cannot be followed by an unpacked (...) argument.') ->identifier('argument.unpackAfterNamed') @@ -318,14 +326,9 @@ public function check( } if ($argumentValueType === null) { - if ($scope instanceof MutatingScope) { - $scope = $scope->pushInFunctionCall(null, $parameter); - } + $scope = $scope->pushInFunctionCall(null, $parameter); $argumentValueType = $scope->getType($argumentValue); - - if ($scope instanceof MutatingScope) { - $scope = $scope->popInFunctionCall(); - } + $scope = $scope->popInFunctionCall(); } if (!$acceptsNamedArguments->yes()) { diff --git a/tests/PHPStan/Rules/Functions/CallToFunctionParametersRuleTest.php b/tests/PHPStan/Rules/Functions/CallToFunctionParametersRuleTest.php index 9a9cc2f6e5..a7e89bc83d 100644 --- a/tests/PHPStan/Rules/Functions/CallToFunctionParametersRuleTest.php +++ b/tests/PHPStan/Rules/Functions/CallToFunctionParametersRuleTest.php @@ -2317,4 +2317,11 @@ public function testBug12317(): void ]); } + public function testBug12234(): void + { + $this->checkExplicitMixed = true; + $this->checkImplicitMixed = true; + $this->analyse([__DIR__ . '/data/bug-12234.php'], []); + } + } diff --git a/tests/PHPStan/Rules/Functions/data/bug-12234.php b/tests/PHPStan/Rules/Functions/data/bug-12234.php new file mode 100644 index 0000000000..1afa1da92a --- /dev/null +++ b/tests/PHPStan/Rules/Functions/data/bug-12234.php @@ -0,0 +1,18 @@ +getSize(), +); From c235ff7ed9114eee30ec77fe0a8f62f575b9fbac Mon Sep 17 00:00:00 2001 From: Markus Staab Date: Sun, 7 Sep 2025 10:29:13 +0200 Subject: [PATCH 2/3] Added regression test --- .../Rules/Methods/CallMethodsRuleTest.php | 11 +++++++++++ tests/PHPStan/Rules/Methods/data/bug-12735.php | 18 ++++++++++++++++++ 2 files changed, 29 insertions(+) create mode 100644 tests/PHPStan/Rules/Methods/data/bug-12735.php diff --git a/tests/PHPStan/Rules/Methods/CallMethodsRuleTest.php b/tests/PHPStan/Rules/Methods/CallMethodsRuleTest.php index 649a505d5b..20bd91cfc9 100644 --- a/tests/PHPStan/Rules/Methods/CallMethodsRuleTest.php +++ b/tests/PHPStan/Rules/Methods/CallMethodsRuleTest.php @@ -3656,4 +3656,15 @@ public function testBug3396(): void $this->analyse([__DIR__ . '/data/bug-3396.php'], []); } + public function testBug12735(): void + { + $this->checkThisOnly = false; + $this->checkNullables = true; + $this->checkUnionTypes = true; + $this->checkExplicitMixed = true; + $this->checkImplicitMixed = true; + + $this->analyse([__DIR__ . '/data/bug-12735.php'], []); + } + } diff --git a/tests/PHPStan/Rules/Methods/data/bug-12735.php b/tests/PHPStan/Rules/Methods/data/bug-12735.php new file mode 100644 index 0000000000..97ea2d8a58 --- /dev/null +++ b/tests/PHPStan/Rules/Methods/data/bug-12735.php @@ -0,0 +1,18 @@ +foo( + $now = new DateTimeImmutable(), + $now, + ); + + $this->foo($now, $now); + } + + private function foo(DateTimeImmutable $a, DateTimeImmutable $b): void {} +} From 347e8487c8e2be4cea78a57c083c6b2b5709e554 Mon Sep 17 00:00:00 2001 From: Markus Staab Date: Sun, 7 Sep 2025 10:36:32 +0200 Subject: [PATCH 3/3] added failling test --- .../Rules/Methods/CallMethodsRuleTest.php | 11 ++++++++ .../PHPStan/Rules/Methods/data/bug-12735b.php | 25 +++++++++++++++++++ 2 files changed, 36 insertions(+) create mode 100644 tests/PHPStan/Rules/Methods/data/bug-12735b.php diff --git a/tests/PHPStan/Rules/Methods/CallMethodsRuleTest.php b/tests/PHPStan/Rules/Methods/CallMethodsRuleTest.php index 20bd91cfc9..f3ad8d2a84 100644 --- a/tests/PHPStan/Rules/Methods/CallMethodsRuleTest.php +++ b/tests/PHPStan/Rules/Methods/CallMethodsRuleTest.php @@ -3667,4 +3667,15 @@ public function testBug12735(): void $this->analyse([__DIR__ . '/data/bug-12735.php'], []); } + public function testBug12735b(): void + { + $this->checkThisOnly = false; + $this->checkNullables = true; + $this->checkUnionTypes = true; + $this->checkExplicitMixed = true; + $this->checkImplicitMixed = true; + + $this->analyse([__DIR__ . '/data/bug-12735b.php'], []); + } + } diff --git a/tests/PHPStan/Rules/Methods/data/bug-12735b.php b/tests/PHPStan/Rules/Methods/data/bug-12735b.php new file mode 100644 index 0000000000..f7c2f08eb9 --- /dev/null +++ b/tests/PHPStan/Rules/Methods/data/bug-12735b.php @@ -0,0 +1,25 @@ +foo( + $now ??= new DateTimeImmutable(), + $now, + ); + + $this->foo($now, $now); + } + + private function foo(DateTimeImmutable $a, DateTimeImmutable $b): void {} +}