GV

GeezerVison

The World Wide Web, restored to 800 pixels of glory.

Home|About|Gaming cabinet|Archives|How it works|Starter sites

On this site

  • Sign in
  • ActionsCI/CD and automation
  • CodespacesCloud development environments
  • All Features
  • Documentation
  • Training
  • Certifications
  • Build with Copilot
  • Customize Copilot
  • Integrations
  • Trending repos
  • GitHub Sponsors
  • Developer articles
  • Enterprises

This view

  • Original page
  • New address

GeezerVison is showing github.com — [mypyc] Fix int subclass crashes and precision of int true division and float/int comparisons by Jahongir-Qurbonov · Pull Request #22418 · python/mypy

Conversation

@Jahongir-Qurbonov

@Jahongir-Qurbonov Jahongir-Qurbonov commented Nov 9, 2026

Copy link
Copy Markdown
Contributor

This fixes three related bugs in int/float primitives.

1. Crashes with large int subclass values. When an int value doesn't fit in a short int, unboxing keeps the original object, so a long tagged int can be an instance of an int subclass. The slow paths of int operations used PyNumber_* / PyObject_RichCompareBool, which call dunders the subclass overrides:

# sub.py (not compiled)
class Str(int):
    def __sub__(self, o): return 1.5
    def __eq__(self, o): raise RuntimeError()

# compiled
def sub(a: int, b: int) -> int: return a - b
def eq(a: int, b: int) -> bool: return a == b

sub(Str(2**70), 2**70)  # segfault (float read as an int object)
eq(Str(2**70), 2**70)   # "fatal: out of memory", process aborts

Small values never call the overrides. The slow paths now first convert operands to exact ints using int's own nb_int slot, so no overrides are called. Normalizing at unboxing time isn't possible, because wrapper functions and attribute setters borrow the argument. CPyTagged_TrueDivide now also checks for errors from PyFloat_AsDouble.

2. int / int was not correctly rounded for operands larger than 2**53. For example, (2**53 + 1) / 3 gave 3002399751580330.5 instead of 3002399751580331.0. The double fast path is now only used if both operands fit in 53 bits, as in CPython.

3. float vs int comparisons converted the int to a float. 2.0**53 == 2**53 + 1 was True, and 1.0 < 2**1100 raised OverflowError. Comparisons now use a new CPyFloat_CompareTagged primitive. It compares as doubles only if the int fits in 53 bits; otherwise it falls back to a rich comparison. Int literals are still converted at compile time when the conversion is exact. Arithmetic is unchanged.

Added run tests for all three, and irbuild tests for the comparisons.

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

All reactions
Jahongir-Qurbonov added 4 commits November 9, 2026 15:41
@Jahongir-Qurbonov
[mypyc] Fix crashes with big int subclass values that override dunders
3f83f68
Unboxing an int keeps the original object when the value doesn't fit in
a short int, so a long tagged int can refer to an instance of an int
subclass. The slow paths of int operations used the generic PyNumber_*
and rich comparison APIs, which call any dunder methods the subclass
overrides. A non-int result was then read as an int object (crash or
garbage), and an exception in an operation that can't fail aborted the
process with "fatal: out of memory".

Convert operands to exact int objects in the slow paths, using int's own
nb_int slot so that no overrides are called. This matches the behavior
for small values, which never call the overrides. Also check for errors
from PyFloat_AsDouble in CPyTagged_TrueDivide.
@Jahongir-Qurbonov
[mypyc] Fix rounding of int / int with operands larger than 2**53
6740825
The fast path of int true division converted short int operands to
doubles before dividing, which rounds twice if an operand can't be
represented exactly as a double. For example, (2**53 + 1) / 3 returned
3002399751580330.5 instead of 3002399751580331.0.

Only use the fast path if the absolute values of both operands are at
most 2**53 (like CPython), and otherwise fall back to the int object
implementation, which is correctly rounded.
@Jahongir-Qurbonov
[mypyc] Fix float vs int comparisons with ints not exact as floats
d611f8a
Comparisons between float and int converted the int to a double first,
which loses precision for ints with an absolute value larger than 2**53
and raises OverflowError for very large ints. For example,
2.0**53 == 2**53 + 1 was True, and 1.0 < 2**1100 raised OverflowError.
CPython compares the values exactly.

Use a new primitive CPyFloat_CompareTagged for these comparisons. It
compares as doubles if the int is a short int that fits in 53 bits, and
otherwise falls back to a rich comparison of the boxed values. Int
literals are still converted to float at compile time if the conversion
is exact. Arithmetic operations are unchanged.
@Jahongir-Qurbonov
Only run float/int comparison IR test on 64-bit platforms
a60e935
Int literals such as 2**53 don't fit in a short int on 32-bit platforms, so the generated IR is different.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Reviewers

No reviews

Uh oh!

There was an error while loading. Please reload this page.

Assignees

No one assigned

Labels

None yet

Projects

None yet

Milestone

No milestone

Development

Successfully merging this pull request may close these issues.

Uh oh!

There was an error while loading. Please reload this page.

1 participant

@Jahongir-Qurbonov
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
You are visitor 01402503 — GeezerVison does not store the pages you look up.
Best viewed with Netscape Navigator 4.7 or Internet Explorer 6 at 800×600. No cookies required.