Skip to content

ASTScope: Take start location into account when modeling local pattern bindings #34038

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 4 commits into from
Sep 25, 2020

Conversation

slavapestov
Copy link
Contributor

@slavapestov slavapestov commented Sep 23, 2020

Today, BraceStmtScope introduces all of its local bindings without regard to source order. Instead, let's model pattern bindings properly, by having the PatternEntryDeclScope introduce its bindings. Note that while PatternEntryInitializerScope is a child of the PatternEntryDeclScope, it's lookup parent skips over the PatternEntryDeclScope since bindings are not visible from their own initializer.

For example,

  var (x, y) = (0, 0), (u, v) = foo(x, y)

The names x and y are in scope immediately following (0, 0), and the names u and v are in scope immediately following foo(x, y).

Builds on top of #34039.

@slavapestov slavapestov changed the title Local pbd scopes ASTScope: Local pattern bindings begin a scope after the initializer expression Sep 23, 2020
@slavapestov slavapestov changed the title ASTScope: Local pattern bindings begin a scope after the initializer expression ASTScope: Take start location into account when modeling local pattern bindings Sep 23, 2020
@slavapestov slavapestov changed the base branch from master to main September 23, 2020 07:05
@slavapestov
Copy link
Contributor Author

@swift-ci Please smoke test

@slavapestov
Copy link
Contributor Author

@swift-ci Please test source compatibility

@slavapestov
Copy link
Contributor Author

@swift-ci Please smoke test

@slavapestov slavapestov force-pushed the local-pbd-scopes branch 2 times, most recently from 66bc234 to da55293 Compare September 23, 2020 22:46
@slavapestov
Copy link
Contributor Author

@swift-ci Please smoke test

Bindings are not visible from inside their own initializer, eg this
is invalid:

  var (x, y) = (y, x)

The PatternEntryDeclScope which starts after the 'var' introduces x
and y, and it contains the PatternEntryInitializerScope which starts
after the '='.

To model this properly in ASTScope, the PatternEntryInitializerScope
overrides getLookupParent() to skip the PatternEntryDeclScope that
contains it.

I believe this is simpler than having PatternEntryDeclScope begin
at the source location following the initializer, because it is hard
to compute this source location in a way that works with invalid
code, for example the 'var' might be nested inside of a BraceStmt
with the closing '}' missing.
… bindings

This gives us the desired behavior, where local bindings are in
scope after their definition.

Note that BraceStmt still introduces all bindings at the beginning,
but now we change BraceStmt to only introduce local functions and
types, allowing us to disable parse-time lookup.
@slavapestov
Copy link
Contributor Author

@swift-ci Please smoke test

@slavapestov
Copy link
Contributor Author

@swift-ci Please test source compatibility

/// If true, nest scopes so a variable is out of scope before its declaration
/// Does not handle capture rules for local functions properly.
/// If false don't push uses down into subscopes after decls.
static const bool handleUseBeforeDef = false;
Copy link
Contributor

Choose a reason for hiding this comment

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

This is the flag I've been talking about!

Comment on lines +758 to +760
ASTScopeAssert(isLocalBinding || insertionPoint == parentScope,
"Bindings at the top-level or members of types should "
"not change the insertion point");
Copy link
Contributor

Choose a reason for hiding this comment

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

Thanks!

Comment on lines +1042 to +1044
// In local context, the PatternEntryDeclScope becomes the insertion point, so
// that all any bindings introduecd by the pattern are in scope for subsequent
// lookups.
Copy link
Contributor

Choose a reason for hiding this comment

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

Nice and clear!

Copy link
Contributor

@davidungar davidungar left a comment

Choose a reason for hiding this comment

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

LGTM!

@slavapestov slavapestov merged commit 8e16b25 into swiftlang:main Sep 25, 2020
// CHECK-EXPANDED-NEXT: |-TypeAliasDeclScope {{.*}}, [15:1 - 15:15]
// CHECK-EXPANDED-NEXT: `-PatternEntryDeclScope {{.*}}, [13:5 - 21:28] entry 0 'c'
// CHECK-EXPANDED-NEXT: |-PatternEntryInitializerScope {{.*}}, [13:9 - 13:9] entry 0 'c'
// CHECK-EXPANDED-NEXT: |-TypeAliasDeclScope {{.*}}, [15:1 - 15:15]
Copy link
Collaborator

Choose a reason for hiding this comment

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

Note: It seems like the TypeAliasDeclScope got overindented along the way.

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.

3 participants