Commit 0de43685 authored by Semyon Proshev's avatar Semyon Proshev
Browse files

Return next after `Base` in `self`'s MRO for `super(Base, self)` (PY-32533)

Previously first class in `Base`'s MRO were returned.
parent cfffd077
Branches unavailable Tags unavailable
Showing with 33 additions and 3 deletions
+33 -3
......@@ -659,9 +659,15 @@ public class PyCallExpressionHelper {
return getSuperClassUnionType(firstClass, context);
}
if (secondClass.isSubclass(firstClass, context)) {
final Iterator<PyClass> iterator = firstClass.getAncestorClasses(context).iterator();
if (iterator.hasNext()) {
return new PyClassTypeImpl(iterator.next(), false); // super(Foo, self) has type of Foo, modulo __get__()
final PyClass nextAfterFirstInMro = StreamEx
.of(secondClass.getAncestorClasses(context))
.dropWhile(it -> it != firstClass)
.skip(1)
.findFirst()
.orElse(null);
if (nextAfterFirstInMro != null) {
return new PyClassTypeImpl(nextAfterFirstInMro, false);
}
}
}
......
......@@ -3294,6 +3294,30 @@ public class PyTypeTest extends PyTestCase {
" expr = a");
}
// PY-32533
public void testSuperWithAnotherType() {
runWithLanguageLevel(
LanguageLevel.PYTHON34,
() -> doTest("A",
"class A:\n" +
" def f(self):\n" +
" return 'A'\n" +
"\n" +
"class B:\n" +
" def f(self):\n" +
" return 'B'\n" +
"\n" +
"class C(B):\n" +
" def f(self):\n" +
" return 'C'\n" +
"\n" +
"class D(C, A):\n" +
" def f(self):\n" +
" expr = super(B, self)\n" +
" return expr.f()")
);
}
private static List<TypeEvalContext> getTypeEvalContexts(@NotNull PyExpression element) {
return ImmutableList.of(TypeEvalContext.codeAnalysis(element.getProject(), element.getContainingFile()).withTracing(),
TypeEvalContext.userInitiated(element.getProject(), element.getContainingFile()).withTracing());
......
Supports Markdown
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