-
-
Notifications
You must be signed in to change notification settings - Fork 2.9k
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 an issubclass
failure for protocols with overloaded methods
#9904
Conversation
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 the fix!
Left an (optional) request to update the test case, otherwise looks good.
test-data/unit/check-protocols.test
Outdated
def meth(self, a): | ||
pass | ||
|
||
reveal_type(issubclass(int, POverload)) # N: Revealed type is 'builtins.bool' |
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.
Could you also add a concrete class (e.g., COverload
) that has a suitable overloaded method, and test that issubclass
can be used to narrow down from Type[Union[COverload, E]]
, similar to above around line 2218?
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.
So while trying the add the test you proposed I seem to have stumbled across another bug.
The if
block successfully narrows down the Union
to Type[COverload]
but the else
block
on the other hand fails to do the same with E
, revealing the type as the original Union
.
Would you happen to know where in mypy the type inference of if
/ else
statements is handled?
I imagine that change similar to non_method_protocol_members()
will have to be made there,
but I'm not quite sure where to look.
Examples
class COverload:
x: str
@overload
def meth(self, a: int) -> float: ...
@overload
def meth(self, a: str) -> Sequence[float]: ...
def meth(self, a):
pass
cls_overload: Type[Union[COverload, E]]
if issubclass(cls_overload, POverload):
reveal_type(cls_overload) # N: Revealed type is 'Type[__main__.COverload]'
else:
reveal_type(cls_overload) # N: Revealed type is 'Type[__main__.E]'
The test output:
Expected:
...
main:45: note: Revealed type is 'Type[__main__.COverload]'
main:47: note: Revealed type is 'Type[__main__.E]' (diff)
Actual:
...
main:45: note: Revealed type is 'Type[__main__.COverload]'
main:47: note: Revealed type is 'Union[Type[__main__.COverload], Type[__main__.E]]' (diff)
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.
Could you please open a new issue about it?
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.
Could you please open a new issue about it?
I just created an issue at #12228.
issubclass
failure for protocols with overloaded methodsissubclass
failure for protocols with overloaded methods
Passes all the tests now. Shall we merge this one? @hauntsaninja |
Jukka already approved it, so let's land it. |
Description
Mypy currently rejects
issubclass
checks for protocols containing non-method members.What I noticed is that this includes overloaded functions as well, the latter being incorrectly
identified as a "non-method" due to a missing
isinstance(typ, mypy.types.Overloaded)
check.This PR attempts to remedy aforementioned issue.
Examples
The
issubclass
behavior prior to this PR:Test Plan
A new
issubclass
test has been added for overload-containing protocols.