From 538758ba61099e08f2a9ad9c0e665b92bcf3f42d Mon Sep 17 00:00:00 2001 From: Ivan Levkivskyi Date: Tue, 21 Feb 2017 13:30:35 +0100 Subject: [PATCH 1/3] Allow covariant args in constructor --- mypy/checker.py | 5 ++++- test-data/unit/check-classes.test | 10 ++++++++++ 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/mypy/checker.py b/mypy/checker.py index 50fd6601dbe4..b343e644d590 100644 --- a/mypy/checker.py +++ b/mypy/checker.py @@ -582,7 +582,10 @@ def is_implicit_any(t: Type) -> bool: elif isinstance(arg_type, TypeVarType): # Refuse covariant parameter type variables # TODO: check recursively for inner type variables - if arg_type.variance == COVARIANT: + if ( + arg_type.variance == COVARIANT and + defn.name() not in ('__init__', '__new__') + ): self.fail(messages.FUNCTION_PARAMETER_CANNOT_BE_COVARIANT, arg_type) if typ.arg_kinds[i] == nodes.ARG_STAR: # builtins.tuple[T] is typing.Tuple[T, ...] diff --git a/test-data/unit/check-classes.test b/test-data/unit/check-classes.test index 87e3342efa15..f3a40878875f 100644 --- a/test-data/unit/check-classes.test +++ b/test-data/unit/check-classes.test @@ -1942,6 +1942,16 @@ def new_pro_user(user_class: Type[ProUser]): new_user(user_class) [out] +[case testAllowCovariantArgsInConstructor] +from typing import Generic, TypeVar + +T_co = TypeVar('T_co', covariant=True) + +class C(Generic[T_co]): + def __init__(self, x: T_co) -> None: # This should be allowed + pass +[out] + [case testTypeUsingTypeCErrorCovariance] from typing import Type, TypeVar class User: pass From 998d623f4288b692b70af9d2ee9f52310c55a85f Mon Sep 17 00:00:00 2001 From: Ivan Levkivskyi Date: Tue, 21 Feb 2017 13:36:49 +0100 Subject: [PATCH 2/3] Add fixture --- test-data/unit/check-classes.test | 1 + 1 file changed, 1 insertion(+) diff --git a/test-data/unit/check-classes.test b/test-data/unit/check-classes.test index f3a40878875f..d699fe8f35f4 100644 --- a/test-data/unit/check-classes.test +++ b/test-data/unit/check-classes.test @@ -1950,6 +1950,7 @@ T_co = TypeVar('T_co', covariant=True) class C(Generic[T_co]): def __init__(self, x: T_co) -> None: # This should be allowed pass +[builtins fixtures/property.pyi] [out] [case testTypeUsingTypeCErrorCovariance] From cc418697ec45e079b0e9d3077bd8adfa4609168b Mon Sep 17 00:00:00 2001 From: Ivan Levkivskyi Date: Tue, 21 Feb 2017 14:25:15 +0100 Subject: [PATCH 3/3] Add reveal_type in tests --- test-data/unit/check-classes.test | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/test-data/unit/check-classes.test b/test-data/unit/check-classes.test index d699fe8f35f4..c277250f64f6 100644 --- a/test-data/unit/check-classes.test +++ b/test-data/unit/check-classes.test @@ -1949,7 +1949,11 @@ T_co = TypeVar('T_co', covariant=True) class C(Generic[T_co]): def __init__(self, x: T_co) -> None: # This should be allowed - pass + self.x = x + def meth(self) -> None: + reveal_type(self.x) # E: Revealed type is 'T_co`1' + +reveal_type(C(1).x) # E: Revealed type is 'builtins.int*' [builtins fixtures/property.pyi] [out]