-
-
Notifications
You must be signed in to change notification settings - Fork 3k
Tag Anys with their provenance #3786
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
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.
At a high level, I think this is a good approach. See comments for some initial feedback.
mypy/report.py
Outdated
line += ('{:>{}} ' * len(widths)).format(*itertools.chain(*zip(values, widths))) | ||
f.write(line + '\n') | ||
|
||
def _report_any_exprs(self) -> None: |
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.
Nit: this should probably go above the previous function.
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.
Yep!
mypy/report.py
Outdated
# On the following line, mypy complains about implicit generic Any and wants us to use | ||
# typing.Counter() instead of collections.Counter(). | ||
# We cannot use typing.Counter() because it doesn't work with python 3.5 and older. | ||
total_counter = collections.Counter() # 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.
Instead, give this # type: typing.Counter[str]
(or whatever the item type is, exactly).
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.
Done!
mypy/report.py
Outdated
def __init__(self, reports: Reports, output_dir: str) -> None: | ||
super().__init__(reports, output_dir) | ||
self.counts = {} # type: Dict[str, Tuple[int, int]] | ||
self.any_types_counter = {} # type: Dict[str, Any] |
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 should be precisely typed.
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.
Done!
mypy/report.py
Outdated
(TypeOfAny.special_form, "Special Form"), | ||
(TypeOfAny.from_another_any, "From Another Any"), | ||
]) # type: collections.OrderedDict[TypeOfAny, str] | ||
file_column_name = "Name" |
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 wonder if the rest of this function could be abstracted out/combined with similar looking code from the function below.
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.
Done! I think code is much cleaner now :)
mypy/checker.py
Outdated
return True | ||
else: | ||
gt = self.named_generic_type('typing.Generator', [AnyType(), AnyType(), AnyType()]) | ||
# todo: is type of this Any correct? |
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.
These Any
s don't escape the function -- special form seems right here.
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.
Done!
try: | ||
agt = self.named_generic_type('typing.AsyncGenerator', [AnyType(), AnyType()]) | ||
# todo: is type of this Any correct? | ||
any_type = AnyType(TypeOfAny.special_form) |
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 Any
doesn't escape the function -- special form seems right here.
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.
Done!
# (However, see https://github.com/python/mypy/issues/1933) | ||
return AnyType() | ||
# todo: is type of this Any correct? | ||
return AnyType(TypeOfAny.special_form) |
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's not clear to me that this should even return Any
, but I think special form is fine here.
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.
Done!
mypy/subtypes.py
Outdated
else: | ||
iter_type = AnyType() | ||
# todo: is type of this Any correct? | ||
iter_type = AnyType(TypeOfAny.from_error) |
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 should be special form.
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 that ideally this should be assert False
, since all these types have one type parameter and types with incorrect type argument numbers (e.g. zero) should be "patched" in the third pass of semantic analysis. There were some efforts recently to weed out all instances with incorrect type argument count (including test fixtures), but maybe some are still there.
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.
@ilevkivskyi, hmm I see. I think it's better to have a separate PR for that one. This doesn't seem to be relevant to this PR and this PR is already huge.
# Conflicts: # mypy/checker.py
All right, all code review feedback should be addressed now! |
mypy/semanal.py
Outdated
node = sym.node | ||
assert isinstance(node, TypeInfo) | ||
return Instance(node, [AnyType()] * len(node.defn.type_vars)) | ||
return Instance(node, [AnyType(TypeOfAny.implicit)] * len(node.defn.type_vars)) |
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 this should be special form.
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.
Done!
fdef.arg_kinds, | ||
[None if argument_elide_name(n) else n for n in fdef.arg_names], | ||
ret_type or AnyType(), | ||
ret_type or AnyType(TypeOfAny.implicit), |
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 this (and the other Any
in this function) should be special form.
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.
Done!
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.
Okay, after making this change, tests were failing, so I made them implicit again.
mypy/semanal.py
Outdated
# TODO: assert len(args) == len(node.defn.type_vars) | ||
return Instance(node, args) | ||
return Instance(node, [AnyType()] * len(node.defn.type_vars)) | ||
return Instance(node, [AnyType(TypeOfAny.implicit)] * len(node.defn.type_vars)) |
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 thiiiink this should be special form.
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.
Done!
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.
Let's do this.
(NewType is not supported in python 3.5.1)
👍 |
🎉 |
This PR tags each instance of
AnyType
with where it comes from.Each
Any
can be one (and only one) of the following:Any
in a type annotation)Any
comes from an unfollowed import)Any
comes from an ommitted generic suchs asAny
inList
)Any
comes from an error)Any
is created for internal mypy purposes)Plus, this PR contains an addition to
AnyExpressionsReport
to report most common "tags" of Anys (implicit, explicit, from_unimported_type, etc).Note that I was not able to identify some of the
Any
s, specifically,Any
s related to generators. I added a todo to each one with the following exact words(# todo: is type of this Any correct?
). All of these should probably be resolved until this PR is ready to be merged.Also, perhaps, it would be better to split the PR into two? (one would tag Anys with their provenance and the other PR would add the new kind of Any Exprs Report)