mypy icon indicating copy to clipboard operation
mypy copied to clipboard

Incompatible definition of generic field on multiple base classes

Open dn-kialo opened this issue 5 years ago • 4 comments

[BUG] Edited for a clearer example Given this code:

# mypy version 0.770
from typing import Generic, TypeVar

T = TypeVar("T", int, str)

class A:
  foo: int

class B(Generic[T]):
  foo: T

class C(B[int], A):
  pass

reveal_type(A().foo)
reveal_type(B().foo)
reveal_type(C().foo)

I get this output:

example.py:11: error: Definition of "foo" in base class "B" is incompatible with definition in base class "A"
example.py:14: note: Revealed type is 'builtins.int'
example.py:15: note: Revealed type is 'builtins.int*'
example.py:16: note: Revealed type is 'builtins.int*'

I couldn't find what builtins.int*. The code makes sense though, right?

dn-kialo avatar Jun 22 '20 14:06 dn-kialo

Yeah, this is a mypy bug. Likely related to https://github.com/python/mypy/issues/7724

ilevkivskyi avatar Jul 03 '20 15:07 ilevkivskyi

Still happening with mypy 0.960 :( Although, now without "*" in the revealed types.

headtr1ck avatar Jun 17 '22 12:06 headtr1ck

I think I just encountered a modified version of this in django-stubs: https://github.com/typeddjango/django-stubs/issues/1227 . Due to the structure of the classes we are trying to type, the attribute is defined as generic in both base classes, and passed as a type parameter to each:

from typing import Generic, TypeVar

T = TypeVar("T", int, str)

class A(Generic[T]):
  foo: T

class B(Generic[T]):
  foo: T

class C(Generic[T], B[T], A[T]):
  pass

c: C[int] = C()

reveal_type(A().foo)
reveal_type(B().foo)
reveal_type(c.foo)

adamchainz avatar Nov 11 '22 09:11 adamchainz

I just ran into the same issue. I don't see it explicitly mentioned above, but one workaround is to explicitly type the attribute in the concrete class (if that's an option; i.e. if the type is resolved in the class definition rather than the variable declaration); e.g.

from typing import Generic, TypeVar

T = TypeVar('T')

class A(Generic[T]):
    value: T

class B(Generic[T]):
    value: T

class C(A[int], B[int]):
    value: int

tonysyu avatar Dec 20 '22 21:12 tonysyu