Skip to content

Function builders: pre-check the original closure body in-place #26286

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

Merged
merged 1 commit into from
Jul 23, 2019

Conversation

rjmccall
Copy link
Contributor

@rjmccall rjmccall commented Jul 23, 2019

Prior to this patch, we pre-checked the result of applying the function-builder transformation, but only when we hadn't already pre-checked the closure before. This causes two problems to arise when the transformation is applied to the same closure along multiple branches of a disjunction. The first is that any expressions that are synthesized by the transformation will not be pre-checked the second time through, which is a problem if we try to apply different builder types to the same closure (we do cache expressions for identical builder types). The second is that the pre-check will rewrite sub-expressions in place in the synthesized expression, which means that top-level expressions in the original closure body (including if conditions) that are now nested in the synthesized expression will not be rewritten in the original closure and therefore will be encountered in their raw state the second time through.

This patch causes all expressions in the original closure body to be pre-checked before doing any other work. We then pre-check the synthesized expression immediately before generating constraints for it in order to set up the AST appropriately for CSGen; this could be skipped if we just synthesized expressions the way that CSGen wants them, but that seems to be somewhat involved.

I've also merged the check for return statements into this same walk, which was convenient.

Pre-checking is safe to apply to an expression multiple times, so it's fine if we take this path and then decide not to use a function builder.

Fixes rdar://53325810 at least, and probably also some bugs with applying different function builders to the same closure.

@rjmccall
Copy link
Contributor Author

@swift-ci Please test.

Copy link
Member

@DougGregor DougGregor left a comment

Choose a reason for hiding this comment

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

Thank for you fixing this! LGTM

@swift-ci
Copy link
Contributor

Build failed
Swift Test OS X Platform
Git Sha - 136685a94e82193eb05e84c30086dcec60add846

@swift-ci
Copy link
Contributor

Build failed
Swift Test Linux Platform
Git Sha - 136685a94e82193eb05e84c30086dcec60add846

@rjmccall rjmccall force-pushed the precheck-function-builders branch from 136685a to 3891274 Compare July 23, 2019 04:06
@rjmccall
Copy link
Contributor Author

@swift-ci Please test.

@swift-ci
Copy link
Contributor

Build failed
Swift Test OS X Platform
Git Sha - 136685a94e82193eb05e84c30086dcec60add846

@swift-ci
Copy link
Contributor

Build failed
Swift Test Linux Platform
Git Sha - 136685a94e82193eb05e84c30086dcec60add846

Copy link
Contributor

@xedin xedin left a comment

Choose a reason for hiding this comment

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

LGTM!

return FunctionBuilderClosurePreCheck::Okay;
}

virtual std::pair<bool, Expr *> walkToExprPre(Expr *E) {
Copy link
Contributor

Choose a reason for hiding this comment

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

Nit: did you mean override instead of virtual here and in walkToStmtPre?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yes, I'll fix that. Thanks!

Prior to this patch, we pre-checked the result of applying the function-builder transformation, but only when we hadn't already pre-checked the closure before.  This causes two problems to arise when the transformation is applied to the same closure along multiple branches of a disjunction.  The first is that any expressions that are synthesized by the transformation will not be pre-checked the second time through, which is a problem if we try to apply different builder types to the same closure (we do cache expressions for identical builder types).  The second is that the pre-check will rewrite sub-expressions in place *in the synthesized expression*, which means that top-level expressions in the original closure body (including `if` conditions) that are now nested in the synthesized expression will not be rewritten in the original closure and therefore will be encountered in their raw state the second time through.

This patch causes all expressions in the original closure body to be pre-checked before doing any other work.  We then pre-check the synthesized expression immediately before generating constraints for it in order to set up the AST appropriately for CSGen; this could be skipped if we just synthesized expressions the way that CSGen wants them, but that seems to be somewhat involved.

Pre-checking is safe to apply to an expression multiple times, so it's
fine if we take this path and then decide not to use a function builder.

I've also merged the check for `return` statements into this same walk, which was convenient.

Fixes rdar://53325810 at least, and probably also some bugs with applying different function builders to the same closure.
@rjmccall rjmccall force-pushed the precheck-function-builders branch from 3891274 to 33fbfaf Compare July 23, 2019 05:53
@rjmccall
Copy link
Contributor Author

@swift-ci Please test.

@rjmccall
Copy link
Contributor Author

@swift-ci Please test source compatibility.

@swift-ci
Copy link
Contributor

Build failed
Swift Test Linux Platform
Git Sha - 3891274b2f389763958853f5094390967e865abc

@swift-ci
Copy link
Contributor

Build failed
Swift Test OS X Platform
Git Sha - 3891274b2f389763958853f5094390967e865abc

@rjmccall rjmccall merged commit 4fcac39 into swiftlang:master Jul 23, 2019
@rjmccall rjmccall deleted the precheck-function-builders branch July 23, 2019 15:23
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