Skip to content

Change ConditionalTypeBinder to mainly use with statements - #1731

Merged
rwbarton merged 28 commits into
python:masterfrom
ecprice:typebinder
Jun 26, 2016
Merged

rwbarton merged 28 commits into
python:masterfrom
ecprice:typebinder

Conversation

@ecprice

@ecprice ecprice commented Jun 22, 2016

Copy link
Copy Markdown
Contributor

Rather than use binder.push_frame() and binder.pop_frame(*args),
you now do with binder.frame_context(*args). There was a previous
context manager used as with binder:, but it was only used in a few
places because it didn't support versatile enough options.

The rewrite exposed a number of bugs in the old implementation, which I have fixed and added tests for. It also exposed a bug with redefining functions, which I have not fixed; testRedefinedFunctionInTryWithElse is skipped for now.

For reviewing this, note that:

  • The last commit just moves the type binder code into its own file
  • Many of the changed lines only have changed indentation.

ecprice added 7 commits June 21, 2016 23:48
Rather than use `binder.push_frame()` and `binder.pop_frame(*args)`,
you now do `with binder.frame_context(*args)`.  There was a previous
context manager used as `with binder`, but it was only used in a few
places because it didn't support options.

In the process, I discovered several bugs in the old control flow
analysis; new test cases have been added to catch them.
This allows the context manager to deal with having multiple parallel
blocks that can break out separately.  It will clear the breaking_out
parameter and propagate variables to an enclosing frame only if
breaking_out wasn't True after falling off the frame.
Also make it share more code with while, and add a test case.
Previously if statements with else: and without else: had two
different code paths, and one had a bug.
It was only used once, so simpler to just do the logic there.
Having fallthrough and clear_breaking was confusing.
@JukkaL

JukkaL commented Jun 22, 2016

Copy link
Copy Markdown
Collaborator

Thanks for cleaning things up! I won't be able to review this until next week, as I'll be traveling the rest of the week. Perhaps @rwbarton can have a look?

@rwbarton

Copy link
Copy Markdown
Contributor

Yes, I've just been taking a look at the conditional type binder this past weekend, and I'd be happy to review this.

ecprice added 2 commits June 22, 2016 13:26
I realized that fall_through and clear_breaking really served the same
purpose, just one is for the parent and one is for the grandparent;
now there's just fall_through, which is an integer.
@ecprice
ecprice force-pushed the typebinder branch 2 times, most recently from bd2b757 to 427f3ea Compare June 23, 2016 05:25
Comment thread mypy/checker.py Outdated
# The first frame is special: it's the declared types of variables.
self.frames.append(Frame())
# We want a second frame that we can update.
self.frames.append(Frame())

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

I notice this second frame's parent is not the first frame. Is the first frame so special that it should just be a separate field of the binder object?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Yeah, that's probably right. Changed.

@rwbarton

Copy link
Copy Markdown
Contributor

Apparently when I commented from the individual commit view it shows up here as "commented on an outdated diff" here, so please make sure to expand all of those!

@ecprice
ecprice force-pushed the typebinder branch 2 times, most recently from ba7af85 to 8bafc26 Compare June 23, 2016 22:42
@rwbarton

Copy link
Copy Markdown
Contributor

Thanks a bunch for working on this! This already looks much better than the original version. I have some further clean-up/restructuring changes I'd like to make in the near future so it'd be great if we can land this one quickly.

The major points are

  • testRedefinedFunctionInTryWithElse needs to not crash mypy, at least. It's probably an extraction from a real program that uses this pattern with imports that may fail. If it's easy to make mypy do the right thing here, then great, otherwise it may be tolerable if we need # type: ignore comments for now.
  • The fix for the list comprehension scoping bug seems questionable to me. I'd prefer it if you removed that commit from this PR (since the bug is pre-existing anyways) and address the issue in a separate PR so it doesn't block this one.
  • The Frame.changed stuff is pretty confusing, which it looks like you've just addressed; I'll take a look at that now.

@ecprice

ecprice commented Jun 23, 2016 •

Copy link
Copy Markdown
Contributor Author

OK, I've dropped the questionable list comprehension change, and made mypy give a note rather than crash in the exposed test.

I've also dropped the move to another file until this lands. Note that runtests.py currently has a few errors (Cannot determine type of 'frame_context') but they will disappear once this is in its own file. (Not sure if there's a github issue for that)

@rwbarton

Copy link
Copy Markdown
Contributor

I've also dropped the move to another file until this lands.

Oh, just to make the PR easier to review? Or what? Not sure I follow.

@ecprice

ecprice commented Jun 24, 2016

Copy link
Copy Markdown
Contributor Author

Yeah, just until you think it's ready to commit. It's annoying to make changes with the move on top, since git isn't smart enough to rebase it.

x = B()
except:
pass
finally:

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Can you add a failing access x.b here so we can see that mypy doesn't just think the type of x is B?

@rwbarton

Copy link
Copy Markdown
Contributor

Okay, this looks good to me aside from a few minor test improvements. Please add the move commit back on top and I'll merge this.

@ecprice

ecprice commented Jun 24, 2016

Copy link
Copy Markdown
Contributor Author

Done.

Previously it cleared binder.breaking_out, but this had an issue with
return: we want to set binder.breaking_out before the complicated
logic there with multiple exit points, but evaluating boolean
expressions would clear the flag.
@ecprice

ecprice commented Jun 24, 2016

Copy link
Copy Markdown
Contributor Author

(I've added another commit fixing a bug.)

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.

4 participants