-
-
Notifications
You must be signed in to change notification settings - Fork 2.8k
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
Allow None vs TypeVar overlap for overloads #15846
Allow None vs TypeVar overlap for overloads #15846
Conversation
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
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 this use case seems sufficiently common that we can relax some type safety to support it.
|
||
@overload | ||
def foo(x: None, y: None) -> str: ... # E: Overloaded function signatures 1 and 2 overlap with incompatible return types | ||
def foo(x: None, y: None) -> str: ... | ||
@overload | ||
def foo(x: T, y: T) -> int: ... | ||
def foo(x): ... |
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.
Test also calling this to make sure we infer the return type correctly?
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.
Oh well, this discovered an obvious flaw in my solution, for this
@overload
def foo(x: None) -> None: ...
@overload
def foo(x: T) -> list[T]: ...
x: int | None
foo(x)
we will continue to infer list[int | None]
, not list[int] | None
that people will likely expect. I will try to check if there is a simple way to force union-math for this case. If there are none, this PR may become much more complex.
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.
OK, I think I have come up with some heuristics to force union math for None
vs TypeVar
overlap situations. It is not very precise, but should be generally safe, since IIUC union math infer better types anyway, we usually try to avoid it simply because it is computationally intensive.
Co-authored-by: Alex Waygood <Alex.Waygood@Gmail.com>
This comment has been minimized.
This comment has been minimized.
Diff from mypy_primer, showing the effect of this PR on open source code: pandas (https://github.com/pandas-dev/pandas)
+ pandas/core/nanops.py:1143: error: Unused "type: ignore" comment [unused-ignore]
+ pandas/core/nanops.py:1144: error: Argument 1 to "_maybe_arg_null_out" has incompatible type "Any | signedinteger[Any]"; expected "ndarray[Any, Any]" [arg-type]
+ pandas/core/nanops.py:1188: error: Unused "type: ignore" comment [unused-ignore]
+ pandas/core/nanops.py:1189: error: Argument 1 to "_maybe_arg_null_out" has incompatible type "Any | signedinteger[Any]"; expected "ndarray[Any, Any]" [arg-type]
streamlit (https://github.com/streamlit/streamlit)
+ lib/streamlit/delta_generator.py:415: error: Unused "type: ignore" comment [unused-ignore]
+ lib/streamlit/delta_generator.py:439: error: Unused "type: ignore" comment [unused-ignore]
discord.py (https://github.com/Rapptz/discord.py)
- discord/app_commands/commands.py:2388: error: Overloaded function signatures 1 and 2 overlap with incompatible return types [misc]
|
FWIW new errors in |
Although the PR now is more hacky than originally approved, I think it is still fine. So I am going to merge it unless there are objections. |
Thank you for this! I agree that a generic way to say "This TypeVar is NOT one of these things" (something like python/typing#801) is the most general way to go, but this definitely solves my problem and what seems to be a most common type of problem out there. |
Fixes #8881
This is technically unsafe, and I remember we explicitly discussed this a while ago, but related use cases turn out to be more common than I expected (judging by how popular the issue is). Also the fix is really simple.