PyCallExpression#multiResolveCallee giving wrong results.
Answered
Example:
class Z:
def __init__(self):
self.z = 'from Zs constructor'
print('from Zs constructor')
class A(Z):
def __init__(self):
super().__init__()
self.a = 'from As constructor'
print('from As constructor')
class B:
def __init__(self):
self.b = 'from Bs constructor'
print('from Bs constructor')
class C(A, B):
def __init__(self):
super(C, self).__init__() # Calls A's constructor
self.c = 'from Cs constructor'
print('from Cs constructor')
def driver(a):
a.b = C()
super(C, self).__init__() resolves to 2 methods:
- A::__init__
- B::__init__
But it should only resolve to A::__init__ only. Is this a bug?
Follow-up question:
Is the resolved method will always be in the same order? Means if I get resolved callee in the following order: A::__init__ and B::__init__, can it be B::__init__ and A__init__ in another call to multiResolveCallee?
Please sign in to leave a comment.
It's a subtle bug caused by the way the resolve for references on "super" works at the moment. In order to resolve any qualified name, we first resolve the type of its qualifier. For most kinds of expressions, it's a straightforward process, but "super" is different because its own result in a particular expression depends on which attribute you're accessing. In your case, when you're calling "__init__", it's indeed "A". However, if you modify the example slightly by accessing an attribute defined only in "B":
it turns out that just taking the first class in MRO order of C is not enough.
In order not to special case "super()" we infer its type as a union of the corresponding class' base classes. It's not entirely correct, and I've filed a couple of tickets about it (PY-53713, PY-53714). However, in most cases, the first item of `multiResolve` should still give what you're looking for. Where did you face this problem?
BTW, the cause of the current behavior can be pinpointed by invoking "Type Info" action on "super()" call.
Thank you for your response. Hope to see this bug fixed in the next release.