-
-
Notifications
You must be signed in to change notification settings - Fork 31.9k
Caching/interning of small ints sometimes fails #91117
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Comments
I'm reluctant to call this a bug, as small int interning/caching is an implementation detail and there are no hard guarantees made. But on the other hand, it seems that the intention is that small ints such as 0, 1 and 2 should be cached. Here are some examples where they are not. Intentional or a bug? >>> x = 1
>>> y = pow(2, 31, 2**31-1)
>>> y == x
True
>>> y is x
False
>>> x = 2
>>> y = pow(2, 31, 2**31-2)
>>> y == x
True
>>> y is x
False It also affects values which are presumably constant-folded at compile time: >>> x = 1
>>> y = 2**31 % (2**31 - 1)
>>> z = 2**31 % (2**31 - 1)
>>> x == y == z
True
>>> x is y
False
>>> y is z
False
>>> x is z
False But if you run the code in exec, the value is interned: >>> code = """
... x = 1
... y = 2**31 % (2**31-1)
... """
>>> dis(code)
2 0 LOAD_CONST 0 (1)
2 STORE_NAME 0 (x)
3 4 LOAD_CONST 0 (1)
6 STORE_NAME 1 (y)
8 LOAD_CONST 1 (None)
10 RETURN_VALUE
>>> exec(code)
>>> x is y
True Also affects zero: >>> x = 0
>>> y = 2**29 % (2**29)
>>> x is y
True
>>> y = 2**30 % (2**30)
>>> x is y
False First noted here: https://discuss.python.org/t/cached-integer-id-on-high-calculations/14128/1 >>> sys.version
'3.10.0 (default, Oct 28 2021, 20:43:43) [GCC 8.3.1 20190223 (Red Hat 8.3.1-2)]' |
I think this might be a duplicate of bpo-46361? |
Related, except this seems to be happening in long_pow. I’ll take a look at it today. |
I believe the issue is the usage of the x_divrem function. x_divrem always returns fresh ints, never cached small ints. This behavior is relied upon in the long_true_divide function, as it mutates the returned quotient at the line """x->ob_digit[0] = low & ~(2U*mask-1U);""". The other uses of x_divrem account for this when handling the *quotient*, but apparently missed checking for small ints in the *remainder*. uses of x_divrem: Possible patches to fix it:
I'd lean towards #1, since that quotient check already exists. |
Note: these values reflect the state of the issue at the time it was migrated and might not reflect the current state.
Show more details
GitHub fields:
bugs.python.org fields:
The text was updated successfully, but these errors were encountered: