Skip to content

Commit

Permalink
Fix arithmetic operations with BenevolentUnionType
Browse files Browse the repository at this point in the history
  • Loading branch information
ondrejmirtes committed Feb 25, 2023
1 parent 7abcc51 commit f882eff
Show file tree
Hide file tree
Showing 3 changed files with 69 additions and 2 deletions.
26 changes: 24 additions & 2 deletions src/Type/UnionType.php
Expand Up @@ -735,12 +735,12 @@ public function isConstantScalarValue(): TrinaryLogic

public function getConstantScalarTypes(): array
{
return $this->pickFromTypes(static fn (Type $type) => $type->getConstantScalarTypes());
return $this->notBenevolentPickFromTypes(static fn (Type $type) => $type->getConstantScalarTypes());
}

public function getConstantScalarValues(): array
{
return $this->pickFromTypes(static fn (Type $type) => $type->getConstantScalarValues());
return $this->notBenevolentPickFromTypes(static fn (Type $type) => $type->getConstantScalarValues());
}

public function isTrue(): TrinaryLogic
Expand Down Expand Up @@ -1008,4 +1008,26 @@ protected function pickFromTypes(callable $getValues): array
return $values;
}

/**
* @template T
* @param callable(Type $type): list<T> $getValues
* @return list<T>
*/
private function notBenevolentPickFromTypes(callable $getValues): array
{
$values = [];
foreach ($this->types as $type) {
$innerValues = $getValues($type);
if ($innerValues === []) {
return [];
}

foreach ($innerValues as $innerType) {
$values[] = $innerType;
}
}

return $values;
}

}
1 change: 1 addition & 0 deletions tests/PHPStan/Analyser/NodeScopeResolverTest.php
Expand Up @@ -1201,6 +1201,7 @@ public function dataFileAsserts(): iterable
yield from $this->gatherAssertTypes(__DIR__ . '/data/list-shapes.php');
yield from $this->gatherAssertTypes(__DIR__ . '/data/bug-7607.php');
yield from $this->gatherAssertTypes(__DIR__ . '/data/ibm_db2.php');
yield from $this->gatherAssertTypes(__DIR__ . '/data/benevolent-union-math.php');
}

/**
Expand Down
44 changes: 44 additions & 0 deletions tests/PHPStan/Analyser/data/benevolent-union-math.php
@@ -0,0 +1,44 @@
<?php

namespace BenevolentUnionMath;

use function PHPStan\Testing\assertType;
use function strtotime;

class Foo
{

public function doFoo($s, $r)
{
$timeS = strtotime($s);
assertType('(int|false)', $timeS);

$timeR = strtotime($r);
assertType('(int|false)', $timeR);

assertType('int', $timeS - $timeR);
}

}

class HelloWorld
{
public function sayHello(int $x): void
{
$dbresponse = $this->getBenevolent();
assertType('array<string, (float|int|string|null)>|null', $dbresponse);

if ($dbresponse === null) {return;}

assertType('array<string, (float|int|string|null)>', $dbresponse);
assertType('(float|int|string|null)', $dbresponse['Value']);
assertType('int<0, max>', strlen($dbresponse['Value']));
}

/**
* @return array<string, __benevolent<float|int|string|null>>|null
*/
private function getBenevolent(): ?array{
return rand(10) > 1 ? null : [];
}
}

0 comments on commit f882eff

Please sign in to comment.