-
-
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 crash involving explicit any flag and Required #12039
Fix crash involving explicit any flag and Required #12039
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.
I can't approve the workflow runs cause I'm not a mypy maintainer. (By the way, don't take these comments too seriously, I don't really know too much about mypy internals)
@@ -43,7 +43,7 @@ class Iterator(Iterable[T_co], Protocol): | |||
def __next__(self) -> T_co: pass | |||
|
|||
class Sequence(Iterable[T_co]): | |||
def __getitem__(self, n: Any) -> T_co: pass | |||
def __getitem__(self, n: Any) -> T_co: pass # type: ignore |
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.
Why is this # type ignore
d? Perhaps leave a note for future viewers?
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.
It has an Any and my new test case checks for explicit Any with typeddict stubs. Alternatively I could add silent import flag to the test case.
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.
What you now makes sense then, I suppose putting a specific code on the type: ignore
(like, if you run with --show-error-codes
it will tell you what code to put) would be appreciated. But I don't know if that's the style tests normally take so...
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 suppose putting a specific code on the type: ignore [...] would be appreciated
+1
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've added the error code. The code is vague [misc] so I included a comment too on which error it was.
@@ -360,6 +360,9 @@ def __repr__(self) -> str: | |||
else: | |||
return "NotRequired[{}]".format(self.item) | |||
|
|||
def accept(self, visitor: 'TypeVisitor[T]') -> T: |
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.
This feels icky, but I presume it's needed?
I think I would have preferred fixing this one layer up -- whatever is trying to figure out if this is a Required should maybe know (this only works if that one layer up is related to TypedDicts which it probably isn't).
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.
The caller is this function, https://github.com/python/mypy/blob/master/mypy/typeanal.py#L1304. It doesn't feel like that function should need to have knowledge of typeddicts/required. This function only wants to check does an Annotation include Any somewhere in it.
The caller above that is https://github.com/python/mypy/blob/master/mypy/semanal_typeddict.py#L305. This does look like a reasonable place. If you would prefer I have the typeddict semantic analyzer strip Required/NotRequired before calling explicit any check I can do that.
Also I appreciate the comments. This is my first pr/time looking at mypy's actual code. I've been using it for a while, but have never had a bug that looked small enough I could just do and this made me explore mypy code.
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 think either approach works:
- Your current approach is more broad and will generally fix the problem with accepting a Required anywhere, as long as just having the item accept it is what is always meant (it sounds like it might be).
- Just changing the function above is less broad but also has less chance of accidentally introducing subtly wrong behavior.
I think the "subtly wrong behavior" is so unlikely that whatever approach is easier will work.
Thanks for the PR @hmc-cs-mdrissi ! Looks like the underlying problem fixed here is that |
I notice that CC @erictraut - TypeGuard PEP author |
It would be nice if running mypy on itself would highlight that A cursory inspection of the mypy documentation suggests that mypy understands an "abstract method" in the context of explicitly-defined Abstract Base Classes. So it might be possible to mark |
Sadly I no longer remember enough of mypy internals to be useful here. There are several new maintainers though! |
Typeguard doesn't crash, but that's because it doesn't even check for explicit Any. This code, def foo(x: object) -> TypeGuard[Any]:
... when run with mypy --disallow-any-explicit produces no type errors. So looks like typeguard probably needs an accept and also to check for any. As for abstract method issue, that works. If I add abstractmethod + ABC to Type class it produces a type error for TypeGuardType. I'll work on a small separate pr for abstract class/method for accept. edit: The typeguard issue is less clear to me. Some debugging the reason typeguard explicit any checks does nothing is return type is normalized to bool before explicit Any check happens. I'll make a separate bug ticket for it and may take another look later. |
LGTM, with the new changes. I cannot merge this PR myself. @JukkaL ? |
Description
Fixes #12038. This adds an accept method to Required that delegates to the inner type. @davidfstr
Test Plan
I ran the tests locally and they passed. I added two small test cases to check-typeddict.test that correspond to fixed crash.