-
-
Notifications
You must be signed in to change notification settings - Fork 3.1k
Fix an issubclass failure for protocols with overloaded methods
#9904
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
JukkaL
left a comment
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
issubclasschecks 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
issubclassbehavior prior to this PR:Test Plan
A new
issubclasstest has been added for overload-containing protocols.