Commit 883001d1 authored by Xavier Thompson's avatar Xavier Thompson

Fix 'illegal implicit conversion overloads' rule not taking inherited methods into account

parent 0df5c4dc
...@@ -1624,7 +1624,6 @@ class CppClassNode(CStructOrUnionDefNode, BlockNode): ...@@ -1624,7 +1624,6 @@ class CppClassNode(CStructOrUnionDefNode, BlockNode):
if self.cypclass and scope is not None: if self.cypclass and scope is not None:
for method_entry in scope.entries.values(): for method_entry in scope.entries.values():
if method_entry.is_cfunction: if method_entry.is_cfunction:
from_type = method_entry.from_type
for alt_entry in method_entry.all_alternatives(): for alt_entry in method_entry.all_alternatives():
alt_type = alt_entry.type alt_type = alt_entry.type
for other_entry in method_entry.all_alternatives(): for other_entry in method_entry.all_alternatives():
...@@ -1632,13 +1631,25 @@ class CppClassNode(CStructOrUnionDefNode, BlockNode): ...@@ -1632,13 +1631,25 @@ class CppClassNode(CStructOrUnionDefNode, BlockNode):
continue continue
other_type = other_entry.type other_type = other_entry.type
# if there is a conversion path from one method to another # if there is a conversion path from one method to another
# the set of classes that define the first must be a superset # the set of classes that define or inherit the first must be a superset
# of the set of base classes that define the second method # of the set of base classes that define or inherit the second method
if alt_type.convertible_arguments_to(other_type): if alt_type.convertible_arguments_to(other_type):
# since we only have the defining classes, we need to add the inheriting classes
def defining_or_inheriting(defining_classes):
result = []
for superclass in self.entry.type.mro():
for defining_class in defining_classes:
if defining_class in superclass.mro():
result.append(superclass)
break
return result
# since the classes are MRO-ordered, a subset is actually the same as a subsequence # since the classes are MRO-ordered, a subset is actually the same as a subsequence
def is_subsequence(s, seq): def is_subsequence(s, seq):
return all(e in iter(seq) for e in s) return all(e in iter(seq) for e in s)
if not is_subsequence(other_entry.defining_classes, alt_entry.defining_classes): if not is_subsequence(
defining_or_inheriting(other_entry.defining_classes),
defining_or_inheriting(alt_entry.defining_classes)
):
error( error(
alt_entry.pos, ( alt_entry.pos, (
"Illegal implicit conversion path between cypclass methods:\n" "Illegal implicit conversion path between cypclass methods:\n"
...@@ -1646,7 +1657,7 @@ class CppClassNode(CStructOrUnionDefNode, BlockNode): ...@@ -1646,7 +1657,7 @@ class CppClassNode(CStructOrUnionDefNode, BlockNode):
">> %s\n" ">> %s\n"
"has argument types implicitely convertible to method\n" "has argument types implicitely convertible to method\n"
">> %s\n" ">> %s\n"
"but some superclasses of '%s' only declare the second method\n" "but some superclasses of '%s' only declare or inherit the second method\n"
% (alt_type.declaration_code(alt_entry.name, for_display = 1).strip(), % (alt_type.declaration_code(alt_entry.name, for_display = 1).strip(),
other_type.declaration_code(alt_entry.name, for_display = 1).strip(), other_type.declaration_code(alt_entry.name, for_display = 1).strip(),
self.name) self.name)
......
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