Closed
Description
I have this example:
import typing
A = typing.TypeVar('A')
class Base(typing.Generic[A]):
def do(self, input: A) -> A:
return input
Inputs1 = typing.Union[int, str]
class Numbers1(Base[Inputs1]):
pass
Inputs2 = typing.TypeVar('Inputs2', bound=typing.Union[int, str])
class Numbers2(Base[Inputs2]):
pass
class Numbers3(Base[Inputs1]):
def do(self, input: Inputs2) -> Inputs2:
return input
reveal_type(1) # This is line 23
reveal_type(Numbers1().do(1))
reveal_type(Numbers1().do('foobar'))
reveal_type(Numbers2().do(1))
reveal_type(Numbers2().do('foobar'))
reveal_type(Numbers3().do(1))
reveal_type(Numbers3().do('foobar'))
When I run mypy (mypy===0.570-dev-1aba774cc00b49627b86f95c8172adbb12b52891
), I get:
test.py:23: error: Revealed type is 'builtins.int'
test.py:24: error: Revealed type is 'Union[builtins.int, builtins.str]'
test.py:25: error: Revealed type is 'Union[builtins.int, builtins.str]'
test.py:26: error: Revealed type is '<nothing>'
test.py:26: error: Argument 1 to "do" of "Base" has incompatible type "int"; expected <nothing>
test.py:27: error: Revealed type is '<nothing>'
test.py:27: error: Argument 1 to "do" of "Base" has incompatible type "str"; expected <nothing>
test.py:28: error: Revealed type is 'builtins.int*'
test.py:29: error: Revealed type is 'builtins.str*'
Ideally, Numbers1
should work like Numbers3
, or at least Numbers2
should. But currently it seems like only Numbers3
make a strict return type and not union type. It is sad that I have to reimplement do
method just to get correct return types. This is really going against DRY principle.
Activity
gvanrossum commentedon Jan 6, 2018
That seems wishful thinking. If you expand the generics in
Numbers1
, you end up with ado()
method that takes an arg of typeUnion[int, str]
and returnsUnion[int, str]
, so the behavior is as it should be.The problem with
Numbers2
seems to be that you've madeNumbers2
a generic class. Now instantiating a generic class without giving it a specific type typically defaults toAny
, but that doesn't fly since the generic var has a union bound. There's some bug here that causes this to come out as<nothing>
(probably already in the tracker somewhere else) but at best it would behave the same asNumbers1
, notNumbers3
.mitar commentedon Jan 6, 2018
Yea, I think I understand why it is not working at the moment. But hopefully it will could work. So how I see is that
A
is a placeholder and that then a subclass can specify what it is. And it seems there is no way to tell currently that it can be or type A or type B, but whatever it will be, it will be the same type. So it seems you cannot mix generic class with methods using type variables? Maybe there could be some syntax for this?Less fancy than
[...]
but could tell to do really replaceA
withInputs
and not create a new generic?ilevkivskyi commentedon Jan 6, 2018
TBH, I don't see an issue here (apart from
Uninhabited
instead ofAny
for an unconstrainedTypeVar
, but we have an issue for this). @mitar could you please provide some more details, what is the code you have, mypy output, and expected output?As a side note, maybe we should add an issue template? (GitHub supports this.) For me personally it would be easier to see these points:
@gvanrossum @JukkaL What do you think?
gvanrossum commentedon Jan 6, 2018
ilevkivskyi commentedon Jan 6, 2018
It is jut plain text placed initially in the issue, one can edit it or remove completely. I will make one now, and we will see how it goes.
ilevkivskyi commentedon Jan 6, 2018
OK, here is the PR #4433
mitar commentedon Jan 6, 2018
I provided that in the initial issue text? There is code, which mypy I ran, current output, and expected output is the last two lines of the mypy output.
Oh, sorry, I thought it was clear that is a feature request. Is there some other/better way to submit features requests? In README it says that issues are for feature requests as well:
emmatyping commentedon Jan 6, 2018
You don't explicitly say whether or not this is a feature request or bug report, so being explicit about that at the beginning would be helpful.
mitar commentedon Jan 6, 2018
Sorry about that. Yea, it is a feature request.
mitar commentedon Apr 30, 2019
I am closing this issue in favor of #6746 where I tried to describe in more detail what I am doing, what I tried, and how it does not work.