Commit d8f4fed0 authored by da-woods's avatar da-woods Committed by GitHub

Fix .__class__() calls on builtin types (GH-3956)

Fixes https://github.com/cython/cython/issues/3954

The problem seems to be that __Pyx_CallUnboundCMethod0 optimizes the call incorrectly. This patch avoids it getting sent to that mechanism.
parent 8e3a0a42
......@@ -3012,6 +3012,13 @@ class OptimizeBuiltinCalls(Visitor.NodeRefCleanupMixin,
is_temp=node.is_temp
)
def _handle_any_slot__class__(self, node, function, args,
is_unbound_method, kwargs=None):
# The purpose of this function is to handle calls to instance.__class__() so that
# it doesn't get handled by the __Pyx_CallUnboundCMethod0 mechanism.
# TODO: optimizations of the instance.__class__() call might be possible in future.
return node
### methods of builtin types
PyObject_Append_func_type = PyrexTypes.CFuncType(
......
......@@ -674,7 +674,7 @@ class MethodDispatcherTransform(EnvTransform):
"method_%s_%s" % (type_name, attr_name), kwargs)
if method_handler is None:
if (attr_name in TypeSlots.method_name_to_slot
or attr_name == '__new__'):
or attr_name in ['__new__', '__class__']):
method_handler = self._find_handler(
"slot%s" % attr_name, kwargs)
if method_handler is None:
......
# mode: run
from __future__ import print_function
import cython
# https://github.com/cython/cython/issues/3954
# calls to the __class__ attributes of builtin types were optimized to something invalid
@cython.locals(d=dict)
def test_dict(d):
"""
>>> test_dict({})
dict
{}
"""
print(d.__class__.__name__)
print(d.__class__())
@cython.locals(i=int)
def test_int(i):
"""
>>> test_int(0)
int
0
"""
print(i.__class__.__name__)
print(i.__class__())
@cython.cclass
class C:
def __str__(self):
return "I'm a C object"
@cython.locals(c=C)
def test_cdef_class(c):
"""
# This wasn't actually broken but is worth testing anyway
>>> test_cdef_class(C())
C
I'm a C object
"""
print(c.__class__.__name__)
print(c.__class__())
@cython.locals(d=object)
def test_object(o):
"""
>>> test_object({})
dict
{}
>>> test_object(1)
int
0
>>> test_object(C())
C
I'm a C object
"""
print(o.__class__.__name__)
print(o.__class__())
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment