Skip to content

Commit

Permalink
Fix: Return of parent::__set_state() method is only object
Browse files Browse the repository at this point in the history
  • Loading branch information
blankse committed Dec 21, 2022
1 parent 7c68a12 commit 630430f
Show file tree
Hide file tree
Showing 3 changed files with 55 additions and 21 deletions.
45 changes: 24 additions & 21 deletions src/Reflection/Php/PhpMethodReflection.php
Expand Up @@ -314,30 +314,33 @@ private function getReturnType(): Type
{
if ($this->returnType === null) {
$name = strtolower($this->getName());
if (
$name === '__construct'
|| $name === '__destruct'
|| $name === '__unset'
|| $name === '__wakeup'
|| $name === '__clone'
) {
return $this->returnType = TypehintHelper::decideType(new VoidType(), $this->phpDocReturnType);
}
if ($name === '__tostring') {
return $this->returnType = TypehintHelper::decideType(new StringType(), $this->phpDocReturnType);
}
if ($name === '__isset') {
return $this->returnType = TypehintHelper::decideType(new BooleanType(), $this->phpDocReturnType);
}
if ($name === '__sleep') {
return $this->returnType = TypehintHelper::decideType(new ArrayType(new IntegerType(), new StringType()), $this->phpDocReturnType);
}
if ($name === '__set_state') {
return $this->returnType = TypehintHelper::decideType(new ObjectWithoutClassType(), $this->phpDocReturnType);
$returnType = $this->reflection->getReturnType();
if ($returnType === null) {
if (
$name === '__construct'
|| $name === '__destruct'
|| $name === '__unset'
|| $name === '__wakeup'
|| $name === '__clone'
) {
return $this->returnType = TypehintHelper::decideType(new VoidType(), $this->phpDocReturnType);
}
if ($name === '__tostring') {
return $this->returnType = TypehintHelper::decideType(new StringType(), $this->phpDocReturnType);
}
if ($name === '__isset') {
return $this->returnType = TypehintHelper::decideType(new BooleanType(), $this->phpDocReturnType);
}
if ($name === '__sleep') {
return $this->returnType = TypehintHelper::decideType(new ArrayType(new IntegerType(), new StringType()), $this->phpDocReturnType);
}
if ($name === '__set_state') {
return $this->returnType = TypehintHelper::decideType(new ObjectWithoutClassType(), $this->phpDocReturnType);
}
}

$this->returnType = TypehintHelper::decideTypeFromReflection(
$this->reflection->getReturnType(),
$returnType,
$this->phpDocReturnType,
$this->declaringClass->getName(),
);
Expand Down
5 changes: 5 additions & 0 deletions tests/PHPStan/Rules/Methods/ReturnTypeRuleTest.php
Expand Up @@ -815,4 +815,9 @@ public function testBug8146bErrors(): void
$this->analyse([__DIR__ . '/data/bug-8146b-errors.php'], []); // there could be a valid error
}

public function testBug8573(): void
{
$this->analyse([__DIR__ . '/data/bug-8573.php'], []);
}

}
26 changes: 26 additions & 0 deletions tests/PHPStan/Rules/Methods/data/bug-8573.php
@@ -0,0 +1,26 @@
<?php declare(strict_types = 1);

class A
{
final public function __construct() { }

/**
* @param array<string, mixed> $data
*/
public static function __set_state(array $data): static
{
$obj = new static();

return $obj;
}
}

class B extends A
{
public static function __set_state(array $data): static
{
$obj = parent::__set_state($data);

return $obj;
}
}

0 comments on commit 630430f

Please sign in to comment.