Skip to content
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

New semantic analyzer: Keep explicit type and inferred status in sync #6988

Merged
merged 3 commits into from
Jun 13, 2019

Conversation

ilevkivskyi
Copy link
Member

@ilevkivskyi ilevkivskyi commented Jun 13, 2019

This is (kind of) an actual fix for #6952

The problem is that previously unwrap_final() unconditionally set s.type to None for bare Final, even if the type was inferred from a simple literal r.h.s. on a previous iteration. At the same time lvalue.is_inferred_def remained False, so that the type was not inferred on the second iteration.

This way s.type and lvalue.is_inferred_def may get out of sync depending on the number of iterations, thus causing weird behavior in type checker.

I generally can say the current way of storing the inferred status is error-prone, but we already have #6458 to track this.

@@ -2118,6 +2118,8 @@ def unwrap_final(self, s: AssignmentStmt) -> bool:
return False
lval = s.lvalues[0]
assert isinstance(lval, RefExpr)
# Reset inferred status if it was set due to simple literal rvalue on previous iteration.
lval.is_inferred_def = s.type is None
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This seems error-prone and hard to reason about. For example, what happens if there are multiple assignments to a final name? How hard it would be to avoid the need to reset this (by not storing the bad value perhaps)?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What do you mean by "bad" value? The value of is_inferred_def is set correctly, but just few lines above we reset s.type to None, but not the flag. If we don't reset it together, s.type will stay None.

For example, what happens if there are multiple assignments to a final name?

There will be an inconsistency with old analyzer. But we anyway give an error. Also this can be fixed only doing the reset if lvalue.is_new_def.

Anyway, if you have a better fix, go ahead.

@ilevkivskyi ilevkivskyi deleted the fix-simple-literal branch June 13, 2019 16:38
@ilevkivskyi
Copy link
Member Author

After all we decided to go with a quick-fix.

@ilevkivskyi ilevkivskyi reopened this Jun 13, 2019
@ilevkivskyi
Copy link
Member Author

@JukkaL does this look acceptable?

Copy link
Collaborator

@JukkaL JukkaL left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks! Looks good. A more general fix may have to wait a bit, and this fixes an important use case.

@ilevkivskyi ilevkivskyi merged commit d90eb18 into python:master Jun 13, 2019
PattenR pushed a commit to PattenR/mypy that referenced this pull request Jun 23, 2019
python#6988)

This is (kind of) an actual fix for python#6952

The problem is that previously `unwrap_final()` unconditionally set `s.type` to `None` for bare `Final`, even if the type was inferred from a simple literal r.h.s. on a previous iteration. At the same time `lvalue.is_inferred_def` remained `False`, so that the type was not inferred on the second iteration.

This way `s.type` and `lvalue.is_inferred_def` may get out of sync depending on the number of iterations, thus causing weird behavior in type checker.

I generally can say the current way of storing the inferred status is error-prone, but we already have python#6458 to track this.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants