← index #17730PR #17785
Duplicate · high · value 4.767
QUERY · ISSUE

code paths that return large ints where small ints would suffice

openby jepleropened 2025-07-21updated 2025-07-21
bugpy-core

Port, board and/or hardware

unix, standard variant, 32 bit

MicroPython version

MicroPython v1.26.0-preview.387.g67acac257f.dirty on 2025-07-21; linux [GCC 12.2.0] version

Reproduction

3-arg pow always returns long ints

>>> i = pow(3,3,3)
>>> i
0
>>> i is 0
False
>>> id(i)
4155902608

anything using the code paths for 'Q' type codes:

>>> i = array.array('Q', [0])[0]
>>> i
0
>>> id(i)
4155903568

Interestingly, the latter doesn't even behave as a zero in some ways (it has 4 digits):

$5 = {neg = 0, fixed_dig = 0, alloc = 4, len = 0, dig = 0xf7b60b80}
(gdb) p mod->dig[0]
$6 = 0
(gdb) p mod->dig[1]
$7 = 0
(gdb) p mod->dig[2]
$8 = 0
(gdb) p mod->dig[3]
$9 = 0

so this will hang indefinitely:

pow(3,3,i)

Expected behaviour

As I understood it, the invariant is supposed to be that if an integer value fits in a small int, it MUST be returned to Python as a small int.

Observed behaviour

In these code paths (and possibly others) there's the possibility for these values to be returned as long ints instead

Additional Information

I discovered this while implementing review comments for #17716, because I noticed a comment that said

        mp_obj_t result = mp_obj_new_int_from_ull(0); // Use the _from_ull version as this forces an mpz int

Code of Conduct

Yes, I agree

CANDIDATE · PULL REQUEST

Fix more operations that can return small ints

openby jepleropened 2025-07-29updated 2025-12-26
py-core

Summary

#17730 identified some code paths that could still return long ints when small ints would suffice. Fix them.

Testing

I wrote a new test based on sites that called new_int_from_{u,}ll, including the case I'd noticed of pow3 (already reported in #9531 as well).

Trade-offs and Alternatives

I haven't seen the code size change summary yet, but this is likely to increase code size. I'm open to suggestions about how to reduce the increase.

Making the new long_from functions always return longs, and changing the existing new_int_from functions to return ints when possible is just one alternative. Another alternative would be to add calls to mp_int_maybe_narrow in paths that used new_int_from, but this seemed like the worse alternative, with more added code.

Keyboard

j / / n
next pair
k / / p
previous pair
1 / / h
show query pane
2 / / l
show candidate pane
c
copy suggested comment
r
toggle reasoning
g i
go to index
?
show this help
esc
close overlays

press ? or esc to close

copied