mirror of
https://github.com/python/cpython.git
synced 2025-11-03 11:23:31 +00:00
bpo-43908: Immutable types inherit vectorcall (GH-27001)
Heap types with the Py_TPFLAGS_IMMUTABLETYPE flag can now inherit the PEP 590 vectorcall protocol. Previously, this was only possible for static types. Co-authored-by: Victor Stinner <vstinner@python.org>
This commit is contained in:
parent
15f0fc571c
commit
a3739b207a
5 changed files with 23 additions and 14 deletions
|
|
@ -710,7 +710,7 @@ and :c:type:`PyType_Type` effectively act as defaults.)
|
||||||
|
|
||||||
.. warning::
|
.. warning::
|
||||||
|
|
||||||
It is not recommended for :ref:`heap types <heap-types>` to implement
|
It is not recommended for :ref:`mutable heap types <heap-types>` to implement
|
||||||
the vectorcall protocol.
|
the vectorcall protocol.
|
||||||
When a user sets :attr:`__call__` in Python code, only *tp_call* is updated,
|
When a user sets :attr:`__call__` in Python code, only *tp_call* is updated,
|
||||||
likely making it inconsistent with the vectorcall function.
|
likely making it inconsistent with the vectorcall function.
|
||||||
|
|
@ -734,8 +734,9 @@ and :c:type:`PyType_Type` effectively act as defaults.)
|
||||||
always inherited. If it's not, then the subclass won't use
|
always inherited. If it's not, then the subclass won't use
|
||||||
:ref:`vectorcall <vectorcall>`, except when
|
:ref:`vectorcall <vectorcall>`, except when
|
||||||
:c:func:`PyVectorcall_Call` is explicitly called.
|
:c:func:`PyVectorcall_Call` is explicitly called.
|
||||||
This is in particular the case for :ref:`heap types <heap-types>`
|
This is in particular the case for types without the
|
||||||
(including subclasses defined in Python).
|
:const:`Py_TPFLAGS_IMMUTABLETYPE` flag set (including subclasses defined in
|
||||||
|
Python).
|
||||||
|
|
||||||
|
|
||||||
.. c:member:: getattrfunc PyTypeObject.tp_getattr
|
.. c:member:: getattrfunc PyTypeObject.tp_getattr
|
||||||
|
|
@ -1125,9 +1126,9 @@ and :c:type:`PyType_Type` effectively act as defaults.)
|
||||||
|
|
||||||
**Inheritance:**
|
**Inheritance:**
|
||||||
|
|
||||||
This flag is never inherited by :ref:`heap types <heap-types>`.
|
This flag is never inherited by types without the
|
||||||
For extension types, it is inherited whenever
|
:const:`Py_TPFLAGS_IMMUTABLETYPE` flag set. For extension types, it is
|
||||||
:c:member:`~PyTypeObject.tp_descr_get` is inherited.
|
inherited whenever :c:member:`~PyTypeObject.tp_descr_get` is inherited.
|
||||||
|
|
||||||
|
|
||||||
.. XXX Document more flags here?
|
.. XXX Document more flags here?
|
||||||
|
|
@ -1172,9 +1173,9 @@ and :c:type:`PyType_Type` effectively act as defaults.)
|
||||||
|
|
||||||
**Inheritance:**
|
**Inheritance:**
|
||||||
|
|
||||||
This bit is inherited for :ref:`static subtypes <static-types>` if
|
This bit is inherited for types with the
|
||||||
|
:const:`Py_TPFLAGS_IMMUTABLETYPE` flag set, if
|
||||||
:c:member:`~PyTypeObject.tp_call` is also inherited.
|
:c:member:`~PyTypeObject.tp_call` is also inherited.
|
||||||
:ref:`Heap types <heap-types>` do not inherit ``Py_TPFLAGS_HAVE_VECTORCALL``.
|
|
||||||
|
|
||||||
.. versionadded:: 3.9
|
.. versionadded:: 3.9
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -214,6 +214,11 @@ Porting to Python 3.11
|
||||||
(:c:member:`PyTypeObject.tp_traverse`).
|
(:c:member:`PyTypeObject.tp_traverse`).
|
||||||
(Contributed by Victor Stinner in :issue:`44263`.)
|
(Contributed by Victor Stinner in :issue:`44263`.)
|
||||||
|
|
||||||
|
* Heap types with the :const:`Py_TPFLAGS_IMMUTABLETYPE` flag can now inherit
|
||||||
|
the :pep:`590` vectorcall protocol. Previously, this was only possible for
|
||||||
|
:ref:`static types <static-types>`.
|
||||||
|
(Contributed by Erlend E. Aasland in :issue:`43908`)
|
||||||
|
|
||||||
Deprecated
|
Deprecated
|
||||||
----------
|
----------
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -563,7 +563,7 @@ class TestPEP590(unittest.TestCase):
|
||||||
self.assertTrue(_testcapi.MethodDescriptorDerived.__flags__ & Py_TPFLAGS_METHOD_DESCRIPTOR)
|
self.assertTrue(_testcapi.MethodDescriptorDerived.__flags__ & Py_TPFLAGS_METHOD_DESCRIPTOR)
|
||||||
self.assertFalse(_testcapi.MethodDescriptorNopGet.__flags__ & Py_TPFLAGS_METHOD_DESCRIPTOR)
|
self.assertFalse(_testcapi.MethodDescriptorNopGet.__flags__ & Py_TPFLAGS_METHOD_DESCRIPTOR)
|
||||||
|
|
||||||
# Heap type should not inherit Py_TPFLAGS_METHOD_DESCRIPTOR
|
# Mutable heap types should not inherit Py_TPFLAGS_METHOD_DESCRIPTOR
|
||||||
class MethodDescriptorHeap(_testcapi.MethodDescriptorBase):
|
class MethodDescriptorHeap(_testcapi.MethodDescriptorBase):
|
||||||
pass
|
pass
|
||||||
self.assertFalse(MethodDescriptorHeap.__flags__ & Py_TPFLAGS_METHOD_DESCRIPTOR)
|
self.assertFalse(MethodDescriptorHeap.__flags__ & Py_TPFLAGS_METHOD_DESCRIPTOR)
|
||||||
|
|
@ -574,7 +574,7 @@ class TestPEP590(unittest.TestCase):
|
||||||
self.assertFalse(_testcapi.MethodDescriptorNopGet.__flags__ & Py_TPFLAGS_HAVE_VECTORCALL)
|
self.assertFalse(_testcapi.MethodDescriptorNopGet.__flags__ & Py_TPFLAGS_HAVE_VECTORCALL)
|
||||||
self.assertTrue(_testcapi.MethodDescriptor2.__flags__ & Py_TPFLAGS_HAVE_VECTORCALL)
|
self.assertTrue(_testcapi.MethodDescriptor2.__flags__ & Py_TPFLAGS_HAVE_VECTORCALL)
|
||||||
|
|
||||||
# Heap type should not inherit Py_TPFLAGS_HAVE_VECTORCALL
|
# Mutable heap types should not inherit Py_TPFLAGS_HAVE_VECTORCALL
|
||||||
class MethodDescriptorHeap(_testcapi.MethodDescriptorBase):
|
class MethodDescriptorHeap(_testcapi.MethodDescriptorBase):
|
||||||
pass
|
pass
|
||||||
self.assertFalse(MethodDescriptorHeap.__flags__ & Py_TPFLAGS_HAVE_VECTORCALL)
|
self.assertFalse(MethodDescriptorHeap.__flags__ & Py_TPFLAGS_HAVE_VECTORCALL)
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,3 @@
|
||||||
|
Heap types with the :const:`Py_TPFLAGS_IMMUTABLETYPE` flag can now inherit the
|
||||||
|
:pep:`590` vectorcall protocol. Previously, this was only possible for
|
||||||
|
:ref:`static types <static-types>`. Patch by Erlend E. Aasland.
|
||||||
|
|
@ -5881,8 +5881,8 @@ inherit_slots(PyTypeObject *type, PyTypeObject *base)
|
||||||
/* Inherit Py_TPFLAGS_HAVE_VECTORCALL for non-heap types
|
/* Inherit Py_TPFLAGS_HAVE_VECTORCALL for non-heap types
|
||||||
* if tp_call is not overridden */
|
* if tp_call is not overridden */
|
||||||
if (!type->tp_call &&
|
if (!type->tp_call &&
|
||||||
(base->tp_flags & Py_TPFLAGS_HAVE_VECTORCALL) &&
|
_PyType_HasFeature(base, Py_TPFLAGS_HAVE_VECTORCALL) &&
|
||||||
!(type->tp_flags & Py_TPFLAGS_HEAPTYPE))
|
_PyType_HasFeature(type, Py_TPFLAGS_IMMUTABLETYPE))
|
||||||
{
|
{
|
||||||
type->tp_flags |= Py_TPFLAGS_HAVE_VECTORCALL;
|
type->tp_flags |= Py_TPFLAGS_HAVE_VECTORCALL;
|
||||||
}
|
}
|
||||||
|
|
@ -5915,8 +5915,8 @@ inherit_slots(PyTypeObject *type, PyTypeObject *base)
|
||||||
* but only for extension types */
|
* but only for extension types */
|
||||||
if (base->tp_descr_get &&
|
if (base->tp_descr_get &&
|
||||||
type->tp_descr_get == base->tp_descr_get &&
|
type->tp_descr_get == base->tp_descr_get &&
|
||||||
!(type->tp_flags & Py_TPFLAGS_HEAPTYPE) &&
|
_PyType_HasFeature(type, Py_TPFLAGS_IMMUTABLETYPE) &&
|
||||||
(base->tp_flags & Py_TPFLAGS_METHOD_DESCRIPTOR))
|
_PyType_HasFeature(base, Py_TPFLAGS_METHOD_DESCRIPTOR))
|
||||||
{
|
{
|
||||||
type->tp_flags |= Py_TPFLAGS_METHOD_DESCRIPTOR;
|
type->tp_flags |= Py_TPFLAGS_METHOD_DESCRIPTOR;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue