-
-
Notifications
You must be signed in to change notification settings - Fork 3k
Description
I believe this would qualify as a bug.
When a method takes generic input types that are also present in the return type, and that method is defined as abstract, the revealed type of the method appears correct, but the inferred type of the returned value is not consistent with the inferred method type. This is resolved when the method is not declared abstract.
I have a very broad use case for this code, but I've minimized for the example here. I hope this is clear and please let me know if there's anything else I can add or help with.
from abc import ABC, abstractmethod
from typing import Generic, TypeVar
A = TypeVar('A')
B = TypeVar('B')
class TwoTypes(Generic[A, B]): pass
class MakeTwoSurprise(ABC, Generic[A]):
@abstractmethod
def __call__(self, a: B) -> TwoTypes[A, B]: pass
class MakeTwoExpected(Generic[A]):
def __call__(self, a: B) -> TwoTypes[A, B]: pass
class Test():
def make_two(self,
mts: MakeTwoSurprise[A],
mte: MakeTwoExpected[A]) -> None:
reveal_type(mts.__call__) # Revealed type is 'def [B] (a: B`-1) -> repro.TwoTypes[A`-1, B`-1]'
reveal_type(mts(2)) # Revealed type is 'repro.TwoTypes[builtins.int*, builtins.int*]'
reveal_type(mte.__call__) # Revealed type is 'def [B] (a: B`2) -> repro.TwoTypes[A`-1, B`2]'
reveal_type(mte(2)) # Revealed type is 'repro.TwoTypes[A`-1, builtins.int*]'
I'd expect both of these implementations to typecheck identically, but more importantly you can see reveal_type(mts(2))
has inferred int
for both type arguments in TwoTypes
, even though the first argument, while still unknown to the implementation of make_two
, would have previously been determined by a caller of this method, based on the instance of MakeTwoSurprise
that they had passed.
Any and all feedback/assistance is greatly appreciated.