Update matching against type var with multiple bounds (PY-32313)

This commit is contained in:
Semyon Proshev
2018-11-06 15:15:29 +03:00
parent b48d4f71e2
commit c036085b40
2 changed files with 30 additions and 2 deletions

View File

@@ -22,6 +22,7 @@ import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.*;
import java.util.function.Function;
import static com.jetbrains.python.codeInsight.typing.PyProtocolsKt.inspectProtocolSubclass;
import static com.jetbrains.python.psi.PyUtil.as;
@@ -198,8 +199,9 @@ public class PyTypeChecker {
final PyType substitution = context.substitutions.get(expected);
PyType bound = expected.getBound();
// Promote int in Type[TypeVar('T', int)] to Type[int] before checking that bounds match
if (expected.isDefinition() && bound instanceof PyInstantiableType) {
bound = ((PyInstantiableType)bound).toClass();
if (expected.isDefinition()) {
final Function<PyType, PyType> toDefinition = t -> t instanceof PyInstantiableType ? ((PyInstantiableType)t).toClass() : t;
bound = PyUnionType.union(PyTypeUtil.toStream(bound).map(toDefinition).toList());
}
Optional<Boolean> match = match(bound, actual, context);

View File

@@ -682,4 +682,30 @@ public class PyTypeCheckerInspectionTest extends PyInspectionTestCase {
"\n" +
"f(A)");
}
// PY-32313
public void testMatchingAgainstMultipleBoundTypeVar() {
runWithLanguageLevel(
LanguageLevel.PYTHON35,
() -> doTestByText("from typing import Type, TypeVar\n" +
"\n" +
"class A:\n" +
" pass\n" +
"\n" +
"class B(A):\n" +
" pass\n" +
"\n" +
"class C:\n" +
" pass\n" +
"\n" +
"T = TypeVar('T', A, B)\n" +
"\n" +
"def f(cls: Type[T], arg: int) -> T:\n" +
" pass\n" +
"\n" +
"f(A, 1)\n" +
"f(B, 2)\n" +
"f(<warning descr=\"Expected type 'Type[T]', got 'Type[C]' instead\">C</warning>, 3)")
);
}
}