Skip to content

Commit

Permalink
Fix StaticType::isSuperTypeOf() for subtypes of ObjectType
Browse files Browse the repository at this point in the history
  • Loading branch information
ondrejmirtes committed Apr 4, 2023
1 parent 307176a commit b439fed
Show file tree
Hide file tree
Showing 6 changed files with 75 additions and 11 deletions.
2 changes: 1 addition & 1 deletion phpstan-baseline.neon
Original file line number Diff line number Diff line change
Expand Up @@ -1450,7 +1450,7 @@ parameters:

-
message: "#^Doing instanceof PHPStan\\\\Type\\\\ObjectType is error\\-prone and deprecated\\. Use Type\\:\\:isObject\\(\\) or Type\\:\\:getObjectClassNames\\(\\) instead\\.$#"
count: 3
count: 2
path: src/Type/StaticType.php

-
Expand Down
5 changes: 4 additions & 1 deletion src/Reflection/Native/NativeMethodReflection.php
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,10 @@ public function getPrototype(): ClassMemberReflection
{
try {
$prototypeMethod = $this->reflection->getPrototype();
$prototypeDeclaringClass = $this->reflectionProvider->getClass($prototypeMethod->getDeclaringClass()->getName());
$prototypeDeclaringClass = $this->declaringClass->getAncestorWithClassName($prototypeMethod->getDeclaringClass()->getName());
if ($prototypeDeclaringClass === null) {
$prototypeDeclaringClass = $this->reflectionProvider->getClass($prototypeMethod->getDeclaringClass()->getName());
}

$tentativeReturnType = null;
if ($prototypeMethod->getTentativeReturnType() !== null) {
Expand Down
5 changes: 4 additions & 1 deletion src/Reflection/Php/PhpMethodReflection.php
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,10 @@ public function getPrototype(): ClassMemberReflection
{
try {
$prototypeMethod = $this->reflection->getPrototype();
$prototypeDeclaringClass = $this->reflectionProvider->getClass($prototypeMethod->getDeclaringClass()->getName());
$prototypeDeclaringClass = $this->declaringClass->getAncestorWithClassName($prototypeMethod->getDeclaringClass()->getName());
if ($prototypeDeclaringClass === null) {
$prototypeDeclaringClass = $this->reflectionProvider->getClass($prototypeMethod->getDeclaringClass()->getName());
}

$tentativeReturnType = null;
if ($prototypeMethod->getTentativeReturnType() !== null) {
Expand Down
17 changes: 9 additions & 8 deletions src/Type/StaticType.php
Original file line number Diff line number Diff line change
Expand Up @@ -149,13 +149,6 @@ public function acceptsWithReason(Type $type, bool $strictTypes): AcceptsResult

public function isSuperTypeOf(Type $type): TrinaryLogic
{
if ($type instanceof ObjectType) {
$classReflection = $type->getClassReflection();
if ($classReflection !== null && $classReflection->isFinal()) {
$type = new StaticType($classReflection, $type->getSubtractedType());
}
}

if ($type instanceof self) {
return $this->getStaticObjectType()->isSuperTypeOf($type);
}
Expand All @@ -165,7 +158,15 @@ public function isSuperTypeOf(Type $type): TrinaryLogic
}

if ($type instanceof ObjectType) {
return $this->getStaticObjectType()->isSuperTypeOf($type)->and(TrinaryLogic::createMaybe());
$result = $this->getStaticObjectType()->isSuperTypeOf($type);
if ($result->yes()) {
$classReflection = $type->getClassReflection();
if ($classReflection !== null && $classReflection->isFinal()) {
return $result;
}
}

return $result->and(TrinaryLogic::createMaybe());
}

if ($type instanceof CompoundType) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -963,4 +963,23 @@ public function testEnumTips(): void
]);
}

public function testBug9142(): void
{
if (PHP_VERSION_ID < 80100) {
$this->markTestSkipped('Test requires PHP 8.1.');
}

$this->checkAlwaysTrueStrictComparison = true;
$this->analyse([__DIR__ . '/data/bug-9142.php'], [
[
'Strict comparison using === between $this(Bug9142\MyEnum) and Bug9142\MyEnum::Three will always evaluate to false.',
18,
],
[
'Strict comparison using === between Bug9142\MyEnum and Bug9142\MyEnum::Three will always evaluate to false.',
31,
],
]);
}

}
38 changes: 38 additions & 0 deletions tests/PHPStan/Rules/Comparison/data/bug-9142.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
<?php // lint >= 8.1

namespace Bug9142;

enum MyEnum: string
{

case One = 'one';
case Two = 'two';
case Three = 'three';

public function thisTypeWithSubtractedEnumCase(): int
{
if ($this === self::Three) {
return -1;
}

if ($this === self::Three) {
return 0;
}

return 1;
}

public function enumTypeWithSubtractedEnumCase(self $self): int
{
if ($self === self::Three) {
return -1;
}

if ($self === self::Three) {
return 0;
}

return 1;
}

}

0 comments on commit b439fed

Please sign in to comment.