summaryrefslogtreecommitdiff
path: root/Objects
diff options
context:
space:
mode:
authorMiss Islington (bot) <31488909+miss-islington@users.noreply.github.com>2019-05-26 15:14:23 -0700
committerGitHub <noreply@github.com>2019-05-26 15:14:23 -0700
commitbfd0b7720196b9ff647cc33dafbd31a04496402c (patch)
tree27624afe606c757cdcee2f074226031b85e1b8a7 /Objects
parentf3d909428c7c61ea32e8fbb9c8b48344e7904a53 (diff)
downloadcpython-git-bfd0b7720196b9ff647cc33dafbd31a04496402c.tar.gz
[3.7] bpo-28866: No type cache for types with specialized mro, invalidation is hard. (GH-13157) (GH-13589)
* No type cache for types with specialized mro, invalidation is hard. * FIX: Don't disable method cache custom types that do not implement mro(). * fixing implem. * Avoid storing error flags, also decref. * news entry * Clear as soon as we're getting an error. * FIX: Reference leak. (cherry picked from commit 180dc1b0f4a57c3f66351568ae8488fa8576d7f0) Co-authored-by: Julien Palard <julien@palard.fr> https://bugs.python.org/issue28866
Diffstat (limited to 'Objects')
-rw-r--r--Objects/typeobject.c38
1 files changed, 30 insertions, 8 deletions
diff --git a/Objects/typeobject.c b/Objects/typeobject.c
index 8adae49a7f..9dba45ac6f 100644
--- a/Objects/typeobject.c
+++ b/Objects/typeobject.c
@@ -77,6 +77,9 @@ slot_tp_new(PyTypeObject *type, PyObject *args, PyObject *kwds);
static void
clear_slotdefs(void);
+static PyObject *
+lookup_maybe_method(PyObject *self, _Py_Identifier *attrid, int *unbound);
+
/*
* finds the beginning of the docstring's introspection signature.
* if present, returns a pointer pointing to the first '('.
@@ -281,17 +284,35 @@ type_mro_modified(PyTypeObject *type, PyObject *bases) {
Unset HAVE_VERSION_TAG and VALID_VERSION_TAG if the type
has a custom MRO that includes a type which is not officially
- super type.
+ super type, or if the type implements its own mro() method.
Called from mro_internal, which will subsequently be called on
each subclass when their mro is recursively updated.
*/
Py_ssize_t i, n;
- int clear = 0;
+ int custom = (Py_TYPE(type) != &PyType_Type);
+ int unbound;
+ PyObject *mro_meth = NULL;
+ PyObject *type_mro_meth = NULL;
if (!PyType_HasFeature(type, Py_TPFLAGS_HAVE_VERSION_TAG))
return;
+ if (custom) {
+ _Py_IDENTIFIER(mro);
+ mro_meth = lookup_maybe_method(
+ (PyObject *)type, &PyId_mro, &unbound);
+ if (mro_meth == NULL)
+ goto clear;
+ type_mro_meth = lookup_maybe_method(
+ (PyObject *)&PyType_Type, &PyId_mro, &unbound);
+ if (type_mro_meth == NULL)
+ goto clear;
+ if (mro_meth != type_mro_meth)
+ goto clear;
+ Py_XDECREF(mro_meth);
+ Py_XDECREF(type_mro_meth);
+ }
n = PyTuple_GET_SIZE(bases);
for (i = 0; i < n; i++) {
PyObject *b = PyTuple_GET_ITEM(bases, i);
@@ -302,14 +323,15 @@ type_mro_modified(PyTypeObject *type, PyObject *bases) {
if (!PyType_HasFeature(cls, Py_TPFLAGS_HAVE_VERSION_TAG) ||
!PyType_IsSubtype(type, cls)) {
- clear = 1;
- break;
+ goto clear;
}
}
-
- if (clear)
- type->tp_flags &= ~(Py_TPFLAGS_HAVE_VERSION_TAG|
- Py_TPFLAGS_VALID_VERSION_TAG);
+ return;
+ clear:
+ Py_XDECREF(mro_meth);
+ Py_XDECREF(type_mro_meth);
+ type->tp_flags &= ~(Py_TPFLAGS_HAVE_VERSION_TAG|
+ Py_TPFLAGS_VALID_VERSION_TAG);
}
static int