Skip to content

Covariance of Awaitable and friends #9812

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

Closed
vectro opened this issue Feb 25, 2023 · 8 comments
Closed

Covariance of Awaitable and friends #9812

vectro opened this issue Feb 25, 2023 · 8 comments

Comments

@vectro
Copy link

vectro commented Feb 25, 2023

Shouldn't typing.Awaitable, asyncio.Task, asyncio.Future, etc., be covariant on their respective type paremeters?

@vectro
Copy link
Author

vectro commented Feb 25, 2023

Looking more closely, it appears that:

It does seem unfortunate that we cannot always convert Future or Task to Awaitable though?

Maybe at least Task should inherit directly from Awaitable rather than through Future?

@AlexWaygood
Copy link
Member

Maybe at least Task should inherit directly from Awaitable rather than through Future?

That's not what happens at runtime, unfortunately. For a variety of reasons, it's good practice for typeshed to hew closely to runtime, rather than inventing fictional inheritance structures and method-resolution orders.

@AlexWaygood
Copy link
Member

I'm afraid I don't really see anything further we can do to improve the situation here, but I'm happy to reconsider if you have any specific suggestions :)

@AlexWaygood AlexWaygood closed this as not planned Won't fix, can't repro, duplicate, stale Feb 27, 2023
@hauntsaninja
Copy link
Collaborator

Feel free to post example code that you wish type checked!

@vectro
Copy link
Author

vectro commented Feb 28, 2023

Sure, this is a sketch of what I'm trying to do:

async def get_int() -> int:
    return 5


async def fun() -> None:
    awaitables: set[typing.Awaitable[int]] = set(get_int() for _ in range(10))

    while awaitables:
        finished_tasks, awaitables = await asyncio.wait(
            awaitables, return_when=asyncio.FIRST_COMPLETED
        )
        finished_results = await asyncio.gather(*finished_tasks)
        print(finished_results)

This results in an error on the line finished_tasks, awaitables = await asyncio.wait(, which is

error: Incompatible types in assignment (expression has type "Set[Task[int]]", variable has type "Set[Awaitable[int]]")  [assignment]

@JelleZijlstra
Copy link
Member

In that case the variance of Awaitable and co wouldn't help you, since set is already invariant.

@hauntsaninja
Copy link
Collaborator

Yup, Jelle is correct. Consider using typing.AbstractSet instead.

@vectro
Copy link
Author

vectro commented Mar 1, 2023

I see. Thanks folks!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants