🌐 US-Proxy
class="logged-out env-production page-responsive" style="word-wrap: break-word;" >
Skip to content

Internal error: abs(PHP_INT_MIN) #14946

Description

@zonuexe

Bug report

Analysing abs(PHP_INT_MIN) crashes with an internal error:

Internal error: PHPStan\Type\Constant\ConstantIntegerType::__construct():
Argument #1 ($value) must be of type int, float given,
called in src/Type/Constant/ConstantIntegerType.php on line 88

ConstantIntegerType::toAbsoluteNumber() does new self(abs($this->value)), but PHP's abs(PHP_INT_MIN) returns a float, because -PHP_INT_MIN is not representable as an int:

var_dump(abs(PHP_INT_MIN)); // float(9.2233720368548E+18)

Note that abs(-9223372036854775808) on the second line of the playground link does not crash — that literal is already a float, so it takes a different code path.

IntegerRangeType::toAbsoluteNumber() has the same problem in two places ($this->min * -1 and $this->max * -1), so these crash too:

/** @var int<-9223372036854775808, 0> $a */
abs($a);   // Internal error: IntegerRangeType::fromInterval(): Argument #2 ($max) must be of type ?int, float given

/** @var int<-9223372036854775808, -1> $b */
abs($b);   // same

/** @var int<min, -9223372036854775808> $c */
abs($c);   // Internal error: ... Argument #1 ($min) ...

Code snippet that reproduces the problem

https://phpstan.org/r/fa1c992f-684d-4abd-a6fc-b248b18180c6

Expected output

No internal error. abs(PHP_INT_MIN) should be inferred as a float:

\PHPStan\dumpType(abs(-9223372036854775807 - 1)); // 9.223372036854776E+18

For integer ranges, I would expect the existing approximation to be kept, so that a lower bound of PHP_INT_MIN behaves like an unbounded one (abs(int) is already int<0, max> today, and abs(int<min, 0>) is already int<0, max>):

/** @var int<-9223372036854775808, 0> $a */
\PHPStan\dumpType(abs($a));  // int<0, max>

/** @var int<-9223372036854775808, -1> $b */
\PHPStan\dumpType(abs($b));  // int<1, max>

int<min, -9223372036854775808> holds exactly one value, so abs() of it is that same float.

I have a fix ready and will open a PR right away.

Did PHPStan help you today? Did it make you happy in any way?

Yes — I found this while investigating how PHPStan models integer width, and PHPStan's own error messages pointed me straight at the offending line.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions