Skip to content

Commit

Permalink
Fix GenericObjectType::isSuperTypeOf() for covariant template types
Browse files Browse the repository at this point in the history
  • Loading branch information
ondrejmirtes committed Feb 21, 2021
1 parent d3b5d60 commit 3f6de01
Show file tree
Hide file tree
Showing 9 changed files with 48 additions and 25 deletions.
5 changes: 2 additions & 3 deletions src/Type/Generic/GenericObjectType.php
Original file line number Diff line number Diff line change
Expand Up @@ -162,9 +162,8 @@ private function isSuperTypeOfInternal(Type $type, bool $acceptsContext): Trinar
if (!$templateType instanceof TemplateType) {
throw new \PHPStan\ShouldNotHappenException();
}
if (!$templateType->isValidVariance($this->types[$i], $ancestor->types[$i])) {
return TrinaryLogic::createNo();
}

return $templateType->isValidVariance($this->types[$i], $ancestor->types[$i])->and($nakedSuperTypeOf);
}

return $nakedSuperTypeOf;
Expand Down
2 changes: 1 addition & 1 deletion src/Type/Generic/TemplateMixedType.php
Original file line number Diff line number Diff line change
Expand Up @@ -160,7 +160,7 @@ public function toArgument(): TemplateType
);
}

public function isValidVariance(Type $a, Type $b): bool
public function isValidVariance(Type $a, Type $b): TrinaryLogic
{
return $this->variance->isValidVariance($a, $b);
}
Expand Down
2 changes: 1 addition & 1 deletion src/Type/Generic/TemplateObjectType.php
Original file line number Diff line number Diff line change
Expand Up @@ -177,7 +177,7 @@ public function toArgument(): TemplateType
);
}

public function isValidVariance(Type $a, Type $b): bool
public function isValidVariance(Type $a, Type $b): TrinaryLogic
{
return $this->variance->isValidVariance($a, $b);
}
Expand Down
2 changes: 1 addition & 1 deletion src/Type/Generic/TemplateObjectWithoutClassType.php
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,7 @@ public function toArgument(): TemplateType
);
}

public function isValidVariance(Type $a, Type $b): bool
public function isValidVariance(Type $a, Type $b): TrinaryLogic
{
return $this->variance->isValidVariance($a, $b);
}
Expand Down
3 changes: 2 additions & 1 deletion src/Type/Generic/TemplateType.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

namespace PHPStan\Type\Generic;

use PHPStan\TrinaryLogic;
use PHPStan\Type\CompoundType;
use PHPStan\Type\Type;

Expand All @@ -18,7 +19,7 @@ public function toArgument(): TemplateType;

public function isArgument(): bool;

public function isValidVariance(Type $a, Type $b): bool;
public function isValidVariance(Type $a, Type $b): TrinaryLogic;

public function getVariance(): TemplateTypeVariance;

Expand Down
13 changes: 7 additions & 6 deletions src/Type/Generic/TemplateTypeVariance.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

namespace PHPStan\Type\Generic;

use PHPStan\TrinaryLogic;
use PHPStan\Type\MixedType;
use PHPStan\Type\Type;

Expand Down Expand Up @@ -94,26 +95,26 @@ public function compose(self $other): self
return $other;
}

public function isValidVariance(Type $a, Type $b): bool
public function isValidVariance(Type $a, Type $b): TrinaryLogic
{
if ($a instanceof MixedType && !$a instanceof TemplateType) {
return true;
return TrinaryLogic::createYes();
}

if ($b instanceof MixedType && !$b instanceof TemplateType) {
return true;
return TrinaryLogic::createYes();
}

if ($this->invariant()) {
return $a->equals($b);
return TrinaryLogic::createFromBoolean($a->equals($b));
}

if ($this->covariant()) {
return $a->isSuperTypeOf($b)->yes();
return $a->isSuperTypeOf($b);
}

if ($this->contravariant()) {
return $b->isSuperTypeOf($a)->yes();
return $b->isSuperTypeOf($a);
}

throw new \PHPStan\ShouldNotHappenException();
Expand Down
7 changes: 0 additions & 7 deletions tests/PHPStan/Generics/data/bug2620-3.json

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -174,10 +174,6 @@ public function testBug3777(): void
'Property Bug3777\Ipsum::$ipsum (Bug3777\Lorem<stdClass, Exception>) does not accept Bug3777\Lorem<Exception, stdClass>.',
95,
],
[
'Property Bug3777\Ipsum2::$lorem2 (Bug3777\Lorem2<stdClass, Exception>) does not accept Bug3777\Lorem2<stdClass, object>.',
129,
],
[
'Property Bug3777\Ipsum2::$ipsum2 (Bug3777\Lorem2<stdClass, Exception>) does not accept Bug3777\Lorem2<Exception, object>.',
131,
Expand Down
35 changes: 34 additions & 1 deletion tests/PHPStan/Type/Generic/GenericObjectTypeTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
use PHPStan\Type\IntersectionType;
use PHPStan\Type\MixedType;
use PHPStan\Type\ObjectType;
use PHPStan\Type\ObjectWithoutClassType;
use PHPStan\Type\Test\A;
use PHPStan\Type\Test\B;
use PHPStan\Type\Test\C;
Expand Down Expand Up @@ -84,7 +85,39 @@ public function dataIsSuperTypeOf(): array
'covariant with super type' => [
new GenericObjectType(C\Covariant::class, [new ObjectType('DateTime')]),
new GenericObjectType(C\Covariant::class, [new ObjectType('DateTimeInterface')]),
TrinaryLogic::createNo(),
TrinaryLogic::createMaybe(),
],
[
new ObjectType(\ReflectionClass::class),
new GenericObjectType(\ReflectionClass::class, [
new ObjectType(\stdClass::class),
]),
TrinaryLogic::createYes(),
],
[
new GenericObjectType(\ReflectionClass::class, [
new ObjectType(\stdClass::class),
]),
new ObjectType(\ReflectionClass::class),
TrinaryLogic::createMaybe(),
],
[
new GenericObjectType(\ReflectionClass::class, [
new ObjectWithoutClassType(),
]),
new GenericObjectType(\ReflectionClass::class, [
new ObjectType(\stdClass::class),
]),
TrinaryLogic::createYes(),
],
[
new GenericObjectType(\ReflectionClass::class, [
new ObjectType(\stdClass::class),
]),
new GenericObjectType(\ReflectionClass::class, [
new ObjectWithoutClassType(),
]),
TrinaryLogic::createMaybe(),
],
];
}
Expand Down

0 comments on commit 3f6de01

Please sign in to comment.