Skip to content

Commit

Permalink
Revert "Fixed '$this instanceof X will always be false' in traits"
Browse files Browse the repository at this point in the history
  • Loading branch information
ondrejmirtes committed Feb 17, 2023
1 parent 19d0669 commit 1f608dc
Show file tree
Hide file tree
Showing 14 changed files with 79 additions and 435 deletions.
19 changes: 3 additions & 16 deletions src/Analyser/MutatingScope.php
Expand Up @@ -2456,26 +2456,13 @@ public function enterTrait(ClassReflection $traitReflection): self
if (count($traitNameParts) > 1) {
$namespace = implode('\\', array_slice($traitNameParts, 0, -1));
}

$traitContext = $this->context->enterTrait($traitReflection);
$classReflection = $traitContext->getClassReflection();
if ($classReflection === null) {
throw new ShouldNotHappenException();
}

$thisHolder = ExpressionTypeHolder::createYes(new Variable('this'), new ThisType($classReflection, null, $traitReflection));
$expressionTypes = $this->expressionTypes;
$expressionTypes['$this'] = $thisHolder;
$nativeExpressionTypes = $this->nativeExpressionTypes;
$nativeExpressionTypes['$this'] = $thisHolder;

return $this->scopeFactory->create(
$traitContext,
$this->context->enterTrait($traitReflection),
$this->isDeclareStrictTypes(),
$this->getFunction(),
$namespace,
$expressionTypes,
$nativeExpressionTypes,
$this->expressionTypes,
$this->nativeExpressionTypes,
[],
$this->inClosureBindScopeClass,
$this->anonymousFunctionReflection,
Expand Down
25 changes: 0 additions & 25 deletions src/Type/ObjectType.php
Expand Up @@ -286,31 +286,6 @@ public function isSuperTypeOf(Type $type): TrinaryLogic
return self::$superTypes[$thisDescription][$description] = TrinaryLogic::createMaybe();
}

if ($type instanceof ThisType && $type->isInTrait()) {
if ($type->getSubtractedType() !== null) {
$isSuperType = $type->getSubtractedType()->isSuperTypeOf($this);
if ($isSuperType->yes()) {
return self::$superTypes[$thisDescription][$description] = TrinaryLogic::createNo();
}
}

if ($this->getClassReflection() === null) {
return self::$superTypes[$thisDescription][$description] = TrinaryLogic::createMaybe();
}

$thisClassReflection = $this->getClassReflection();
if ($thisClassReflection->isTrait()) {
return self::$superTypes[$thisDescription][$description] = TrinaryLogic::createNo();
}

$traitReflection = $type->getTraitReflection();
if ($thisClassReflection->isFinal() && !$thisClassReflection->hasTraitUse($traitReflection->getName())) {
return self::$superTypes[$thisDescription][$description] = TrinaryLogic::createNo();
}

return self::$superTypes[$thisDescription][$description] = TrinaryLogic::createMaybe();
}

$transformResult = static fn (TrinaryLogic $result) => $result;
if ($this->subtractedType !== null) {
$isSuperType = $this->subtractedType->isSuperTypeOf($type);
Expand Down
67 changes: 3 additions & 64 deletions src/Type/ThisType.php
Expand Up @@ -5,7 +5,6 @@
use PHPStan\Reflection\ClassReflection;
use PHPStan\Reflection\ReflectionProviderStaticAccessor;
use PHPStan\TrinaryLogic;
use function get_class;
use function sprintf;

/** @api */
Expand All @@ -18,70 +17,24 @@ class ThisType extends StaticType
public function __construct(
ClassReflection $classReflection,
?Type $subtractedType = null,
private ?ClassReflection $traitReflection = null,
)
{
parent::__construct($classReflection, $subtractedType);
}

public function equals(Type $type): bool
{
if (get_class($type) !== static::class) {
return false;
}

/** @var ThisType $type */
$type = $type;
$equals = $this->getStaticObjectType()->equals($type->getStaticObjectType());
if (!$equals) {
return false;
}

if ($this->getTraitReflection() === null) {
if ($type->getTraitReflection() === null) {
return true;
}

return false;
}
if ($type->getTraitReflection() === null) {
return false;
}

return $this->getTraitReflection()->getName() === $type->getTraitReflection()->getName();
}

public function changeBaseClass(ClassReflection $classReflection): StaticType
{
return new self($classReflection, $this->getSubtractedType(), $this->traitReflection);
return new self($classReflection, $this->getSubtractedType());
}

public function describe(VerbosityLevel $level): string
{
$callback = fn () => sprintf('$this(%s)', $this->getStaticObjectType()->describe($level));
return $level->handle(
$callback,
$callback,
$callback,
function () use ($callback): string {
$base = $callback();
$trait = $this->getTraitReflection();
if ($trait === null) {
return $base;
}

return sprintf('%s-trait-%s', $base, $trait->getDisplayName());
},
);
return sprintf('$this(%s)', $this->getStaticObjectType()->describe($level));
}

public function isSuperTypeOf(Type $type): TrinaryLogic
{
if ($type instanceof self) {
if ($this->equals($type)) {
return TrinaryLogic::createYes();
}

return $this->getStaticObjectType()->isSuperTypeOf($type);
}

Expand All @@ -98,25 +51,12 @@ public function changeSubtractedType(?Type $subtractedType): Type
{
$type = parent::changeSubtractedType($subtractedType);
if ($type instanceof parent) {
return new self($type->getClassReflection(), $subtractedType, $this->traitReflection);
return new self($type->getClassReflection(), $subtractedType);
}

return $type;
}

/**
* @phpstan-assert-if-true !null $this->getTraitReflection()
*/
public function isInTrait(): bool
{
return $this->traitReflection !== null;
}

public function getTraitReflection(): ?ClassReflection
{
return $this->traitReflection;
}

public function traverse(callable $cb): Type
{
$subtractedType = $this->getSubtractedType() !== null ? $cb($this->getSubtractedType()) : null;
Expand All @@ -125,7 +65,6 @@ public function traverse(callable $cb): Type
return new self(
$this->getClassReflection(),
$subtractedType,
$this->traitReflection,
);
}

Expand Down
1 change: 0 additions & 1 deletion tests/PHPStan/Analyser/NodeScopeResolverTest.php
Expand Up @@ -1179,7 +1179,6 @@ public function dataFileAsserts(): iterable
yield from $this->gatherAssertTypes(__DIR__ . '/data/callsite-cast-narrowing.php');
yield from $this->gatherAssertTypes(__DIR__ . '/data/bug-8775.php');
yield from $this->gatherAssertTypes(__DIR__ . '/data/bug-8752.php');
yield from $this->gatherAssertTypes(__DIR__ . '/data/trait-instance-of.php');
yield from $this->gatherAssertTypes(__DIR__ . '/data/list-shapes.php');
yield from $this->gatherAssertTypes(__DIR__ . '/data/bug-7607.php');
}
Expand Down
70 changes: 0 additions & 70 deletions tests/PHPStan/Analyser/data/trait-instance-of.php

This file was deleted.

10 changes: 0 additions & 10 deletions tests/PHPStan/Rules/Classes/ExistingClassInInstanceOfRuleTest.php
Expand Up @@ -70,14 +70,4 @@ public function testBug7720(): void
]);
}

public function testTraitInstanceOf(): void
{
$this->analyse([__DIR__ . '/../../Analyser/data/trait-instance-of.php'], [
[
'Instanceof between $this(TraitInstanceOf\ATrait1Class) and trait TraitInstanceOf\Trait2 will always evaluate to false.',
21,
],
]);
}

}
7 changes: 0 additions & 7 deletions tests/PHPStan/Rules/Classes/ImpossibleInstanceOfRuleTest.php
Expand Up @@ -368,11 +368,4 @@ public function testBug5333(): void
]);
}

public function testBug3632(): void
{
$this->checkAlwaysTrueInstanceOf = true;
$this->treatPhpDocTypesAsCertain = false;
$this->analyse([__DIR__ . '/data/bug-3632.php'], []);
}

}
33 changes: 0 additions & 33 deletions tests/PHPStan/Rules/Classes/data/bug-3632.php

This file was deleted.

9 changes: 9 additions & 0 deletions tests/PHPStan/Rules/Methods/CallMethodsRuleTest.php
Expand Up @@ -2781,4 +2781,13 @@ public function testCannotCallOnGenericClassString(): void
]);
}

public function testBug8888(): void
{
$this->checkThisOnly = false;
$this->checkNullables = true;
$this->checkUnionTypes = true;
$this->checkExplicitMixed = true;
$this->analyse([__DIR__ . '/data/bug-8888.php'], []);
}

}
5 changes: 5 additions & 0 deletions tests/PHPStan/Rules/Methods/ReturnTypeRuleTest.php
Expand Up @@ -820,4 +820,9 @@ public function testBug8573(): void
$this->analyse([__DIR__ . '/data/bug-8573.php'], []);
}

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

}
15 changes: 15 additions & 0 deletions tests/PHPStan/Rules/Methods/data/bug-8879.php
@@ -0,0 +1,15 @@
<?php

namespace Bug8879;

trait GetThisTrait {
/** @return $this */
function getThis() {
return $this;
}
}

/** @template T */
final class A {
use GetThisTrait;
}

1 comment on commit 1f608dc

@staabm
Copy link
Contributor

@staabm staabm commented on 1f608dc Feb 17, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

thanks for reverting and sorry for the trouble

Please sign in to comment.