-
-
Notifications
You must be signed in to change notification settings - Fork 8.3k
Open
Labels
Description
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