diff --git a/src/Analyser/NodeScopeResolver.php b/src/Analyser/NodeScopeResolver.php index de96aed5e9..c56e2198c4 100644 --- a/src/Analyser/NodeScopeResolver.php +++ b/src/Analyser/NodeScopeResolver.php @@ -546,6 +546,7 @@ private function processStmtNode( $scope->getClassReflection()->isReadOnly(), false, ), $methodScope); + $methodScope = $methodScope->assignExpression(new PropertyInitializationExpr($param->var->name), new MixedType(), new MixedType()); } } diff --git a/src/Node/ClassPropertiesNode.php b/src/Node/ClassPropertiesNode.php index 194fd87959..fe9eaf3eb4 100644 --- a/src/Node/ClassPropertiesNode.php +++ b/src/Node/ClassPropertiesNode.php @@ -99,6 +99,7 @@ public function getUninitializedProperties( $classReflection = $scope->getClassReflection(); $properties = []; + $originalProperties = []; foreach ($this->getProperties() as $property) { if ($property->isStatic()) { continue; @@ -109,6 +110,7 @@ public function getUninitializedProperties( if ($property->getDefault() !== null) { continue; } + $originalProperties[$property->getName()] = $property; if ($property->isPromoted()) { continue; } @@ -139,7 +141,6 @@ public function getUninitializedProperties( $methodsCalledFromConstructor = $this->getMethodsCalledFromConstructor($classReflection, $this->methodCalls, $constructors); $prematureAccess = []; $additionalAssigns = []; - $originalProperties = $properties; foreach ($this->getPropertyUsages() as $usage) { $fetch = $usage->getFetch(); diff --git a/tests/PHPStan/Rules/Properties/MissingReadOnlyPropertyAssignRuleTest.php b/tests/PHPStan/Rules/Properties/MissingReadOnlyPropertyAssignRuleTest.php index b9e155d837..86273863ad 100644 --- a/tests/PHPStan/Rules/Properties/MissingReadOnlyPropertyAssignRuleTest.php +++ b/tests/PHPStan/Rules/Properties/MissingReadOnlyPropertyAssignRuleTest.php @@ -108,6 +108,10 @@ public function testRule(): void 'Readonly property MissingReadOnlyPropertyAssign\FooTraitClass::$doubleAssigned is already assigned.', 149, ], + [ + 'Readonly property MissingReadOnlyPropertyAssign\AdditionalAssignOfReadonlyPromotedProperty::$x is already assigned.', + 188, + ], ]); } diff --git a/tests/PHPStan/Rules/Properties/data/missing-readonly-property-assign.php b/tests/PHPStan/Rules/Properties/data/missing-readonly-property-assign.php index bb474ae9bc..742d46cd05 100644 --- a/tests/PHPStan/Rules/Properties/data/missing-readonly-property-assign.php +++ b/tests/PHPStan/Rules/Properties/data/missing-readonly-property-assign.php @@ -179,3 +179,13 @@ class BarClass use BarTrait; } + +class AdditionalAssignOfReadonlyPromotedProperty +{ + + public function __construct(private readonly int $x) + { + $this->x = 2; + } + +}