Skip to content

Commit

Permalink
fixup! Improve abs() return type
Browse files Browse the repository at this point in the history
  • Loading branch information
julienfalque committed Jul 24, 2024
1 parent cd50c21 commit 6b99e0c
Show file tree
Hide file tree
Showing 2 changed files with 51 additions and 29 deletions.
44 changes: 24 additions & 20 deletions src/Type/Php/AbsFunctionDynamicReturnTypeExtension.php
Original file line number Diff line number Diff line change
Expand Up @@ -38,49 +38,53 @@ public function getTypeFromFunctionCall(
$type = $scope->getType($args[0]->value);

if ($type instanceof UnionType) {
$ranges = [];
$absUnionTypes = [];

foreach ($type->getTypes() as $unionType) {
if (
!$unionType instanceof ConstantIntegerType
&& !$unionType instanceof IntegerRangeType
&& !$unionType instanceof ConstantFloatType
) {
$absUnionType = $this->tryAbsType($unionType);

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

$absRange = $this->absType($unionType);

foreach ($ranges as $index => $range) {
if (!($range instanceof IntegerRangeType)) {
foreach ($absUnionTypes as $index => $otherAbsUnionType) {
if (!($otherAbsUnionType instanceof IntegerRangeType)) {
continue;
}

$unionRange = $range->tryUnion($absRange);
$unionRange = $otherAbsUnionType->tryUnion($absUnionType);

if ($unionRange !== null) {
$ranges[$index] = $unionRange;
$absUnionTypes[$index] = $unionRange;

continue 2;
}
}

$ranges[] = $absRange;
$absUnionTypes[] = $absUnionType;
}

if (count($ranges) === 1) {
return $ranges[0];
if (count($absUnionTypes) === 1) {
return $absUnionTypes[0];
}

return new UnionType($ranges);
return new UnionType($absUnionTypes);
}

return $this->tryAbsType($type);
}

private function tryAbsType(Type $type): ?Type
{
$numberType = $type->toNumber();

if (
$type instanceof ConstantIntegerType
|| $type instanceof IntegerRangeType
|| $type instanceof ConstantFloatType
$numberType instanceof IntegerRangeType
|| $numberType instanceof ConstantIntegerType
|| $numberType instanceof ConstantFloatType

) {
return $this->absType($type);
return $this->absType($numberType);
}

return null;
Expand Down
36 changes: 27 additions & 9 deletions tests/PHPStan/Analyser/nsrt/abs.php
Original file line number Diff line number Diff line change
Expand Up @@ -121,19 +121,37 @@ public function constantFloat(float $float): void
assertType('1.0', abs($float));
}

public function mixedUnion(float $float): void
public function string(string $string): void
{
/** @var 1.0|int<2, 3> $float */
assertType('1.0|int<2, 3>', abs($float));
/** @var string $string */
assertType('float|int<0, max>', abs($string));

/** @var -1.0|int<-3, -2> $float */
assertType('1.0|int<2, 3>', abs($float));
/** @var numeric-string $string */
assertType('float|int<0, max>', abs($string));

/** @var 2.0|int<1, 3> $float */
assertType('2.0|int<1, 3>', abs($float));
/** @var '-1' $string */
assertType('1', abs($string));

/** @var -2.0|int<-3, -1> $float */
assertType('2.0|int<1, 3>', abs($float));
/** @var '-1'|'-2.0'|'3.0'|'4' $string */
assertType('1|2.0|3.0|4', abs($string));
}

public function mixedUnion(mixed $value): void
{
/** @var 1.0|int<2, 3> $value */
assertType('1.0|int<2, 3>', abs($value));

/** @var -1.0|int<-3, -2> $value */
assertType('1.0|int<2, 3>', abs($value));

/** @var 2.0|int<1, 3> $value */
assertType('2.0|int<1, 3>', abs($value));

/** @var -2.0|int<-3, -1> $value */
assertType('2.0|int<1, 3>', abs($value));

/** @var -1.0|int<2, 3>|numeric-string $value */
assertType('float|int<0, max>', abs($value));
}

public function invalidType(mixed $nonInt): void
Expand Down

0 comments on commit 6b99e0c

Please sign in to comment.