Skip to content

Commit

Permalink
[TypeDeclaration] Keep constant false return type from strict native …
Browse files Browse the repository at this point in the history
…call (#5223)
  • Loading branch information
tomi85 committed Dec 3, 2023
1 parent 483aca1 commit ae081e1
Show file tree
Hide file tree
Showing 6 changed files with 142 additions and 4 deletions.
20 changes: 17 additions & 3 deletions packages/NodeTypeResolver/PHPStan/Type/TypeFactory.php
Expand Up @@ -56,16 +56,30 @@ public function createMixedPassedOrUnionType(array $types, bool $keepConstantTyp
*/
public function uniquateTypes(array $types, bool $keepConstant = false): array
{
$constantTypeHashes = [];
$uniqueTypes = [];

foreach ($types as $type) {
if (! $keepConstant) {
$type = $this->removeValueFromConstantType($type);
$removedConstantType = $this->removeValueFromConstantType($type);
$removedConstantTypeHash = $this->typeHasher->createTypeHash($removedConstantType);

if ($keepConstant && $type !== $removedConstantType) {
$typeHash = $this->typeHasher->createTypeHash($type);
$constantTypeHashes[$typeHash] = $removedConstantTypeHash;
} else {
$type = $removedConstantType;
$typeHash = $removedConstantTypeHash;
}

$typeHash = $this->typeHasher->createTypeHash($type);
$uniqueTypes[$typeHash] = $type;
}

foreach ($constantTypeHashes as $constantTypeHash => $removedConstantTypeHash) {
if (array_key_exists($removedConstantTypeHash, $uniqueTypes)) {
unset($uniqueTypes[$constantTypeHash]);
}
}

// re-index
return array_values($uniqueTypes);
}
Expand Down
@@ -0,0 +1,35 @@
<?php

namespace Rector\Tests\TypeDeclaration\Rector\ClassMethod\ReturnTypeFromStrictNativeCallRector\Fixture;

final class NativeMethodCallReturningBooleanUnionFalse
{
public function run(string $needle, array $haystack)
{
if (rand(0,1)) {
return in_array($needle, $haystack, true);
}

return ob_get_clean();
}
}

?>
-----
<?php

namespace Rector\Tests\TypeDeclaration\Rector\ClassMethod\ReturnTypeFromStrictNativeCallRector\Fixture;

final class NativeMethodCallReturningBooleanUnionFalse
{
public function run(string $needle, array $haystack): bool|string
{
if (rand(0,1)) {
return in_array($needle, $haystack, true);
}

return ob_get_clean();
}
}

?>
@@ -0,0 +1,27 @@
<?php

namespace Rector\Tests\TypeDeclaration\Rector\ClassMethod\ReturnTypeFromStrictNativeCallRector\Fixture;

final class NativeMethodCallReturningUnion
{
public function run()
{
return time_nanosleep(100, 100);
}
}

?>
-----
<?php

namespace Rector\Tests\TypeDeclaration\Rector\ClassMethod\ReturnTypeFromStrictNativeCallRector\Fixture;

final class NativeMethodCallReturningUnion
{
public function run(): array|bool
{
return time_nanosleep(100, 100);
}
}

?>
@@ -0,0 +1,27 @@
<?php

namespace Rector\Tests\TypeDeclaration\Rector\ClassMethod\ReturnTypeFromStrictNativeCallRector\Fixture;

final class NativeMethodCallReturningUnionFalse
{
public function run()
{
return ob_get_clean();
}
}

?>
-----
<?php

namespace Rector\Tests\TypeDeclaration\Rector\ClassMethod\ReturnTypeFromStrictNativeCallRector\Fixture;

final class NativeMethodCallReturningUnionFalse
{
public function run(): string|false
{
return ob_get_clean();
}
}

?>
@@ -0,0 +1,35 @@
<?php

namespace Rector\Tests\TypeDeclaration\Rector\ClassMethod\ReturnTypeFromStrictNativeCallRector\Fixture;

final class NativeMethodCallReturningMergedUnionFalseOrBoolean
{
public function run(string $needle, array $haystack)
{
if (rand(0,1)) {
return ob_get_clean();
}

return in_array($needle, $haystack, true);
}
}

?>
-----
<?php

namespace Rector\Tests\TypeDeclaration\Rector\ClassMethod\ReturnTypeFromStrictNativeCallRector\Fixture;

final class NativeMethodCallReturningMergedUnionFalseOrBoolean
{
public function run(string $needle, array $haystack): string|bool
{
if (rand(0,1)) {
return ob_get_clean();
}

return in_array($needle, $haystack, true);
}
}

?>
Expand Up @@ -96,7 +96,7 @@ public function refactorWithScope(Node $node, Scope $scope): ?Node
$callLikeTypes[] = $this->getType($nativeCallLike);
}

$returnType = $this->typeFactory->createMixedPassedOrUnionType($callLikeTypes);
$returnType = $this->typeFactory->createMixedPassedOrUnionTypeAndKeepConstant($callLikeTypes);
if ($returnType instanceof MixedType) {
return null;
}
Expand Down

0 comments on commit ae081e1

Please sign in to comment.