mirror of
https://github.com/python/cpython.git
synced 2025-08-04 00:48:58 +00:00
code_richcompare() now uses the constants types
Issue #25843: When compiling code, don't merge constants if they are equal but have a different types. For example, "f1, f2 = lambda: 1, lambda: 1.0" is now correctly compiled to two different functions: f1() returns 1 (int) and f2() returns 1.0 (int), even if 1 and 1.0 are equal. Add a new _PyCode_ConstantKey() private function.
This commit is contained in:
parent
e3560a7dc9
commit
efb2413ce8
5 changed files with 245 additions and 49 deletions
|
@ -393,7 +393,7 @@ list2dict(PyObject *list)
|
|||
return NULL;
|
||||
}
|
||||
k = PyList_GET_ITEM(list, i);
|
||||
k = PyTuple_Pack(2, k, k->ob_type);
|
||||
k = _PyCode_ConstantKey(k);
|
||||
if (k == NULL || PyDict_SetItem(dict, k, v) < 0) {
|
||||
Py_XDECREF(k);
|
||||
Py_DECREF(v);
|
||||
|
@ -456,7 +456,7 @@ dictbytype(PyObject *src, int scope_type, int flag, Py_ssize_t offset)
|
|||
return NULL;
|
||||
}
|
||||
i++;
|
||||
tuple = PyTuple_Pack(2, k, k->ob_type);
|
||||
tuple = _PyCode_ConstantKey(k);
|
||||
if (!tuple || PyDict_SetItem(dest, tuple, item) < 0) {
|
||||
Py_DECREF(sorted_keys);
|
||||
Py_DECREF(item);
|
||||
|
@ -559,7 +559,7 @@ compiler_enter_scope(struct compiler *c, identifier name,
|
|||
compiler_unit_free(u);
|
||||
return 0;
|
||||
}
|
||||
tuple = PyTuple_Pack(2, name, Py_TYPE(name));
|
||||
tuple = _PyCode_ConstantKey(name);
|
||||
if (!tuple) {
|
||||
compiler_unit_free(u);
|
||||
return 0;
|
||||
|
@ -1105,47 +1105,8 @@ compiler_add_o(struct compiler *c, PyObject *dict, PyObject *o)
|
|||
{
|
||||
PyObject *t, *v;
|
||||
Py_ssize_t arg;
|
||||
double d;
|
||||
|
||||
/* necessary to make sure types aren't coerced (e.g., float and complex) */
|
||||
/* _and_ to distinguish 0.0 from -0.0 e.g. on IEEE platforms */
|
||||
if (PyFloat_Check(o)) {
|
||||
d = PyFloat_AS_DOUBLE(o);
|
||||
/* all we need is to make the tuple different in either the 0.0
|
||||
* or -0.0 case from all others, just to avoid the "coercion".
|
||||
*/
|
||||
if (d == 0.0 && copysign(1.0, d) < 0.0)
|
||||
t = PyTuple_Pack(3, o, o->ob_type, Py_None);
|
||||
else
|
||||
t = PyTuple_Pack(2, o, o->ob_type);
|
||||
}
|
||||
else if (PyComplex_Check(o)) {
|
||||
Py_complex z;
|
||||
int real_negzero, imag_negzero;
|
||||
/* For the complex case we must make complex(x, 0.)
|
||||
different from complex(x, -0.) and complex(0., y)
|
||||
different from complex(-0., y), for any x and y.
|
||||
All four complex zeros must be distinguished.*/
|
||||
z = PyComplex_AsCComplex(o);
|
||||
real_negzero = z.real == 0.0 && copysign(1.0, z.real) < 0.0;
|
||||
imag_negzero = z.imag == 0.0 && copysign(1.0, z.imag) < 0.0;
|
||||
if (real_negzero && imag_negzero) {
|
||||
t = PyTuple_Pack(5, o, o->ob_type,
|
||||
Py_None, Py_None, Py_None);
|
||||
}
|
||||
else if (imag_negzero) {
|
||||
t = PyTuple_Pack(4, o, o->ob_type, Py_None, Py_None);
|
||||
}
|
||||
else if (real_negzero) {
|
||||
t = PyTuple_Pack(3, o, o->ob_type, Py_None);
|
||||
}
|
||||
else {
|
||||
t = PyTuple_Pack(2, o, o->ob_type);
|
||||
}
|
||||
}
|
||||
else {
|
||||
t = PyTuple_Pack(2, o, o->ob_type);
|
||||
}
|
||||
t = _PyCode_ConstantKey(o);
|
||||
if (t == NULL)
|
||||
return -1;
|
||||
|
||||
|
@ -1459,7 +1420,7 @@ static int
|
|||
compiler_lookup_arg(PyObject *dict, PyObject *name)
|
||||
{
|
||||
PyObject *k, *v;
|
||||
k = PyTuple_Pack(2, name, name->ob_type);
|
||||
k = _PyCode_ConstantKey(name);
|
||||
if (k == NULL)
|
||||
return -1;
|
||||
v = PyDict_GetItem(dict, k);
|
||||
|
@ -4657,9 +4618,10 @@ dict_keys_inorder(PyObject *dict, Py_ssize_t offset)
|
|||
return NULL;
|
||||
while (PyDict_Next(dict, &pos, &k, &v)) {
|
||||
i = PyLong_AS_LONG(v);
|
||||
/* The keys of the dictionary are tuples. (see compiler_add_o)
|
||||
The object we want is always first, though. */
|
||||
k = PyTuple_GET_ITEM(k, 0);
|
||||
/* The keys of the dictionary are tuples. (see compiler_add_o
|
||||
* and _PyCode_ConstantKey). The object we want is always second,
|
||||
* though. */
|
||||
k = PyTuple_GET_ITEM(k, 1);
|
||||
Py_INCREF(k);
|
||||
assert((i - offset) < size);
|
||||
assert((i - offset) >= 0);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue