bpo-1617161: Make the hash and equality of methods not depending on the value of self. (GH-7848)

* The hash of BuiltinMethodType instances no longer depends on the hash
  of __self__. It depends now on the hash of id(__self__).
* The hash and equality of ModuleType and MethodWrapperType instances no
  longer depend on the hash and equality of __self__. They depend now on
  the hash and equality of id(__self__).
* MethodWrapperType instances no longer support ordering.
This commit is contained in:
Serhiy Storchaka 2018-07-31 09:18:24 +03:00 committed by GitHub
parent c48e26dcad
commit ac20e0f98d
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
6 changed files with 112 additions and 73 deletions

View file

@ -1038,38 +1038,35 @@ wrapper_dealloc(wrapperobject *wp)
static PyObject *
wrapper_richcompare(PyObject *a, PyObject *b, int op)
{
PyWrapperDescrObject *a_descr, *b_descr;
wrapperobject *wa, *wb;
int eq;
assert(a != NULL && b != NULL);
/* both arguments should be wrapperobjects */
if (!Wrapper_Check(a) || !Wrapper_Check(b)) {
if ((op != Py_EQ && op != Py_NE)
|| !Wrapper_Check(a) || !Wrapper_Check(b))
{
Py_RETURN_NOTIMPLEMENTED;
}
/* compare by descriptor address; if the descriptors are the same,
compare by the objects they're bound to */
a_descr = ((wrapperobject *)a)->descr;
b_descr = ((wrapperobject *)b)->descr;
if (a_descr == b_descr) {
a = ((wrapperobject *)a)->self;
b = ((wrapperobject *)b)->self;
return PyObject_RichCompare(a, b, op);
wa = (wrapperobject *)a;
wb = (wrapperobject *)b;
eq = (wa->descr == wb->descr && wa->self == wb->self);
if (eq == (op == Py_EQ)) {
Py_RETURN_TRUE;
}
else {
Py_RETURN_FALSE;
}
Py_RETURN_RICHCOMPARE(a_descr, b_descr, op);
}
static Py_hash_t
wrapper_hash(wrapperobject *wp)
{
Py_hash_t x, y;
x = _Py_HashPointer(wp->descr);
if (x == -1)
return -1;
y = PyObject_Hash(wp->self);
if (y == -1)
return -1;
x = _Py_HashPointer(wp->self);
y = _Py_HashPointer(wp->descr);
x = x ^ y;
if (x == -1)
x = -2;