Skip to content
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

mypy 0.750 regression with asyncio.wait #8051

Closed
srittau opened this issue Dec 2, 2019 · 3 comments · Fixed by #8077
Closed

mypy 0.750 regression with asyncio.wait #8051

srittau opened this issue Dec 2, 2019 · 3 comments · Fixed by #8077
Labels
bug mypy got something wrong priority-0-high

Comments

@srittau
Copy link
Contributor

srittau commented Dec 2, 2019

Please consider the following:

from asyncio import Future, wait
from typing import List

async def foo() -> None:
    f: List[Future[None]] = []
    await wait(f)

Checking this with mypy 0.740 (Python 3.8.0) without options succeeds. Checking it with mypy 0.750 (also Python 3.8.0, no options) prints the following error:

foo.py:6: error: Argument 1 to "wait" has incompatible type "List[Future[None]]"; expected "Iterable[Union[Future[<nothing>], Generator[Any, None, <nothing>], Awaitable[<nothing>]]]"
Found 1 error in 1 file (checked 1 source file)

The annotation of asyncio.wait() from typeshed has not changed between mypy versions:

_T = TypeVar('_T')
...
_FutureT = Union[Future[_T], Generator[Any, None, _T], Awaitable[_T]]
...
def wait(fs: Iterable[_FutureT[_T]], *, loop: Optional[AbstractEventLoop] = ..., timeout: Optional[float] = ...,
         return_when: str = ...) -> Future[Tuple[Set[Future[_T]], Set[Future[_T]]]]: ...
@ilevkivskyi
Copy link
Member

FWIW this also fails on master and Python 3.7. I wasn't able to find a simple repro not-involving async/await.

@ilevkivskyi ilevkivskyi added bug mypy got something wrong priority-0-high labels Dec 2, 2019
@ilevkivskyi
Copy link
Member

ilevkivskyi commented Dec 4, 2019

Here I have a simple repro:

from typing import Union, Generic, TypeVar

T = TypeVar('T')
T_co = TypeVar('T_co', covariant=True)

class Cov(Generic[T_co]): ...
class Inv(Cov[T]): ...

X = Union[Cov[T], Inv[T]]

def f(x: X[T]) -> T: ...
x: Inv[int]
f(x)

This test passes on v0.740, but fails on v0.750. The reason is subtle, but ultimately it is related to switch to the new type alias representation. The point is that expand_type() (called from freshen_function_type_vars()) calls make_simplified_union() when visiting union types, while type alias to union stays "unsimplified". Then later constraint inference fails, because it is generally more tricky for union types. I see two possible solutions here:

  • Call make_simplified_union() in infer_constraints() to only use union inference when necessary
  • Improve any_constraints() to consider cases where two constrain lists are [T <: X, T :> X] and [T :> X].

I am leaning towards first option. Also I don't really want to call get_proper_type() in expand_type() to trigger union simplification, since that looks a bit unprincipled and potentially dangerous.

@JukkaL
Copy link
Collaborator

JukkaL commented Dec 4, 2019

I agree that using make_simplified_union in infer_constraints() sounds like the best approach. Type inference shouldn't be affected by whether union types have bee simplified.

ilevkivskyi added a commit that referenced this issue Dec 4, 2019
…ference (#8077)

Fixes #8051

The fix is as discussed in the issue. I didn't find a test case for the union `actual`, but I think it makes sense to simplify it as well. Note: I add the `pythoneval` test just as a regression test, if you think it is not worth it, I can remove it.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug mypy got something wrong priority-0-high
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants