From 2e50abd39357d95af3d6e3f9c622294092fd3939 Mon Sep 17 00:00:00 2001 From: Adrian Freund Date: Thu, 11 Mar 2021 15:50:30 +0100 Subject: [PATCH 1/2] Fix mypyc failing to compile on CPython 3.10.0a6 _PyObject_HasAttrId() has been removed in https://github.com/python/cpython/pull/22629 --- mypyc/lib-rt/dict_ops.c | 15 +++++++++++++-- mypyc/test-data/run-misc.test | 5 ++++- 2 files changed, 17 insertions(+), 3 deletions(-) diff --git a/mypyc/lib-rt/dict_ops.c b/mypyc/lib-rt/dict_ops.c index 1e635ada2c00..4ca7f84c129b 100644 --- a/mypyc/lib-rt/dict_ops.c +++ b/mypyc/lib-rt/dict_ops.c @@ -112,10 +112,16 @@ int CPyDict_Update(PyObject *dict, PyObject *stuff) { } int CPyDict_UpdateFromAny(PyObject *dict, PyObject *stuff) { + PyObject *tmp; + if (PyDict_CheckExact(dict)) { // Argh this sucks _Py_IDENTIFIER(keys); - if (PyDict_Check(stuff) || _PyObject_HasAttrId(stuff, &PyId_keys)) { + int hasAttr = PyDict_Check(stuff) || _PyObject_LookupAttrId(stuff, &PyId_keys, &tmp); + if (tmp) { + Py_DECREF(tmp); + } + if (hasAttr) { return PyDict_Update(dict, stuff); } else { return PyDict_MergeFromSeq2(dict, stuff, 1); @@ -126,6 +132,8 @@ int CPyDict_UpdateFromAny(PyObject *dict, PyObject *stuff) { } PyObject *CPyDict_FromAny(PyObject *obj) { + PyObject *tmp; + if (PyDict_Check(obj)) { return PyDict_Copy(obj); } else { @@ -135,11 +143,14 @@ PyObject *CPyDict_FromAny(PyObject *obj) { return NULL; } _Py_IDENTIFIER(keys); - if (_PyObject_HasAttrId(obj, &PyId_keys)) { + if (_PyObject_LookupAttrId(obj, &PyId_keys, &tmp)) { res = PyDict_Update(dict, obj); } else { res = PyDict_MergeFromSeq2(dict, obj, 1); } + if (tmp) { + Py_DECREF(tmp); + } if (res < 0) { Py_DECREF(dict); return NULL; diff --git a/mypyc/test-data/run-misc.test b/mypyc/test-data/run-misc.test index cc9ef444f31b..8b79949b55ad 100644 --- a/mypyc/test-data/run-misc.test +++ b/mypyc/test-data/run-misc.test @@ -940,7 +940,10 @@ import sys # We lie about the version we are running in tests if it is 3.5, so # that hits a crash case. -if sys.version_info[:2] == (3, 9): +if sys.version_info[:2] == (3, 10): + def version() -> int: + return 10 +elif sys.version_info[:2] == (3, 9): def version() -> int: return 9 elif sys.version_info[:2] == (3, 8): From 0b94195b98076a348a92d282fd3115273c47b446 Mon Sep 17 00:00:00 2001 From: Adrian Freund Date: Thu, 11 Mar 2021 17:46:32 +0100 Subject: [PATCH 2/2] Keep using _PyObject_HasAttrId when python version is too old We could potentionally already use _PyObject_LookupAttrId starting with python 3.7 instead of 3.10. I'm not sure if we should switch as soon or as late as possible. Alternatively we could also try backporting _PyObject_LookupAttrId to <3.7. --- mypyc/lib-rt/dict_ops.c | 15 ++------------- mypyc/lib-rt/pythonsupport.h | 14 ++++++++++++++ 2 files changed, 16 insertions(+), 13 deletions(-) diff --git a/mypyc/lib-rt/dict_ops.c b/mypyc/lib-rt/dict_ops.c index 4ca7f84c129b..4f831d0ba850 100644 --- a/mypyc/lib-rt/dict_ops.c +++ b/mypyc/lib-rt/dict_ops.c @@ -112,16 +112,10 @@ int CPyDict_Update(PyObject *dict, PyObject *stuff) { } int CPyDict_UpdateFromAny(PyObject *dict, PyObject *stuff) { - PyObject *tmp; - if (PyDict_CheckExact(dict)) { // Argh this sucks _Py_IDENTIFIER(keys); - int hasAttr = PyDict_Check(stuff) || _PyObject_LookupAttrId(stuff, &PyId_keys, &tmp); - if (tmp) { - Py_DECREF(tmp); - } - if (hasAttr) { + if (PyDict_Check(stuff) || _CPyObject_HasAttrId(stuff, &PyId_keys)) { return PyDict_Update(dict, stuff); } else { return PyDict_MergeFromSeq2(dict, stuff, 1); @@ -132,8 +126,6 @@ int CPyDict_UpdateFromAny(PyObject *dict, PyObject *stuff) { } PyObject *CPyDict_FromAny(PyObject *obj) { - PyObject *tmp; - if (PyDict_Check(obj)) { return PyDict_Copy(obj); } else { @@ -143,14 +135,11 @@ PyObject *CPyDict_FromAny(PyObject *obj) { return NULL; } _Py_IDENTIFIER(keys); - if (_PyObject_LookupAttrId(obj, &PyId_keys, &tmp)) { + if (_CPyObject_HasAttrId(obj, &PyId_keys)) { res = PyDict_Update(dict, obj); } else { res = PyDict_MergeFromSeq2(dict, obj, 1); } - if (tmp) { - Py_DECREF(tmp); - } if (res < 0) { Py_DECREF(dict); return NULL; diff --git a/mypyc/lib-rt/pythonsupport.h b/mypyc/lib-rt/pythonsupport.h index 864a1d152aa0..a8b00e168bb7 100644 --- a/mypyc/lib-rt/pythonsupport.h +++ b/mypyc/lib-rt/pythonsupport.h @@ -389,4 +389,18 @@ _CPyDictView_New(PyObject *dict, PyTypeObject *type) } #endif +#if PY_MAJOR_VERSION >= 3 && PY_MINOR_VERSION >=10 +static int +_CPyObject_HasAttrId(PyObject *v, _Py_Identifier *name) { + PyObject *tmp = NULL; + int result = _PyObject_LookupAttrId(v, name, &tmp); + if (tmp) { + Py_DECREF(tmp); + } + return result; +} +#else +#define _CPyObject_HasAttrId _PyObject_HasAttrId +#endif + #endif