Skip to content

Narrow intdiv() return type from integer ranges - #6925

Merged
ondrejmirtes merged 1 commit into
2.3.xfrom
intdiv-return-type
Nov 3, 2026
Merged

ondrejmirtes merged 1 commit into
2.3.xfrom
intdiv-return-type

Conversation

@ondrejmirtes

Copy link
Copy Markdown
Member

intdiv() always returned int, because the only extension for it described what it throws. This adds IntdivFunctionReturnTypeExtension, which derives the result range from the integer ranges of both arguments.

  • The divisor is split into its negative and positive parts; zero is dropped because dividing by it throws.
  • For each numerator × divisor part, real intdiv() is evaluated at the four corners. Truncated division is monotonic in both operands while the divisor keeps one sign, so the corners give the exact bounds. Unbounded ends are handled as ±INF.
  • Union members are kept separate, e.g. intdiv(3|int<10, 12>, 2) is 1|int<5, 6>.
  • / logic in InitializerExprTypeResolver is not reused: it rounds bounds inwards (int<1, 5> / 2 → int<1, 2>|float), while intdiv() truncates towards zero (int<0, 2>).

Examples: intdiv(int<0, max>, int<1, max>) → int<0, max>, intdiv(int<-7, -1>, 2) → int<-3, 0>, intdiv(7, 2) → 3.

Verified against brute-force intdiv() over 5,041 range pairs: every result is contained, and for bounded ranges the bounds are exact.

Closes phpstan/phpstan#15282
Closes phpstan/phpstan#15347

@ondrejmirtes
ondrejmirtes merged commit 59c0233 into 2.3.x Nov 3, 2026
592 of 593 checks passed
@ondrejmirtes
ondrejmirtes deleted the intdiv-return-type branch November 3, 2026 15:21
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Provide refined type for the int range returned by intdiv Narrow intdiv() return type when both arguments are non-negative

1 participant