diff --git a/rules-tests/DeadCode/Rector/FunctionLike/NarrowWideUnionReturnTypeRector/Fixture/skip_assert.php.inc b/rules-tests/DeadCode/Rector/FunctionLike/NarrowWideUnionReturnTypeRector/Fixture/skip_assert.php.inc new file mode 100644 index 00000000000..afbd13a8d60 --- /dev/null +++ b/rules-tests/DeadCode/Rector/FunctionLike/NarrowWideUnionReturnTypeRector/Fixture/skip_assert.php.inc @@ -0,0 +1,26 @@ + [ + 'directory' => null, + ], + ]; + + public function getCacheDirectory(): ?string + { + $dir = $this->config['cache']['directory'] ?? null; + \assert(\is_string($dir) || $dir === null, 'Invalid cache directory.'); + + return $dir; + } +} + diff --git a/rules/DeadCode/Rector/FunctionLike/NarrowWideUnionReturnTypeRector.php b/rules/DeadCode/Rector/FunctionLike/NarrowWideUnionReturnTypeRector.php index 99ffb859742..2f0d6948e9f 100644 --- a/rules/DeadCode/Rector/FunctionLike/NarrowWideUnionReturnTypeRector.php +++ b/rules/DeadCode/Rector/FunctionLike/NarrowWideUnionReturnTypeRector.php @@ -20,6 +20,7 @@ use PhpParser\Node\UnionType; use PHPStan\PhpDocParser\Ast\PhpDoc\ReturnTagValueNode; use PHPStan\Reflection\ClassReflection; +use PHPStan\Type\NeverType; use PHPStan\Type\NullType; use PHPStan\Type\ObjectType; use PHPStan\Type\Type; @@ -272,6 +273,13 @@ private function collectActualReturnTypes(array $returnStatements): array private function resolveNativeReturnTypes(Expr $expr): array { if (! $expr instanceof Ternary || ! $this->hasVendorClassConstFetch($expr->cond)) { + $type = $this->nodeTypeResolver->getType($expr); + + // native type may be narrowed by assertions even when the resolved scope is unreachable + if ($type instanceof NeverType) { + return [$type]; + } + return [$this->nodeTypeResolver->getNativeType($expr)]; }