From 41db9a0c570a3e190f3749cf0b681a31823dc0f7 Mon Sep 17 00:00:00 2001 From: Ivan Levkivskyi Date: Tue, 10 Sep 2019 14:58:55 +0100 Subject: [PATCH] Pass is_classmethod to bind_self() also for superype (#7491) Fix a regression caused by https://github.com/python/mypy/pull/7474 The original PR correctly added `is_classmethod=...` in `bind_self()` for supertype, but I didn't notice the same problem (flag not passed) was also present for _subtype_. The fix is trivial. --- mypy/checker.py | 5 ++++- test-data/unit/check-classes.test | 15 +++++++++++++++ test-data/unit/fixtures/isinstancelist.pyi | 1 + 3 files changed, 20 insertions(+), 1 deletion(-) diff --git a/mypy/checker.py b/mypy/checker.py index c3015bb3ba34..255c0732e9bd 100644 --- a/mypy/checker.py +++ b/mypy/checker.py @@ -1454,14 +1454,17 @@ def check_method_override_for_base_with_name( if isinstance(defn, (FuncDef, OverloadedFuncDef)): typ = self.function_type(defn) # type: Type override_class_or_static = defn.is_class or defn.is_static + override_class = defn.is_class else: assert defn.var.is_ready assert defn.var.type is not None typ = defn.var.type override_class_or_static = defn.func.is_class or defn.func.is_static + override_class = defn.func.is_class typ = get_proper_type(typ) if isinstance(typ, FunctionLike) and not is_static(context): - typ = bind_self(typ, self.scope.active_self_type()) + typ = bind_self(typ, self.scope.active_self_type(), + is_classmethod=override_class) # Map the overridden method type to subtype context so that # it can be checked for compatibility. original_type = get_proper_type(base_attr.type) diff --git a/test-data/unit/check-classes.test b/test-data/unit/check-classes.test index 938b868eff14..a10c3c8e77da 100644 --- a/test-data/unit/check-classes.test +++ b/test-data/unit/check-classes.test @@ -6141,3 +6141,18 @@ class C(B[int, T]): def __init__(self) -> None: # TODO: error message could be better. self.x: Tuple[str, T] # E: Incompatible types in assignment (expression has type "Tuple[str, T]", base class "A" defined the type as "Tuple[int, T]") + +[case testOverrideGenericSelfClassMethod] +from typing import Generic, TypeVar, Type, List + +T = TypeVar('T', bound=A) + +class A: + @classmethod + def meth(cls: Type[T]) -> List[T]: ... + +class B(A): + @classmethod + def meth(cls: Type[T]) -> List[T]: ... + +[builtins fixtures/isinstancelist.pyi] diff --git a/test-data/unit/fixtures/isinstancelist.pyi b/test-data/unit/fixtures/isinstancelist.pyi index e5d8f98e425c..fcc3032183aa 100644 --- a/test-data/unit/fixtures/isinstancelist.pyi +++ b/test-data/unit/fixtures/isinstancelist.pyi @@ -11,6 +11,7 @@ class type: class function: pass class ellipsis: pass +class classmethod: pass def isinstance(x: object, t: Union[type, Tuple]) -> bool: pass def issubclass(x: object, t: Union[type, Tuple]) -> bool: pass