From a62caad372de5d2810b1072e4ca23e527f721228 Mon Sep 17 00:00:00 2001 From: Reid Barton Date: Mon, 2 May 2016 20:58:28 -0700 Subject: [PATCH] Allow substituting typevar-with-values for typevar-with-values (#1469) This is needed for subtyping of generic function with type variables with values to work correctly, which will be needed for #1261. --- mypy/applytype.py | 9 ++++++++- mypy/test/data/check-typevar-values.test | 14 ++++++++++++++ 2 files changed, 22 insertions(+), 1 deletion(-) diff --git a/mypy/applytype.py b/mypy/applytype.py index 5d827da4d1a2..29f2287ef39c 100644 --- a/mypy/applytype.py +++ b/mypy/applytype.py @@ -1,8 +1,9 @@ from typing import List, Dict import mypy.subtypes +from mypy.sametypes import is_same_type from mypy.expandtype import expand_type -from mypy.types import Type, CallableType, AnyType, Void +from mypy.types import Type, TypeVarType, CallableType, AnyType, Void from mypy.messages import MessageBuilder from mypy.nodes import Context @@ -29,6 +30,12 @@ def apply_generic_arguments(callable: CallableType, types: List[Type], if values and type: if isinstance(type, AnyType): continue + if isinstance(type, TypeVarType) and type.values: + # Allow substituting T1 for T if every allowed value of T1 + # is also a legal value of T. + if all(any(is_same_type(v, v1) for v in values) + for v1 in type.values): + continue for value in values: if mypy.subtypes.is_subtype(type, value): types[i] = value diff --git a/mypy/test/data/check-typevar-values.test b/mypy/test/data/check-typevar-values.test index f9d8223b352a..4f690cdbade3 100644 --- a/mypy/test/data/check-typevar-values.test +++ b/mypy/test/data/check-typevar-values.test @@ -465,3 +465,17 @@ def g(x: str) -> str: return x main: note: In function "f": main:7: error: Incompatible types in assignment (expression has type "object", variable has type "int") main:7: error: Incompatible types in assignment (expression has type "object", variable has type "str") + +[case testGenericFunctionSubtypingWithTypevarValues] +from typing import TypeVar +class A: pass +T = TypeVar('T', int, str) +U = TypeVar('U', str, A, int) +def f(x: T) -> T: pass +def g(x: U) -> U: pass +a = f +a = f +a = g +b = g +b = g +b = f # E: Incompatible types in assignment (expression has type Callable[[T], T], variable has type Callable[[U], U])