diff --git a/rules-tests/Php80/Rector/Ternary/TernaryToNullsafeCoalesceRector/Fixture/skip_mixed_return.php.inc b/rules-tests/Php80/Rector/Ternary/TernaryToNullsafeCoalesceRector/Fixture/skip_mixed_return.php.inc new file mode 100644 index 00000000000..38875f6ae9f --- /dev/null +++ b/rules-tests/Php80/Rector/Ternary/TernaryToNullsafeCoalesceRector/Fixture/skip_mixed_return.php.inc @@ -0,0 +1,23 @@ +findMixed() : ''; + } + + public function runUntyped(?SomeObject $someObject): mixed + { + return null !== $someObject ? $someObject->findUntyped() : ''; + } + + public function runUntypedProperty(?SomeObject $someObject): mixed + { + return null !== $someObject ? $someObject->untypedName : ''; + } +} diff --git a/rules-tests/Php80/Rector/Ternary/TernaryToNullsafeCoalesceRector/Source/SomeObject.php b/rules-tests/Php80/Rector/Ternary/TernaryToNullsafeCoalesceRector/Source/SomeObject.php index 6be342ab4f7..126528d7db8 100644 --- a/rules-tests/Php80/Rector/Ternary/TernaryToNullsafeCoalesceRector/Source/SomeObject.php +++ b/rules-tests/Php80/Rector/Ternary/TernaryToNullsafeCoalesceRector/Source/SomeObject.php @@ -8,6 +8,8 @@ final class SomeObject { public string $name = 'name'; + public $untypedName = 'name'; + public function getName(): string { return $this->name; @@ -17,4 +19,14 @@ public function findName(): ?string { return $this->name; } + + public function findMixed(): mixed + { + return $this->name; + } + + public function findUntyped() + { + return $this->name; + } } diff --git a/rules/Php80/Rector/Ternary/TernaryToNullsafeCoalesceRector.php b/rules/Php80/Rector/Ternary/TernaryToNullsafeCoalesceRector.php index 3ee42ec82bf..779ee659936 100644 --- a/rules/Php80/Rector/Ternary/TernaryToNullsafeCoalesceRector.php +++ b/rules/Php80/Rector/Ternary/TernaryToNullsafeCoalesceRector.php @@ -16,7 +16,6 @@ use PhpParser\Node\Expr\StaticPropertyFetch; use PhpParser\Node\Expr\Ternary; use PhpParser\Node\Expr\Variable; -use PHPStan\Type\TypeCombinator; use Rector\PhpParser\Node\Value\ValueResolver; use Rector\Rector\AbstractRector; use Rector\ValueObject\PhpVersionFeature; @@ -185,13 +184,14 @@ private function isPureExpr(Expr $expr): bool /** * Guards the "?? $fallback" rewrite. * - * The ternary and the coalesce only agree while the call itself cannot return null: + * The ternary and the coalesce only agree while the call itself cannot return null, + * so "mixed" and untyped calls are skipped too: * * null !== $a ? $a->find() : '' // $a->find() returning null yields null * $a?->find() ?? '' // $a->find() returning null yields '' */ private function shouldSkipCoalesceFallback(Expr $callExpr): bool { - return TypeCombinator::containsNull($this->getType($callExpr)); + return ! $this->getType($callExpr)->isNull()->no(); } }