New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Type variables in Callables don't unify #8275
Comments
The TypeScript and Python examples look different to me, in particular the |
The error container in the Typescript example is generic, the names were confusingly inconsistent. I've modified them to match, here they are: I'm not at all confident that my repro is correct. Now that I'm going back and attempting to do a repro more closely related to my actual code, I can't seem to get a typecheck error to occur. I'll continue poking at it, but regardless, we've got a direct translation to Typescript that typechecks and a version in with mypy that does not. Do you have a sense of why mypy's having an issue with this code? |
Here is a smaller repro of the first error. from typing import TypeVar, Generic, Union
T = TypeVar('T')
class Wrapper(Generic[T]):
pass
T1 = TypeVar('T1')
T2 = TypeVar('T2')
def passthrough(f: Union[Wrapper[T1], T2]) -> Union[Wrapper[T1], T2]:
return f
x: Union[Wrapper[int], str]
# E: Argument 1 to "passthrough" has incompatible type "Union[Wrapper[int], str]"; expected "Union[Wrapper[<nothing>], str]"
passthrough(x) It seems mypy infers odd results if we include two TypeVars within a union. We get similarly poor results if we define Here's a smaller repro for the second error. from typing import TypeVar, Generic, Union, Callable
class Parent: pass
class Child1(Parent): pass
class Child2(Parent): pass
T = TypeVar('T')
class Wrapper(Generic[T]):
inner: T
TParent = TypeVar('TParent', bound=Parent)
class Pipe(Generic[TParent]):
def __init__(self, x: Wrapper[TParent]) -> None:
pass
def __or__(self) -> Pipe[Union[Child1, Child2]]:
# E: Argument 1 to "Pipe" has incompatible type "Union[Wrapper[Child1], Wrapper[Child2]]";
# expected "Wrapper[Union[Child1, Child2]]"
x: Union[Wrapper[Child1], Wrapper[Child2]]
return Pipe(x) In this case, the root cause is that mypy does not consider In this case, I believe mypy is actually correct here. If we have a I'm not sure why TypeScript isn't detecting this particular issue, even with a similar simplified example. You do get some errors if you switch to doing The remaining errors seem to be the same as the first. |
The first error seems like mypy bug. The second example type checks cleanly if we make |
Thanks for the help with the repro @Michael0x2a! I completely agree with your assessment. In the meantime until this bug is addressed, is there a way to work around the issue using casts or something, or is the only option a mypy extension? I also tried using a fully-tagged union (rather than only tagging errors), and while Here's a first attempt where |
Any thoughts on my previous comment? |
I ran into this case recently and I wonder if it is the same/related (apologies if not): from typing import TypeVar
T = TypeVar("T")
def do_something(a: T) -> T:
return a
map(do_something, [1]) This gives:
I can see in typeshed the type for class map(Iterator[_S], Generic[_S]):
@overload
def __init__(self, __func: Callable[[_T1], _S], __iter1: Iterable[_T1]) -> None: ... So the problem seems to be that |
@anentropic I think your example passes on mypy master using the |
@hauntsaninja indeed it does... thank you 🎉 |
Issue type: Bug
Python version: 3.8
mypy version: 0.760
mypy flags: whatever the defaults are on https://mypy-play.net/
I discovered this issue when playing around with a monad-y
Either
thing (and here's it working in Typescript)Here is (I think) a minimal repro:
I would expect that in the type declaration of
bar
,T
would unify withint
, but clearly it does not.The text was updated successfully, but these errors were encountered: