Skip to content

Commit

Permalink
Parent template type should respect child class bound when unspecified
Browse files Browse the repository at this point in the history
  • Loading branch information
ondrejmirtes committed Apr 5, 2023
1 parent 95a8777 commit 1017dc7
Show file tree
Hide file tree
Showing 3 changed files with 36 additions and 2 deletions.
3 changes: 1 addition & 2 deletions src/Reflection/ClassReflection.php
Original file line number Diff line number Diff line change
Expand Up @@ -199,7 +199,6 @@ public function getParentClass(): ?ClassReflection
$extendedType = TemplateTypeHelper::resolveTemplateTypes(
$extendedType,
$this->getPossiblyIncompleteActiveTemplateTypeMap(),
true,
);
}

Expand Down Expand Up @@ -1266,7 +1265,7 @@ public function typeMapFromList(array $types): TemplateTypeMap
$map = [];
$i = 0;
foreach ($resolvedPhpDoc->getTemplateTags() as $tag) {
$map[$tag->getName()] = $types[$i] ?? new ErrorType();
$map[$tag->getName()] = $types[$i] ?? $tag->getBound();
$i++;
}

Expand Down
9 changes: 9 additions & 0 deletions tests/PHPStan/Rules/Methods/data/bug-4008.php
Original file line number Diff line number Diff line change
Expand Up @@ -29,3 +29,12 @@ class OtherGenericClass{}
abstract class BaseModel{}

class Model extends BaseModel{}

/**
* @template T of Model
* @extends GenericClass<T>
*/
class ChildGenericGenericClass extends GenericClass
{

}
26 changes: 26 additions & 0 deletions tests/PHPStan/Type/ObjectTypeTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,10 @@

use ArrayAccess;
use ArrayObject;
use Bug4008\BaseModel;
use Bug4008\ChildGenericGenericClass;
use Bug4008\GenericClass;
use Bug4008\Model;
use Bug8850\UserInSessionInRoleEndpointExtension;
use Bug9006\TestInterface;
use Closure;
Expand Down Expand Up @@ -665,4 +669,26 @@ public function testGetEnumCases(
}
}

public function testClassReflectionWithTemplateBound(): void
{
$type = new ObjectType(GenericClass::class);
$classReflection = $type->getClassReflection();
$this->assertNotNull($classReflection);
$tModlel = $classReflection->getActiveTemplateTypeMap()->getType('TModlel');
$this->assertNotNull($tModlel);
$this->assertSame(BaseModel::class, $tModlel->describe(VerbosityLevel::precise()));
}

public function testClassReflectionParentWithTemplateBound(): void
{
$type = new ObjectType(ChildGenericGenericClass::class);
$classReflection = $type->getClassReflection();
$this->assertNotNull($classReflection);
$ancestor = $classReflection->getAncestorWithClassName(GenericClass::class);
$this->assertNotNull($ancestor);
$tModlel = $ancestor->getActiveTemplateTypeMap()->getType('TModlel');
$this->assertNotNull($tModlel);
$this->assertSame(Model::class, $tModlel->describe(VerbosityLevel::precise()));
}

}

0 comments on commit 1017dc7

Please sign in to comment.