-
-
Notifications
You must be signed in to change notification settings - Fork 1.8k
Make asyncio.Task covariant #8781
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
Conversation
See my comment on the mypy issue, I think making Future covariant is unsound |
Will it still work by making Task covariant and Future not? |
Thanks @hauntsaninja, I missed that method. We can't make Task covariant either, because |
Task.set_result always raises, so I think you could get away with that. |
Indeed, docs says:
|
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
I'm still hesitant about having a covariant subclass of an invariant base class. Given @erictraut curious if you have any opinions here: maybe type checkers should not allow covariant subclasses of invariant base classes? And how would this work under PEP 695? |
It definitely feels sketchy, but in this particular case as far as I can tell it's not any more unsound than the existing Liskov issue with set_result |
I agree this is sketchy. Neither mypy nor pyright (I haven't tried the other type checkers) complain about this situation currently, even though it's clearly wrong. from typing import TypeVar
T = TypeVar("T", covariant=True)
class MyList(list[T]): pass
def append_float(y: MyList[float]):
y.append(1.0)
x: MyList[int] = MyList([1, 2, 3])
append_float(x) This is a pretty big hole in type safety, and it should probably be plugged. I'll explore a solution in pyright and see whether it produces a lot of noise for internal Microsoft code bases that use pyright. In the meantime, I recommend not taking a dependency on this sketchy behavior — especially for classes that are as commonly-used as |
I've implemented support for this missing check in pyright. I didn't see any violations of it in our internal Microsoft source bases, nor were there any existing violations in typeshed. I'm not sure what I'd recommend for this PR. I understand the reasoning, but I think I'd reject it because it's unsound from a type perspective, and it will no longer pass type checking when using pyright. If you decide to keep it, you can use a |
Thanks for checking that! I'm still in favour of this PR because it solves a real problem, models the runtime better, and there isn't opportunity for unsoundness beyond the pre-existing Liskov violation. Seems worth adding a test case to confirm behaviour, though. But it is icky and we've managed so far without it, so if we were to reject that would be understandable. Edit: I added the check to mypy in python/mypy#13714 |
I don't have a strong opinion on this, but I agree that this can be useful. In one project, I had many collections of tasks that I wanted to cancel when a specific thing happened, so I made it something like |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I agree that doing this is usually unsound, and I'm very happy that we're fixing mypy and pyright to properly detect this unsoundness in the future. But I also agree that this case is weird enough that the usual rules don't really apply here, and that this models the runtime better. I'm happy for this to go in; we can type: ignore
it when we upgrade to versions of mypy/pyright that detect this kind of unsoundness.
This comment has been minimized.
This comment has been minimized.
1 similar comment
According to mypy_primer, this change has no effect on the checked open source code. 🤖🎉 |
This has been open for a bit and while it is a sketchy change, no one seems particularly opposed to it. So I'm planning on merging. tldr:
|
python/mypy#13689 (comment)