Skip to content

Commit

Permalink
Merge pull request #7696 from AndrolGenhald/improve-bool-to-int-cast
Browse files Browse the repository at this point in the history
  • Loading branch information
weirdan committed Feb 18, 2022
2 parents 2d83a4b + 525a86e commit 6a68287
Show file tree
Hide file tree
Showing 2 changed files with 67 additions and 7 deletions.
27 changes: 20 additions & 7 deletions src/Psalm/Internal/Analyzer/Statements/Expression/CastAnalyzer.php
Expand Up @@ -45,7 +45,6 @@
use function array_merge;
use function array_pop;
use function array_values;
use function count;
use function get_class;

/**
Expand Down Expand Up @@ -77,12 +76,26 @@ public static function analyze(
$valid_int_type = Type::getInt(false, (int)$maybe_type->getSingleStringLiteral()->value);
}

if (count($maybe_type->getAtomicTypes()) === 1
&& $maybe_type->getSingleAtomic() instanceof Type\Atomic\TBool) {
$valid_int_type = new Union([
new TLiteralInt(0),
new TLiteralInt(1),
]);
if ($maybe_type->hasBool()) {
$casted_type = clone $maybe_type;
if (isset($casted_type->getAtomicTypes()['bool'])) {
$casted_type->addType(new TLiteralInt(0));
$casted_type->addType(new TLiteralInt(1));
} else {
if (isset($casted_type->getAtomicTypes()['true'])) {
$casted_type->addType(new TLiteralInt(1));
}
if (isset($casted_type->getAtomicTypes()['false'])) {
$casted_type->addType(new TLiteralInt(0));
}
}
$casted_type->removeType('bool');
$casted_type->removeType('true');
$casted_type->removeType('false');

if ($casted_type->isInt()) {
$valid_int_type = $casted_type;
}
}

if ($statements_analyzer->data_flow_graph instanceof VariableUseGraph) {
Expand Down
47 changes: 47 additions & 0 deletions tests/CastTest.php
@@ -0,0 +1,47 @@
<?php

namespace Psalm\Tests;

use Psalm\Tests\Traits\ValidCodeAnalysisTestTrait;

class CastTest extends TestCase
{
use ValidCodeAnalysisTestTrait;

/**
* @return iterable<string,array{code:string,assertions?:array<string,string>,ignored_issues?:list<string>,php_version?:string}>
*/
public function providerValidCodeParse(): iterable
{
yield 'castFalseOrIntToInt' => [
'code' => '<?php
/** @var false|int<10, 20> */
$intOrFalse = 10;
$int = (int) $intOrFalse;
',
'assertions' => [
'$int===' => '0|int<10, 20>',
],
];
yield 'castTrueOrIntToInt' => [
'code' => '<?php
/** @var true|int<10, 20> */
$intOrTrue = 10;
$int = (int) $intOrTrue;
',
'assertions' => [
'$int===' => '1|int<10, 20>',
],
];
yield 'castBoolOrIntToInt' => [
'code' => '<?php
/** @var bool|int<10, 20> */
$intOrBool = 10;
$int = (int) $intOrBool;
',
'assertions' => [
'$int===' => '0|1|int<10, 20>',
],
];
}
}

0 comments on commit 6a68287

Please sign in to comment.