Commit a09e8c79 authored by Xavier Thompson's avatar Xavier Thompson

Fix typechecks for casts to and from qualified cypclass

parent 5f44fcb1
...@@ -10921,6 +10921,8 @@ class TypecastNode(ExprNode): ...@@ -10921,6 +10921,8 @@ class TypecastNode(ExprNode):
if self.operand.type.is_ptr: if self.operand.type.is_ptr:
if not (self.operand.type.base_type.is_void or self.operand.type.base_type.is_struct): if not (self.operand.type.base_type.is_void or self.operand.type.base_type.is_struct):
error(self.pos, "Python objects cannot be cast from pointers of primitive types") error(self.pos, "Python objects cannot be cast from pointers of primitive types")
elif self.operand.type.is_qualified_cyp_class:
error(self.pos, "Cannot cast '%s' to '%s'" % (self.operand.type, self.type))
else: else:
# Should this be an error? # Should this be an error?
warning(self.pos, "No conversion from %s to %s, python object pointer used." % ( warning(self.pos, "No conversion from %s to %s, python object pointer used." % (
...@@ -10954,9 +10956,10 @@ class TypecastNode(ExprNode): ...@@ -10954,9 +10956,10 @@ class TypecastNode(ExprNode):
self.op_func_type = entry.type self.op_func_type = entry.type
if self.type.is_cyp_class: if self.type.is_cyp_class:
self.is_temp = self.overloaded self.is_temp = self.overloaded
if self.type.is_qualified_cyp_class: if self.type.is_cyp_class and self.operand.type.is_cyp_class:
if not self.type.assignable_from(self.operand.type): if self.operand.type.is_qualified_cyp_class or self.type.is_qualified_cyp_class:
error(self.pos, "Cannot cast %s to %s" % (self.operand.type, self.type)) if not (self.type.same_as(self.operand.type) or self.type.assignable_from(self.operand.type)):
error(self.pos, "Cannot cast '%s' to '%s'" % (self.operand.type, self.type))
if self.type.is_ptr and self.type.base_type.is_cfunction and self.type.base_type.nogil: if self.type.is_ptr and self.type.base_type.is_cfunction and self.type.base_type.nogil:
op_type = self.operand.type op_type = self.operand.type
if op_type.is_ptr: if op_type.is_ptr:
......
...@@ -19,6 +19,7 @@ cdef cypclass A activable: ...@@ -19,6 +19,7 @@ cdef cypclass A activable:
def test_aliasing(): def test_aliasing():
cdef active A active_a cdef active A active_a
# Aliasing from active
cdef iso A iso_a cdef iso A iso_a
iso_a = active_a iso_a = active_a
...@@ -28,6 +29,17 @@ def test_aliasing(): ...@@ -28,6 +29,17 @@ def test_aliasing():
cdef A ref_a cdef A ref_a
ref_a = active_a ref_a = active_a
# Aliasing to active
cdef active A active_b
active_b = A()
cdef active A active_c
active_c = consume A()
cdef active A active_d
active_d = <locked A> consume A()
def test_calling(): def test_calling():
a = activate(consume A()) a = activate(consume A())
...@@ -45,9 +57,41 @@ def test_calling(): ...@@ -45,9 +57,41 @@ def test_calling():
a.f_active(NULL, active_a) a.f_active(NULL, active_a)
def test_typecast():
cdef active A active_a
# Casting from active
cdef iso A iso_a
iso_a = consume <iso A> active_a
cdef locked A locked_a
locked_a = <locked A> active_a
cdef A ref_a
ref_a = <A> active_a
# Casting to active
cdef active A active_b
active_b = <active A> A()
cdef active A active_c
active_c = <active A> <iso A> consume A()
cdef active A active_d
active_d = <active A> <locked A> consume A()
_ERRORS = u''' _ERRORS = u'''
23:12: Cannot assign type 'active A' to 'iso A' 24:12: Cannot assign type 'active A' to 'iso A'
26:15: Cannot assign type 'active A' to 'locked A' 27:15: Cannot assign type 'active A' to 'locked A'
29:12: Cannot assign type 'active A' to 'A' 30:12: Cannot assign type 'active A' to 'A'
34:15: Cannot assign type 'A' to 'iso-> A' 34:16: Cannot assign type 'A' to 'active A'
40:15: Cannot assign type 'locked A' to 'active A'
46:15: Cannot assign type 'A' to 'iso-> A'
65:20: Cannot cast 'active A' to 'iso A'
68:15: Cannot cast 'active A' to 'locked A'
71:12: Cannot cast 'active A' to 'A'
75:15: Cannot cast 'A' to 'active A'
78:15: Cannot cast 'iso A' to 'active A'
81:15: Cannot cast 'locked A' to 'active A'
''' '''
...@@ -9,7 +9,7 @@ def test_name_aliasing(): ...@@ -9,7 +9,7 @@ def test_name_aliasing():
cdef iso A iso_a cdef iso A iso_a
iso_a = consume A() iso_a = consume A()
# Aliasing non-consumed to iso # Aliasing to iso
cdef iso A iso_b cdef iso A iso_b
iso_b = iso_a iso_b = iso_a
...@@ -75,6 +75,37 @@ def test_field_aliasing(): ...@@ -75,6 +75,37 @@ def test_field_aliasing():
c = o.bar(consume Field()) c = o.bar(consume Field())
def test_typecast():
cdef iso A iso_a
iso_a = consume A()
# Casting to iso
cdef iso A iso_b
iso_b = <iso A> A()
cdef iso A iso_c
iso_c = <iso A> activate(consume A())
cdef iso A iso_d
iso_d = <iso A> <object> A()
# Casting from iso
cdef active A active_a
active_a = <active A> iso_a
cdef A ref_a
ref_a = <A> iso_a
cdef object py_a
py_a = <object> iso_a
cdef iso A iso_e
iso_e = <iso A> iso_a
cdef iso A iso_f
iso_f = consume <iso A> iso_a
_ERRORS = u''' _ERRORS = u'''
14:12: Cannot assign type 'iso A' to 'iso A' 14:12: Cannot assign type 'iso A' to 'iso A'
17:13: Cannot assign type 'A' to 'iso A' 17:13: Cannot assign type 'A' to 'iso A'
...@@ -89,4 +120,13 @@ _ERRORS = u''' ...@@ -89,4 +120,13 @@ _ERRORS = u'''
66:13: Cannot assign type 'iso-> Field' to 'iso-> Field' 66:13: Cannot assign type 'iso-> Field' to 'iso-> Field'
72:15: Cannot assign type 'Field' to 'iso-> Field' 72:15: Cannot assign type 'Field' to 'iso-> Field'
75:13: Cannot assign type 'iso-> Field' to 'iso-> Field' 75:13: Cannot assign type 'iso-> Field' to 'iso-> Field'
84:12: Cannot assign type 'iso A' to 'iso A'
84:12: Cannot cast 'A' to 'iso A'
87:12: Cannot assign type 'iso A' to 'iso A'
87:12: Cannot cast 'active A' to 'iso A'
90:12: Cannot assign type 'iso A' to 'iso A'
94:15: Cannot cast 'iso A' to 'active A'
97:12: Cannot cast 'iso A' to 'A'
100:11: Cannot cast 'iso A' to 'Python object'
103:12: Cannot assign type 'iso A' to 'iso A'
''' '''
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