Skip to content

Commit 7068e22

Browse files
github-actions[bot]phpstan-bot
authored andcommitted
Fix conditional return type on $this not using subtracted type
- When a method has a conditional return type like `@return ($this is self::A ? int : null)`, and `$this` has a subtracted type (e.g. `$this(X~X::A)` from narrowing), the conditional was not properly resolved because the subtracted type was not propagated - The root cause was in `StaticType::transformStaticType` which transforms `StaticType` instances in return types but did not propagate the calling type's subtracted type - Added subtracted type propagation in `StaticType::transformStaticType` to match the behavior of `CalledOnTypeUnresolvedMethodPrototypeReflection::transformStaticType` - New regression test in tests/PHPStan/Analyser/nsrt/bug-12244.php Closes phpstan/phpstan#12244
1 parent 1bbe9dc commit 7068e22

File tree

2 files changed

+39
-0
lines changed

2 files changed

+39
-0
lines changed

src/Type/StaticType.php

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -369,6 +369,13 @@ private function transformStaticType(Type $type, ClassMemberAccessAnswerer $scop
369369
$type = new self($type->getClassReflection(), $type->getSubtractedType());
370370
}
371371

372+
if ($this->getSubtractedType() !== null && $type->getSubtractedType() === null) {
373+
$type = $type->changeSubtractedType($this->getSubtractedType());
374+
if (!$type instanceof StaticType) {
375+
return $traverse($type);
376+
}
377+
}
378+
372379
if (!$isFinal || $type instanceof ThisType) {
373380
return $traverse($type);
374381
}
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
<?php // lint >= 8.1
2+
3+
declare(strict_types = 1);
4+
5+
namespace Bug12244;
6+
7+
use function PHPStan\Testing\assertType;
8+
9+
enum X: string {
10+
case A = 'a';
11+
case B = 'b';
12+
case C = 'c';
13+
14+
/** @return ($this is self::A ? int : null) */
15+
public function get(): ?int {
16+
return ($this === self::A) ? 123 : null;
17+
}
18+
19+
public function doSomething(): void {
20+
if ($this !== self::A) {
21+
assertType('$this(Bug12244\X~Bug12244\X::A)', $this);
22+
assertType('null', $this->get());
23+
}
24+
}
25+
26+
public static function doSomethingFor(X $x): void {
27+
if ($x !== self::A) {
28+
assertType('Bug12244\X~Bug12244\X::A', $x);
29+
assertType('null', $x->get());
30+
}
31+
}
32+
}

0 commit comments

Comments
 (0)