-
-
Notifications
You must be signed in to change notification settings - Fork 3.1k
New semantic analyzer: support named tuples #6330
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.
Looks good! Just one significant request (don't reanalyze if it was previously successful) and some minor things. The prior can be implemented in a separate PR.
|
@JukkaL Thanks for review! Because you merged your PR first, it was necessary to update my implementation logic for assignment based named tuples (basically it is much closer to class based one now). I however discovered couple small bugs:
I fixed them and added more tests. |
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 updates! Left some more comments.
mypy/newsemanal/semanal.py
Outdated
| return | ||
| # Yes, it's a valid namedtuple, but defer if it is not ready. | ||
| if not info: | ||
| self.add_symbol(name, PlaceholderNode(self.qualified_name(name), lvalue, True), |
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.
mark_incomplete adds a PlaceholderNode. The logic is a bit delicate so it's important that all additions go through the same implementation.
| while deferred and more_iterations: | ||
| iteration += 1 | ||
| if not incomplete or iteration == MAX_ITERATIONS: | ||
| if not (deferred or incomplete) or iteration == MAX_ITERATIONS: |
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.
A namespace can be deferred while it's incomplete. I think that we should also remove the namespace from incomplete namespaces if it's complete. Now it looks like that we sometimes don't remove the namespace from incomplete_namespaces even though we probably should.
test-data/unit/check-newsemanal.test
Outdated
| In = NamedTuple('In', [('s', str), ('t', Other)]) | ||
| class Other: pass | ||
|
|
||
| [case testNewAnalyzerNamedTupleMixed1] |
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.
Is there a specific reason for adding these tests? It will be impractical to test all combinations of features anyway, as the number of test cases will grow too quickly. For example, is this more useful than a mixed named tuple vs. typed dict test case? It may be better to only test combinations that are known to be risky or have been broken previously.
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.
Yes, these two tests cases were broken, but then the breakage had the same cause as for assignment based vs assignment based, so it is probably OK to remove them.
| defn.info._fullname = self.cur_mod_id + '.' + local_name | ||
| if defn.info.is_named_tuple: | ||
| # Module already correctly set for named tuples. | ||
| defn.info._fullname += '@' + str(defn.line) |
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 unclear why we need this special case. Even if the module was already correctly set, if it's always self.cur_mod_id, I think that it's better to avoid this if statement if it doesn't change behavior.
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.
As discussed elsewhere this is (unfortunately) actually needed.
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 updates! Looks good now, just one remaining nit.
mypy/newsemanal/semanal.py
Outdated
| name: The name that we weren't able to define (or '*' if the name is unknown) | ||
| node: The node that refers to the name (definition or lvalue) | ||
| becomes_typeinfo: Pass this to Placeholder (used by special forms like named tuples | ||
| that will create TypeInfos). |
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.
Style nit: we generally further indent the second line of argument decsriptions.
Fixes #6284
Fixes #6285
This doesn't add support for recursive definitions, but all the forward reference patterns that are supported in old semantic analyzer, should be also supported.
Some notes:
semanal_namedtuple.pyTypeInfos in multi-iteration scenario_NTto the bodies (otherwise type variable scope breaks), but it is probably fine because names starting with underscores are anyway prohibited in named tuples.