Skip to content

Commit 8e16b25

Browse files
authored
Merge pull request #34038 from slavapestov/local-pbd-scopes
ASTScope: Take start location into account when modeling local pattern bindings
2 parents 8dbac48 + 5461508 commit 8e16b25

File tree

4 files changed

+45
-28
lines changed

4 files changed

+45
-28
lines changed

include/swift/AST/ASTScope.h

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -344,9 +344,6 @@ class ASTScopeImpl {
344344
virtual NullablePtr<ASTScopeImpl> insertionPointForDeferredExpansion();
345345
virtual SourceRange sourceRangeForDeferredExpansion() const;
346346

347-
public:
348-
bool isATypeDeclScope() const;
349-
350347
private:
351348
virtual ScopeCreator &getScopeCreator();
352349

@@ -435,6 +432,7 @@ class ASTScopeImpl {
435432
return p->getParent().isNonNull() ? p : nullptr;
436433
}
437434

435+
public:
438436
/// The tree is organized by source location and for most nodes this is also
439437
/// what obtaines for scoping. However, guards are different. The scope after
440438
/// the guard else must hop into the innermoset scope of the guard condition.
@@ -1079,6 +1077,7 @@ class PatternEntryDeclScope final : public AbstractPatternEntryScope {
10791077

10801078
protected:
10811079
bool lookupLocalsOrMembers(DeclConsumer) const override;
1080+
bool isLabeledStmtLookupTerminator() const override;
10821081
};
10831082

10841083
class PatternEntryInitializerScope final : public AbstractPatternEntryScope {
@@ -1093,6 +1092,7 @@ class PatternEntryInitializerScope final : public AbstractPatternEntryScope {
10931092

10941093
protected:
10951094
ASTScopeImpl *expandSpecifically(ScopeCreator &scopeCreator) override;
1095+
NullablePtr<const ASTScopeImpl> getLookupParent() const override;
10961096

10971097
private:
10981098
void expandAScopeThatDoesNotCreateANewInsertionPoint(ScopeCreator &);

lib/AST/ASTScopeCreation.cpp

Lines changed: 15 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -38,11 +38,6 @@
3838
using namespace swift;
3939
using namespace ast_scope;
4040

41-
/// If true, nest scopes so a variable is out of scope before its declaration
42-
/// Does not handle capture rules for local functions properly.
43-
/// If false don't push uses down into subscopes after decls.
44-
static const bool handleUseBeforeDef = false;
45-
4641
#pragma mark source range utilities
4742
static bool rangeableIsIgnored(const Decl *d) { return d->isImplicit(); }
4843
static bool rangeableIsIgnored(const Expr *d) {
@@ -746,11 +741,11 @@ class NodeAdder
746741
if (auto *var = patternBinding->getSingleVar())
747742
scopeCreator.addChildrenForKnownAttributes(var, parentScope);
748743

749-
const bool isInTypeDecl = parentScope->isATypeDeclScope();
744+
const bool isLocalBinding = patternBinding->getDeclContext()->isLocalContext();
750745

751746
const DeclVisibilityKind vis =
752-
isInTypeDecl ? DeclVisibilityKind::MemberOfCurrentNominal
753-
: DeclVisibilityKind::LocalVariable;
747+
isLocalBinding ? DeclVisibilityKind::LocalVariable
748+
: DeclVisibilityKind::MemberOfCurrentNominal;
754749
auto *insertionPoint = parentScope;
755750
for (auto i : range(patternBinding->getNumPatternEntries())) {
756751
insertionPoint =
@@ -759,9 +754,12 @@ class NodeAdder
759754
insertionPoint, patternBinding, i, vis)
760755
.getPtrOr(insertionPoint);
761756
}
762-
// If in a type decl, the type search will find these,
763-
// but if in a brace stmt, must continue under the last binding.
764-
return isInTypeDecl ? parentScope : insertionPoint;
757+
758+
ASTScopeAssert(isLocalBinding || insertionPoint == parentScope,
759+
"Bindings at the top-level or members of types should "
760+
"not change the insertion point");
761+
762+
return insertionPoint;
765763
}
766764

767765
NullablePtr<ASTScopeImpl> visitEnumElementDecl(EnumElementDecl *eed,
@@ -1041,11 +1039,13 @@ PatternEntryDeclScope::expandAScopeThatCreatesANewInsertionPoint(
10411039
scopeCreator.addChildrenForAllLocalizableAccessorsInSourceOrder(var, this);
10421040
});
10431041

1044-
ASTScopeAssert(!handleUseBeforeDef,
1045-
"next line is wrong otherwise; would need a use scope");
1042+
// In local context, the PatternEntryDeclScope becomes the insertion point, so
1043+
// that all any bindings introduecd by the pattern are in scope for subsequent
1044+
// lookups.
1045+
if (vis == DeclVisibilityKind::LocalVariable)
1046+
return {this, "All code that follows is inside this scope"};
10461047

1047-
return {getParent().get(), "When not handling use-before-def, succeeding "
1048-
"code just goes in the same scope as this one"};
1048+
return {getParent().get(), "Global and type members do not introduce scopes"};
10491049
}
10501050

10511051
void
@@ -1424,11 +1424,6 @@ AbstractPatternEntryScope::AbstractPatternEntryScope(
14241424
"out of bounds");
14251425
}
14261426

1427-
bool ASTScopeImpl::isATypeDeclScope() const {
1428-
Decl *const pd = getDeclIfAny().getPtrOrNull();
1429-
return pd && (isa<NominalTypeDecl>(pd) || isa<ExtensionDecl>(pd));
1430-
}
1431-
14321427
#pragma mark new operators
14331428
void *ASTScopeImpl::operator new(size_t bytes, const ASTContext &ctx,
14341429
unsigned alignment) {

lib/AST/ASTScopeLookup.cpp

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -271,6 +271,24 @@ bool GenericTypeOrExtensionScope::areMembersVisibleFromWhereClause() const {
271271
return isa<ProtocolDecl>(decl) || isa<ExtensionDecl>(decl);
272272
}
273273

274+
#pragma mark custom lookup parent behavior
275+
276+
NullablePtr<const ASTScopeImpl>
277+
PatternEntryInitializerScope::getLookupParent() const {
278+
auto parent = getParent().get();
279+
assert(parent->getClassName() == "PatternEntryDeclScope");
280+
281+
// Lookups from inside a pattern binding initializer skip the parent
282+
// scope that introduces bindings bound by the pattern, since we
283+
// want this to work:
284+
//
285+
// func f(x: Int) {
286+
// let x = x
287+
// print(x)
288+
// }
289+
return parent->getLookupParent();
290+
}
291+
274292
#pragma mark looking in locals or members - locals
275293

276294
bool GenericParamScope::lookupLocalsOrMembers(DeclConsumer consumer) const {
@@ -510,6 +528,10 @@ bool CaseStmtBodyScope::isLabeledStmtLookupTerminator() const {
510528
return false;
511529
}
512530

531+
bool PatternEntryDeclScope::isLabeledStmtLookupTerminator() const {
532+
return false;
533+
}
534+
513535
llvm::SmallVector<LabeledStmt *, 4>
514536
ASTScopeImpl::lookupLabeledStmts(SourceFile *sourceFile, SourceLoc loc) {
515537
// Find the innermost scope from which to start our search.

test/NameLookup/scope_map_top_level.swift

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -31,8 +31,8 @@ var i: Int = b.my_identity()
3131
// CHECK-EXPANDED-NEXT: `-NominalTypeBodyScope {{.*}}, [4:11 - 4:13]
3232
// CHECK-EXPANDED-NEXT: `-TopLevelCodeScope {{.*}}, [6:1 - 21:28]
3333
// CHECK-EXPANDED-NEXT: `-BraceStmtScope {{.*}}, [6:1 - 21:28]
34-
// CHECK-EXPANDED-NEXT: |-PatternEntryDeclScope {{.*}}, [6:5 - 6:15] entry 0 'a'
35-
// CHECK-EXPANDED-NEXT: `-PatternEntryInitializerScope {{.*}}, [6:15 - 6:15] entry 0 'a'
34+
// CHECK-EXPANDED-NEXT: `-PatternEntryDeclScope {{.*}}, [6:5 - 21:28] entry 0 'a'
35+
// CHECK-EXPANDED-NEXT: |-PatternEntryInitializerScope {{.*}}, [6:15 - 6:15] entry 0 'a'
3636
// CHECK-EXPANDED-NEXT: `-TopLevelCodeScope {{.*}}, [8:1 - 21:28]
3737
// CHECK-EXPANDED-NEXT: `-BraceStmtScope {{.*}}, [8:1 - 21:28]
3838
// CHECK-EXPANDED-NEXT: `-GuardStmtScope {{.*}}, [8:1 - 21:28]
@@ -46,9 +46,9 @@ var i: Int = b.my_identity()
4646
// CHECK-EXPANDED-NEXT: `-BraceStmtScope {{.*}}, [11:18 - 11:19]
4747
// CHECK-EXPANDED-NEXT: `-TopLevelCodeScope {{.*}}, [13:1 - 21:28]
4848
// CHECK-EXPANDED-NEXT: `-BraceStmtScope {{.*}}, [13:1 - 21:28]
49-
// CHECK-EXPANDED-NEXT: |-PatternEntryDeclScope {{.*}}, [13:5 - 13:9] entry 0 'c'
50-
// CHECK-EXPANDED-NEXT: `-PatternEntryInitializerScope {{.*}}, [13:9 - 13:9] entry 0 'c'
51-
// CHECK-EXPANDED-NEXT: |-TypeAliasDeclScope {{.*}}, [15:1 - 15:15]
49+
// CHECK-EXPANDED-NEXT: `-PatternEntryDeclScope {{.*}}, [13:5 - 21:28] entry 0 'c'
50+
// CHECK-EXPANDED-NEXT: |-PatternEntryInitializerScope {{.*}}, [13:9 - 13:9] entry 0 'c'
51+
// CHECK-EXPANDED-NEXT: |-TypeAliasDeclScope {{.*}}, [15:1 - 15:15]
5252
// CHECK-EXPANDED-NEXT: |-ExtensionDeclScope {{.*}}, [17:14 - 19:1]
5353
// CHECK-EXPANDED-NEXT: `-ExtensionBodyScope {{.*}}, [17:15 - 19:1]
5454
// CHECK-EXPANDED-NEXT: `-AbstractFunctionDeclScope {{.*}}, [18:3 - 18:43] 'my_identity()'

0 commit comments

Comments
 (0)