PY-24383 Fixed: type inference broken for Union[Any, List[int]]

Update PySubscriptionExpressionImpl to correctly process weak operands.
Also update PyTypeChecker to not use original qualifier type while calculating substitutions for receiver, use current class type instead.
This commit is contained in:
Semyon Proshev
2017-06-09 15:29:03 +03:00
parent f49337af0c
commit dee2bf40c6
3 changed files with 16 additions and 2 deletions
@@ -1,5 +1,5 @@
/*
* Copyright 2000-2016 JetBrains s.r.o.
* Copyright 2000-2017 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -42,6 +42,7 @@ public class PySubscriptionExpressionImpl extends PyElementImpl implements PySub
super(astNode);
}
@Override
@NotNull
public PyExpression getOperand() {
return childToPsiNotNull(PythonDialectsTokenSetProvider.INSTANCE.getExpressionTokens(), 0);
@@ -57,6 +58,7 @@ public class PySubscriptionExpressionImpl extends PyElementImpl implements PySub
return operand;
}
@Override
@Nullable
public PyExpression getIndexExpression() {
return childToPsi(PythonDialectsTokenSetProvider.INSTANCE.getExpressionTokens(), 1);
@@ -98,6 +100,11 @@ public class PySubscriptionExpressionImpl extends PyElementImpl implements PySub
}
members.add(res);
}
if (type instanceof PyUnionType && ((PyUnionType)type).isWeak()) {
return PyUnionType.createWeakType(PyUnionType.union(members));
}
return PyUnionType.union(members);
}
@@ -561,7 +561,7 @@ public class PyTypeChecker {
for (PyTypeProvider provider : Extensions.getExtensions(PyTypeProvider.EP_NAME)) {
final PyType genericType = provider.getGenericType(type.getPyClass(), context);
if (genericType != null) {
match(genericType, qualifierType, context, substitutions);
match(genericType, type, context, substitutions);
}
for (Map.Entry<PyType, PyType> entry : provider.getGenericSubstitutions(type.getPyClass(), context).entrySet()) {
final PyGenericType genericKey = as(entry.getKey(), PyGenericType.class);
@@ -1897,6 +1897,13 @@ public class PyTypeTest extends PyTestCase {
);
}
// PY-24383
public void testSubscriptionOnWeakType() {
doTest("Union[int, Any]",
"foo = bar() if 42 != 42 else [1, 2, 3, 4]\n" +
"expr = foo[0]");
}
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());