-
-
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
Fix ParamSpec constraint for types as callable #14153
Fix ParamSpec constraint for types as callable #14153
Conversation
Most types can be considered as callables, constructing the type itself. When a constraint was created for a ParamSpec variable, the return type would be set to NoneType, which conflicts with assumptions that CallableType makes when it is the constructor of another type, crashing mypy. This patch replaces the return type by UninhabitedType instead, which stops CallableType from considering itself as a constructor.
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.
Thanks for finding and fixing! This looks great :-)
mypy_primer also looks promising, but haven't yet confirmed it's correct
For my reference, this is the guard mentioned in the PR description:
Line 1773 in 401798f
def is_type_obj(self) -> bool: |
The mypy_primer diff boils down to the following example: from typing import Callable, ParamSpec, Union, Any
P = ParamSpec("P")
def wrapper(coro: Callable[P, int]) -> Callable[P, int]:
return coro
f: Union[Callable[[str], int], Any]
g = wrapper(f)
# Before: error: Argument 1 to "wrapper" has incompatible type "Union[Callable[[str], int], Any]"; expected "Callable[[VarArg(<nothing>), KwArg(<nothing>)], int]"
# After: No error
# --no-strict-optional: No error
reveal_type(g)
# Before: Revealed type is "def (*<nothing>, **<nothing>) -> int"
# After: Revealed type is "def (builtins.str) -> int"
# --no-strict-optional: Revealed type is "def (builtins.str) -> int" The main difference is that the constraint on |
Co-authored-by: Shantanu <12621235+hauntsaninja@users.noreply.github.com>
92f9899
to
5ff55dc
Compare
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.
Thanks again! I resolved a merge conflict, will merge once tests pass again
Diff from mypy_primer, showing the effect of this PR on open source code: discord.py (https://github.com/Rapptz/discord.py)
- discord/ext/commands/context.py:605: error: Argument 1 to "wrap_callback" has incompatible type "Callable[[Cog], Coroutine[Any, Any, None]]"; expected "Callable[[Mapping[Optional[Cog], List[Command[Any, [VarArg(Any), KwArg(Any)], Any]]]], Coroutine[Any, Any, None]]" [arg-type]
+ discord/ext/commands/context.py:605: error: Incompatible types in assignment (expression has type "Callable[[Cog], Coroutine[Any, Any, None]]", variable has type "Callable[[Mapping[Optional[Cog], List[Command[Any, [VarArg(Any), KwArg(Any)], Any]]]], Coroutine[Any, Any, None]]") [assignment]
- discord/ext/commands/context.py:608: error: Argument 1 to "wrap_callback" has incompatible type "Callable[[Group[Any, [VarArg(Any), KwArg(Any)], Any]], Coroutine[Any, Any, None]]"; expected "Callable[[Mapping[Optional[Cog], List[Command[Any, [VarArg(Any), KwArg(Any)], Any]]]], Coroutine[Any, Any, None]]" [arg-type]
+ discord/ext/commands/context.py:608: error: Incompatible types in assignment (expression has type "Callable[[Group[Any, [VarArg(Any), KwArg(Any)], Any]], Coroutine[Any, Any, None]]", variable has type "Callable[[Mapping[Optional[Cog], List[Command[Any, [VarArg(Any), KwArg(Any)], Any]]]], Coroutine[Any, Any, None]]") [assignment]
- discord/ext/commands/context.py:611: error: Argument 1 to "wrap_callback" has incompatible type "Callable[[Command[Any, [VarArg(Any), KwArg(Any)], Any]], Coroutine[Any, Any, None]]"; expected "Callable[[Mapping[Optional[Cog], List[Command[Any, [VarArg(Any), KwArg(Any)], Any]]]], Coroutine[Any, Any, None]]" [arg-type]
+ discord/ext/commands/context.py:611: error: Incompatible types in assignment (expression has type "Callable[[Command[Any, [VarArg(Any), KwArg(Any)], Any]], Coroutine[Any, Any, None]]", variable has type "Callable[[Mapping[Optional[Cog], List[Command[Any, [VarArg(Any), KwArg(Any)], Any]]]], Coroutine[Any, Any, None]]") [assignment]
- discord/ext/commands/core.py:641: error: Argument 1 to "wrap_callback" has incompatible type "Union[Callable[[Context[BotT], Exception], Coroutine[Any, Any, None]], Any]"; expected "Callable[[VarArg(<nothing>), KwArg(<nothing>)], Coroutine[Any, Any, Optional[Any]]]" [arg-type]
- discord/ext/commands/core.py:642: error: Argument 1 has incompatible type "Context[BotT]"; expected <nothing> [arg-type]
- discord/ext/commands/core.py:642: error: Argument 2 has incompatible type "CommandError"; expected <nothing> [arg-type]
- discord/ext/commands/core.py:1271: error: Argument 1 to "maybe_coroutine" has incompatible type "Union[Callable[[Context[BotT]], bool], Any]"; expected "Callable[[VarArg(<nothing>), KwArg(<nothing>)], Union[Any, Awaitable[Any]]]" [arg-type]
- discord/ext/commands/core.py:1271: error: Argument 2 to "maybe_coroutine" has incompatible type "Context[BotT]"; expected <nothing> [arg-type]
+ discord/ext/commands/core.py:1271: error: Argument 2 to "maybe_coroutine" has incompatible type "Context[BotT]"; expected "Context[BotT]" [arg-type]
|
Most types can be considered as callables, constructing the type itself. When a constraint was created for a ParamSpec variable, the return type would be set to NoneType, which conflicts with assumptions that CallableType makes when it is the constructor of another type, crashing mypy. This patch replaces the return type by UninhabitedType instead, which stops CallableType from considering itself as a constructor.