Skip to content

Commit cb8dd98

Browse files
committed
[Scope map] Cope with pattern binding accessor/initializer children in any order.
Semantic analysis produces implicit accessors that can show up before initializers (e.g., for initializers), and it’s reasonable for ill-formed code to do this as well, so be more tolerant of ordering issues here.
1 parent abf9bfe commit cb8dd98

File tree

3 files changed

+41
-7
lines changed

3 files changed

+41
-7
lines changed

lib/AST/ASTScope.cpp

Lines changed: 21 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -235,18 +235,35 @@ void ASTScope::expand() const {
235235
patternBinding.decl->getPatternList()[patternBinding.entry];
236236

237237
// Create a child for the initializer, if present.
238+
ASTScope *initChild = nullptr;
238239
if (patternEntry.getInit() &&
239-
patternEntry.getInit()->getSourceRange().isValid())
240-
addChild(new (ctx) ASTScope(ASTScopeKind::PatternInitializer, this,
241-
patternBinding.decl, patternBinding.entry));
240+
patternEntry.getInit()->getSourceRange().isValid()) {
241+
initChild = new (ctx) ASTScope(ASTScopeKind::PatternInitializer, this,
242+
patternBinding.decl, patternBinding.entry);
243+
}
242244

243245
// Create children for the accessors of any variables in the pattern that
244246
// have them.
245247
patternEntry.getPattern()->forEachVariable([&](VarDecl *var) {
246-
if (hasAccessors(var))
248+
if (hasAccessors(var)) {
249+
// If there is an initializer child that precedes this node (the
250+
// normal case), add teh initializer child first.
251+
if (initChild &&
252+
ctx.SourceMgr.isBeforeInBuffer(
253+
patternBinding.decl->getInit(patternBinding.entry)->getEndLoc(),
254+
var->getBracesRange().Start)) {
255+
addChild(initChild);
256+
initChild = nullptr;
257+
}
258+
247259
addChild(new (ctx) ASTScope(this, var));
260+
}
248261
});
249262

263+
// If an initializer child remains, add it now.
264+
if (initChild)
265+
addChild(initChild);
266+
250267
// If the pattern binding is in a local context, we nest the remaining
251268
// pattern bindings.
252269
if (patternBinding.decl->getDeclContext()->isLocalContext()) {

lib/AST/Decl.cpp

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -919,15 +919,23 @@ VarDecl *PatternBindingEntry::getAnchoringVarDecl() const {
919919
}
920920

921921
SourceRange PatternBindingEntry::getSourceRange() const {
922+
ASTContext *ctx = nullptr;
923+
922924
SourceLoc endLoc;
923925
getPattern()->forEachVariable([&](VarDecl *var) {
924926
auto accessorsEndLoc = var->getBracesRange().End;
925-
if (accessorsEndLoc.isValid()) endLoc = accessorsEndLoc;
927+
if (accessorsEndLoc.isValid()) {
928+
endLoc = accessorsEndLoc;
929+
if (!ctx) ctx = &var->getASTContext();
930+
}
926931
});
927932

928933
// Check the initializer.
929-
if (endLoc.isInvalid())
930-
endLoc = getOrigInitRange().End;
934+
SourceLoc initEndLoc = getOrigInitRange().End;
935+
if (initEndLoc.isValid() &&
936+
(endLoc.isInvalid() ||
937+
(ctx && ctx->SourceMgr.isBeforeInBuffer(endLoc, initEndLoc))))
938+
endLoc = initEndLoc;
931939

932940
// Check the pattern.
933941
if (endLoc.isInvalid())

test/NameBinding/scope_map_lookup.swift

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,3 +31,12 @@ extension P2 {
3131
return self
3232
}
3333
}
34+
35+
// Lazy properties
36+
class LazyProperties {
37+
init() {
38+
lazy var localvar = 42 // expected-error {{lazy is only valid for members of a struct or class}} {{5-10=}}
39+
localvar += 1
40+
_ = localvar
41+
}
42+
}

0 commit comments

Comments
 (0)