mirror of
				https://github.com/python/cpython.git
				synced 2025-10-30 21:21:22 +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
	
	 Victor Stinner
						Victor Stinner