diff --git a/src/Rules/Properties/ReadOnlyPropertyAssignRule.php b/src/Rules/Properties/ReadOnlyPropertyAssignRule.php index 585e8fbd0d..e63953bc1d 100644 --- a/src/Rules/Properties/ReadOnlyPropertyAssignRule.php +++ b/src/Rules/Properties/ReadOnlyPropertyAssignRule.php @@ -67,7 +67,7 @@ public function processNode(Node $node, Scope $scope): array throw new ShouldNotHappenException(); } - if (strtolower($scopeMethod->getName()) === '__construct') { + if (strtolower($scopeMethod->getName()) === '__construct' || strtolower($scopeMethod->getName()) === '__unserialize') { if (!$scope->getType($propertyFetch->var) instanceof ThisType) { $errors[] = RuleErrorBuilder::message(sprintf('Readonly property %s::$%s is not assigned on $this.', $declaringClass->getDisplayName(), $propertyReflection->getName()))->build(); } diff --git a/tests/PHPStan/Rules/Properties/data/readonly-assign.php b/tests/PHPStan/Rules/Properties/data/readonly-assign.php index fd3c0c22bc..cfead51c27 100644 --- a/tests/PHPStan/Rules/Properties/data/readonly-assign.php +++ b/tests/PHPStan/Rules/Properties/data/readonly-assign.php @@ -164,3 +164,23 @@ public function doFoo(Foo $foo, int $i) } } + +class Unserialization +{ + + private readonly int $foo; + + public function __construct(int $foo) + { + $this->foo = $foo; // constructor - fine + } + + /** + * @param array $data + */ + public function __unserialize(array $data) : void + { + [$this->foo] = $data; // __unserialize - fine + } + +}