Skip to content

Commit 1f608dc

Browse files
committed
Revert "Fixed '$this instanceof X will always be false' in traits"
Closes phpstan/phpstan#8879 Closes phpstan/phpstan#8888
1 parent 19d0669 commit 1f608dc

14 files changed

+79
-435
lines changed

src/Analyser/MutatingScope.php

+3-16
Original file line numberDiff line numberDiff line change
@@ -2456,26 +2456,13 @@ public function enterTrait(ClassReflection $traitReflection): self
24562456
if (count($traitNameParts) > 1) {
24572457
$namespace = implode('\\', array_slice($traitNameParts, 0, -1));
24582458
}
2459-
2460-
$traitContext = $this->context->enterTrait($traitReflection);
2461-
$classReflection = $traitContext->getClassReflection();
2462-
if ($classReflection === null) {
2463-
throw new ShouldNotHappenException();
2464-
}
2465-
2466-
$thisHolder = ExpressionTypeHolder::createYes(new Variable('this'), new ThisType($classReflection, null, $traitReflection));
2467-
$expressionTypes = $this->expressionTypes;
2468-
$expressionTypes['$this'] = $thisHolder;
2469-
$nativeExpressionTypes = $this->nativeExpressionTypes;
2470-
$nativeExpressionTypes['$this'] = $thisHolder;
2471-
24722459
return $this->scopeFactory->create(
2473-
$traitContext,
2460+
$this->context->enterTrait($traitReflection),
24742461
$this->isDeclareStrictTypes(),
24752462
$this->getFunction(),
24762463
$namespace,
2477-
$expressionTypes,
2478-
$nativeExpressionTypes,
2464+
$this->expressionTypes,
2465+
$this->nativeExpressionTypes,
24792466
[],
24802467
$this->inClosureBindScopeClass,
24812468
$this->anonymousFunctionReflection,

src/Type/ObjectType.php

-25
Original file line numberDiff line numberDiff line change
@@ -286,31 +286,6 @@ public function isSuperTypeOf(Type $type): TrinaryLogic
286286
return self::$superTypes[$thisDescription][$description] = TrinaryLogic::createMaybe();
287287
}
288288

289-
if ($type instanceof ThisType && $type->isInTrait()) {
290-
if ($type->getSubtractedType() !== null) {
291-
$isSuperType = $type->getSubtractedType()->isSuperTypeOf($this);
292-
if ($isSuperType->yes()) {
293-
return self::$superTypes[$thisDescription][$description] = TrinaryLogic::createNo();
294-
}
295-
}
296-
297-
if ($this->getClassReflection() === null) {
298-
return self::$superTypes[$thisDescription][$description] = TrinaryLogic::createMaybe();
299-
}
300-
301-
$thisClassReflection = $this->getClassReflection();
302-
if ($thisClassReflection->isTrait()) {
303-
return self::$superTypes[$thisDescription][$description] = TrinaryLogic::createNo();
304-
}
305-
306-
$traitReflection = $type->getTraitReflection();
307-
if ($thisClassReflection->isFinal() && !$thisClassReflection->hasTraitUse($traitReflection->getName())) {
308-
return self::$superTypes[$thisDescription][$description] = TrinaryLogic::createNo();
309-
}
310-
311-
return self::$superTypes[$thisDescription][$description] = TrinaryLogic::createMaybe();
312-
}
313-
314289
$transformResult = static fn (TrinaryLogic $result) => $result;
315290
if ($this->subtractedType !== null) {
316291
$isSuperType = $this->subtractedType->isSuperTypeOf($type);

src/Type/ThisType.php

+3-64
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@
55
use PHPStan\Reflection\ClassReflection;
66
use PHPStan\Reflection\ReflectionProviderStaticAccessor;
77
use PHPStan\TrinaryLogic;
8-
use function get_class;
98
use function sprintf;
109

1110
/** @api */
@@ -18,70 +17,24 @@ class ThisType extends StaticType
1817
public function __construct(
1918
ClassReflection $classReflection,
2019
?Type $subtractedType = null,
21-
private ?ClassReflection $traitReflection = null,
2220
)
2321
{
2422
parent::__construct($classReflection, $subtractedType);
2523
}
2624

27-
public function equals(Type $type): bool
28-
{
29-
if (get_class($type) !== static::class) {
30-
return false;
31-
}
32-
33-
/** @var ThisType $type */
34-
$type = $type;
35-
$equals = $this->getStaticObjectType()->equals($type->getStaticObjectType());
36-
if (!$equals) {
37-
return false;
38-
}
39-
40-
if ($this->getTraitReflection() === null) {
41-
if ($type->getTraitReflection() === null) {
42-
return true;
43-
}
44-
45-
return false;
46-
}
47-
if ($type->getTraitReflection() === null) {
48-
return false;
49-
}
50-
51-
return $this->getTraitReflection()->getName() === $type->getTraitReflection()->getName();
52-
}
53-
5425
public function changeBaseClass(ClassReflection $classReflection): StaticType
5526
{
56-
return new self($classReflection, $this->getSubtractedType(), $this->traitReflection);
27+
return new self($classReflection, $this->getSubtractedType());
5728
}
5829

5930
public function describe(VerbosityLevel $level): string
6031
{
61-
$callback = fn () => sprintf('$this(%s)', $this->getStaticObjectType()->describe($level));
62-
return $level->handle(
63-
$callback,
64-
$callback,
65-
$callback,
66-
function () use ($callback): string {
67-
$base = $callback();
68-
$trait = $this->getTraitReflection();
69-
if ($trait === null) {
70-
return $base;
71-
}
72-
73-
return sprintf('%s-trait-%s', $base, $trait->getDisplayName());
74-
},
75-
);
32+
return sprintf('$this(%s)', $this->getStaticObjectType()->describe($level));
7633
}
7734

7835
public function isSuperTypeOf(Type $type): TrinaryLogic
7936
{
8037
if ($type instanceof self) {
81-
if ($this->equals($type)) {
82-
return TrinaryLogic::createYes();
83-
}
84-
8538
return $this->getStaticObjectType()->isSuperTypeOf($type);
8639
}
8740

@@ -98,25 +51,12 @@ public function changeSubtractedType(?Type $subtractedType): Type
9851
{
9952
$type = parent::changeSubtractedType($subtractedType);
10053
if ($type instanceof parent) {
101-
return new self($type->getClassReflection(), $subtractedType, $this->traitReflection);
54+
return new self($type->getClassReflection(), $subtractedType);
10255
}
10356

10457
return $type;
10558
}
10659

107-
/**
108-
* @phpstan-assert-if-true !null $this->getTraitReflection()
109-
*/
110-
public function isInTrait(): bool
111-
{
112-
return $this->traitReflection !== null;
113-
}
114-
115-
public function getTraitReflection(): ?ClassReflection
116-
{
117-
return $this->traitReflection;
118-
}
119-
12060
public function traverse(callable $cb): Type
12161
{
12262
$subtractedType = $this->getSubtractedType() !== null ? $cb($this->getSubtractedType()) : null;
@@ -125,7 +65,6 @@ public function traverse(callable $cb): Type
12565
return new self(
12666
$this->getClassReflection(),
12767
$subtractedType,
128-
$this->traitReflection,
12968
);
13069
}
13170

tests/PHPStan/Analyser/NodeScopeResolverTest.php

-1
Original file line numberDiff line numberDiff line change
@@ -1179,7 +1179,6 @@ public function dataFileAsserts(): iterable
11791179
yield from $this->gatherAssertTypes(__DIR__ . '/data/callsite-cast-narrowing.php');
11801180
yield from $this->gatherAssertTypes(__DIR__ . '/data/bug-8775.php');
11811181
yield from $this->gatherAssertTypes(__DIR__ . '/data/bug-8752.php');
1182-
yield from $this->gatherAssertTypes(__DIR__ . '/data/trait-instance-of.php');
11831182
yield from $this->gatherAssertTypes(__DIR__ . '/data/list-shapes.php');
11841183
yield from $this->gatherAssertTypes(__DIR__ . '/data/bug-7607.php');
11851184
}

tests/PHPStan/Analyser/data/trait-instance-of.php

-70
This file was deleted.

tests/PHPStan/Rules/Classes/ExistingClassInInstanceOfRuleTest.php

-10
Original file line numberDiff line numberDiff line change
@@ -70,14 +70,4 @@ public function testBug7720(): void
7070
]);
7171
}
7272

73-
public function testTraitInstanceOf(): void
74-
{
75-
$this->analyse([__DIR__ . '/../../Analyser/data/trait-instance-of.php'], [
76-
[
77-
'Instanceof between $this(TraitInstanceOf\ATrait1Class) and trait TraitInstanceOf\Trait2 will always evaluate to false.',
78-
21,
79-
],
80-
]);
81-
}
82-
8373
}

tests/PHPStan/Rules/Classes/ImpossibleInstanceOfRuleTest.php

-7
Original file line numberDiff line numberDiff line change
@@ -368,11 +368,4 @@ public function testBug5333(): void
368368
]);
369369
}
370370

371-
public function testBug3632(): void
372-
{
373-
$this->checkAlwaysTrueInstanceOf = true;
374-
$this->treatPhpDocTypesAsCertain = false;
375-
$this->analyse([__DIR__ . '/data/bug-3632.php'], []);
376-
}
377-
378371
}

tests/PHPStan/Rules/Classes/data/bug-3632.php

-33
This file was deleted.

tests/PHPStan/Rules/Methods/CallMethodsRuleTest.php

+9
Original file line numberDiff line numberDiff line change
@@ -2781,4 +2781,13 @@ public function testCannotCallOnGenericClassString(): void
27812781
]);
27822782
}
27832783

2784+
public function testBug8888(): void
2785+
{
2786+
$this->checkThisOnly = false;
2787+
$this->checkNullables = true;
2788+
$this->checkUnionTypes = true;
2789+
$this->checkExplicitMixed = true;
2790+
$this->analyse([__DIR__ . '/data/bug-8888.php'], []);
2791+
}
2792+
27842793
}

tests/PHPStan/Rules/Methods/ReturnTypeRuleTest.php

+5
Original file line numberDiff line numberDiff line change
@@ -820,4 +820,9 @@ public function testBug8573(): void
820820
$this->analyse([__DIR__ . '/data/bug-8573.php'], []);
821821
}
822822

823+
public function testBug8879(): void
824+
{
825+
$this->analyse([__DIR__ . '/data/bug-8879.php'], []);
826+
}
827+
823828
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
<?php
2+
3+
namespace Bug8879;
4+
5+
trait GetThisTrait {
6+
/** @return $this */
7+
function getThis() {
8+
return $this;
9+
}
10+
}
11+
12+
/** @template T */
13+
final class A {
14+
use GetThisTrait;
15+
}

0 commit comments

Comments
 (0)