Skip to content

Commit 95c4a97

Browse files
authored
Merge pull request #34135 from slavapestov/simulate-parser-lookup
Implement backward-compatible closure capture behavior with parser lookup disabled
2 parents 490cc13 + 3ec4ced commit 95c4a97

File tree

11 files changed

+233
-139
lines changed

11 files changed

+233
-139
lines changed

include/swift/AST/ASTScope.h

Lines changed: 21 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@
2929
#define SWIFT_AST_AST_SCOPE_H
3030

3131
#include "swift/AST/ASTNode.h"
32-
#include "swift/AST/NameLookup.h" // for DeclVisibilityKind
32+
#include "swift/AST/NameLookup.h"
3333
#include "swift/AST/SimpleRequest.h"
3434
#include "swift/Basic/Compiler.h"
3535
#include "swift/Basic/Debug.h"
@@ -444,7 +444,6 @@ class ASTScopeImpl {
444444
// It is not an instance variable or inherited type.
445445

446446
static bool lookupLocalBindingsInPattern(const Pattern *p,
447-
DeclVisibilityKind vis,
448447
DeclConsumer consumer);
449448

450449
/// When lookup must stop before the outermost scope, return the scope to stop
@@ -1024,10 +1023,10 @@ class AbstractPatternEntryScope : public ASTScopeImpl {
10241023
public:
10251024
PatternBindingDecl *const decl;
10261025
const unsigned patternEntryIndex;
1027-
const DeclVisibilityKind vis;
1026+
const bool isLocalBinding;
10281027

10291028
AbstractPatternEntryScope(PatternBindingDecl *, unsigned entryIndex,
1030-
DeclVisibilityKind);
1029+
bool);
10311030
virtual ~AbstractPatternEntryScope() {}
10321031

10331032
const PatternBindingEntry &getPatternEntry() const;
@@ -1044,8 +1043,8 @@ class AbstractPatternEntryScope : public ASTScopeImpl {
10441043
class PatternEntryDeclScope final : public AbstractPatternEntryScope {
10451044
public:
10461045
PatternEntryDeclScope(PatternBindingDecl *pbDecl, unsigned entryIndex,
1047-
DeclVisibilityKind vis)
1048-
: AbstractPatternEntryScope(pbDecl, entryIndex, vis) {}
1046+
bool isLocalBinding)
1047+
: AbstractPatternEntryScope(pbDecl, entryIndex, isLocalBinding) {}
10491048
virtual ~PatternEntryDeclScope() {}
10501049

10511050
protected:
@@ -1072,8 +1071,8 @@ class PatternEntryInitializerScope final : public AbstractPatternEntryScope {
10721071

10731072
public:
10741073
PatternEntryInitializerScope(PatternBindingDecl *pbDecl, unsigned entryIndex,
1075-
DeclVisibilityKind vis)
1076-
: AbstractPatternEntryScope(pbDecl, entryIndex, vis),
1074+
bool isLocalBinding)
1075+
: AbstractPatternEntryScope(pbDecl, entryIndex, isLocalBinding),
10771076
initAsWrittenWhenCreated(pbDecl->getOriginalInit(entryIndex)) {}
10781077
virtual ~PatternEntryInitializerScope() {}
10791078

@@ -1658,10 +1657,22 @@ class CaseStmtBodyScope final : public ASTScopeImpl {
16581657
};
16591658

16601659
class BraceStmtScope final : public AbstractStmtScope {
1660+
BraceStmt *const stmt;
1661+
1662+
/// Declarations which are in scope from the beginning of the statement.
1663+
SmallVector<ValueDecl *, 2> localFuncsAndTypes;
1664+
1665+
/// Declarations that are normally in scope only after their
1666+
/// definition.
1667+
SmallVector<VarDecl *, 2> localVars;
16611668

16621669
public:
1663-
BraceStmt *const stmt;
1664-
BraceStmtScope(BraceStmt *e) : stmt(e) {}
1670+
BraceStmtScope(BraceStmt *e,
1671+
SmallVector<ValueDecl *, 2> localFuncsAndTypes,
1672+
SmallVector<VarDecl *, 2> localVars)
1673+
: stmt(e),
1674+
localFuncsAndTypes(localFuncsAndTypes),
1675+
localVars(localVars) {}
16651676
virtual ~BraceStmtScope() {}
16661677

16671678
protected:

include/swift/AST/NameLookup.h

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -603,7 +603,7 @@ class AbstractASTScopeDeclConsumer {
603603
/// of type -vs- instance lookup results.
604604
///
605605
/// \return true if the lookup should be stopped at this point.
606-
virtual bool consume(ArrayRef<ValueDecl *> values, DeclVisibilityKind vis,
606+
virtual bool consume(ArrayRef<ValueDecl *> values,
607607
NullablePtr<DeclContext> baseDC = nullptr) = 0;
608608

609609
/// Look for members of a nominal type or extension scope.
@@ -613,6 +613,14 @@ class AbstractASTScopeDeclConsumer {
613613
lookInMembers(DeclContext *const scopeDC,
614614
NominalTypeDecl *const nominal) = 0;
615615

616+
/// Called for local VarDecls that might not yet be in scope.
617+
///
618+
/// Note that the set of VarDecls visited here are going to be a
619+
/// superset of those visited in consume().
620+
virtual bool consumePossiblyNotInScope(ArrayRef<VarDecl *> values) {
621+
return false;
622+
}
623+
616624
/// Called right before looking at the parent scope of a BraceStmt.
617625
///
618626
/// \return true if the lookup should be stopped at this point.
@@ -636,7 +644,7 @@ class ASTScopeDeclGatherer : public AbstractASTScopeDeclConsumer {
636644
public:
637645
virtual ~ASTScopeDeclGatherer() = default;
638646

639-
bool consume(ArrayRef<ValueDecl *> values, DeclVisibilityKind vis,
647+
bool consume(ArrayRef<ValueDecl *> values,
640648
NullablePtr<DeclContext> baseDC = nullptr) override;
641649

642650
/// Eventually this functionality should move into ASTScopeLookup

lib/AST/ASTScopeCreation.cpp

Lines changed: 36 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -667,10 +667,30 @@ class NodeAdder
667667

668668
NullablePtr<ASTScopeImpl> visitBraceStmt(BraceStmt *bs, ASTScopeImpl *p,
669669
ScopeCreator &scopeCreator) {
670+
SmallVector<ValueDecl *, 2> localFuncsAndTypes;
671+
SmallVector<VarDecl *, 2> localVars;
672+
673+
// All types and functions are visible anywhere within a brace statement
674+
// scope. When ordering matters (i.e. var decl) we will have split the brace
675+
// statement into nested scopes.
676+
for (auto braceElement : bs->getElements()) {
677+
if (auto localBinding = braceElement.dyn_cast<Decl *>()) {
678+
if (auto *vd = dyn_cast<ValueDecl>(localBinding)) {
679+
if (isa<FuncDecl>(vd) || isa<TypeDecl>(vd)) {
680+
localFuncsAndTypes.push_back(vd);
681+
} else if (auto *var = dyn_cast<VarDecl>(localBinding)) {
682+
localVars.push_back(var);
683+
}
684+
}
685+
}
686+
}
687+
670688
auto maybeBraceScope =
671-
scopeCreator.ifUniqueConstructExpandAndInsert<BraceStmtScope>(p, bs);
689+
scopeCreator.ifUniqueConstructExpandAndInsert<BraceStmtScope>(
690+
p, bs, std::move(localFuncsAndTypes), std::move(localVars));
672691
if (auto *s = scopeCreator.getASTContext().Stats)
673692
++s->getFrontendCounters().NumBraceStmtASTScopes;
693+
674694
return maybeBraceScope.getPtrOr(p);
675695
}
676696

@@ -681,23 +701,23 @@ class NodeAdder
681701
if (auto *var = patternBinding->getSingleVar())
682702
scopeCreator.addChildrenForKnownAttributes(var, parentScope);
683703

684-
const bool isLocalBinding = patternBinding->getDeclContext()->isLocalContext();
685-
686-
const DeclVisibilityKind vis =
687-
isLocalBinding ? DeclVisibilityKind::LocalVariable
688-
: DeclVisibilityKind::MemberOfCurrentNominal;
689704
auto *insertionPoint = parentScope;
690705
for (auto i : range(patternBinding->getNumPatternEntries())) {
706+
bool isLocalBinding = false;
707+
if (auto *varDecl = patternBinding->getAnchoringVarDecl(i)) {
708+
isLocalBinding = varDecl->getDeclContext()->isLocalContext();
709+
}
710+
691711
insertionPoint =
692712
scopeCreator
693713
.ifUniqueConstructExpandAndInsert<PatternEntryDeclScope>(
694-
insertionPoint, patternBinding, i, vis)
714+
insertionPoint, patternBinding, i, isLocalBinding)
695715
.getPtrOr(insertionPoint);
696-
}
697716

698-
ASTScopeAssert(isLocalBinding || insertionPoint == parentScope,
699-
"Bindings at the top-level or members of types should "
700-
"not change the insertion point");
717+
ASTScopeAssert(isLocalBinding || insertionPoint == parentScope,
718+
"Bindings at the top-level or members of types should "
719+
"not change the insertion point");
720+
}
701721

702722
return insertionPoint;
703723
}
@@ -971,7 +991,7 @@ PatternEntryDeclScope::expandAScopeThatCreatesANewInsertionPoint(
971991
"Original inits are always after the '='");
972992
scopeCreator
973993
.constructExpandAndInsertUncheckable<PatternEntryInitializerScope>(
974-
this, decl, patternEntryIndex, vis);
994+
this, decl, patternEntryIndex, isLocalBinding);
975995
}
976996

977997
// Add accessors for the variables in this pattern.
@@ -982,7 +1002,7 @@ PatternEntryDeclScope::expandAScopeThatCreatesANewInsertionPoint(
9821002
// In local context, the PatternEntryDeclScope becomes the insertion point, so
9831003
// that all any bindings introduecd by the pattern are in scope for subsequent
9841004
// lookups.
985-
if (vis == DeclVisibilityKind::LocalVariable)
1005+
if (isLocalBinding)
9861006
return {this, "All code that follows is inside this scope"};
9871007

9881008
return {getParent().get(), "Global and type members do not introduce scopes"};
@@ -1358,8 +1378,9 @@ ASTScopeImpl *LabeledConditionalStmtScope::createNestedConditionalClauseScopes(
13581378

13591379
AbstractPatternEntryScope::AbstractPatternEntryScope(
13601380
PatternBindingDecl *declBeingScoped, unsigned entryIndex,
1361-
DeclVisibilityKind vis)
1362-
: decl(declBeingScoped), patternEntryIndex(entryIndex), vis(vis) {
1381+
bool isLocalBinding)
1382+
: decl(declBeingScoped), patternEntryIndex(entryIndex),
1383+
isLocalBinding(isLocalBinding) {
13631384
ASTScopeAssert(entryIndex < declBeingScoped->getPatternList().size(),
13641385
"out of bounds");
13651386
}

lib/AST/ASTScopeLookup.cpp

Lines changed: 22 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -222,7 +222,7 @@ bool ASTScopeImpl::lookInGenericParametersOf(
222222
SmallVector<ValueDecl *, 32> bindings;
223223
for (auto *param : paramList.get()->getParams())
224224
bindings.push_back(param);
225-
if (consumer.consume(bindings, DeclVisibilityKind::GenericParameter))
225+
if (consumer.consume(bindings))
226226
return true;
227227
return false;
228228
}
@@ -289,28 +289,26 @@ PatternEntryInitializerScope::getLookupParent() const {
289289

290290
bool GenericParamScope::lookupLocalsOrMembers(DeclConsumer consumer) const {
291291
auto *param = paramList->getParams()[index];
292-
return consumer.consume({param}, DeclVisibilityKind::GenericParameter);
292+
return consumer.consume({param});
293293
}
294294

295295
bool PatternEntryDeclScope::lookupLocalsOrMembers(DeclConsumer consumer) const {
296-
if (vis != DeclVisibilityKind::LocalVariable)
297-
return false; // look in self type will find this later
298-
return lookupLocalBindingsInPattern(getPattern(), vis, consumer);
296+
if (!isLocalBinding)
297+
return false;
298+
return lookupLocalBindingsInPattern(getPattern(), consumer);
299299
}
300300

301301
bool ForEachPatternScope::lookupLocalsOrMembers(DeclConsumer consumer) const {
302-
return lookupLocalBindingsInPattern(
303-
stmt->getPattern(), DeclVisibilityKind::LocalVariable, consumer);
302+
return lookupLocalBindingsInPattern(stmt->getPattern(), consumer);
304303
}
305304

306305
bool CaseLabelItemScope::lookupLocalsOrMembers(DeclConsumer consumer) const {
307-
return lookupLocalBindingsInPattern(
308-
item.getPattern(), DeclVisibilityKind::LocalVariable, consumer);
306+
return lookupLocalBindingsInPattern(item.getPattern(), consumer);
309307
}
310308

311309
bool CaseStmtBodyScope::lookupLocalsOrMembers(DeclConsumer consumer) const {
312310
for (auto *var : stmt->getCaseBodyVariablesOrEmptyArray())
313-
if (consumer.consume({var}, DeclVisibilityKind::LocalVariable))
311+
if (consumer.consume({var}))
314312
return true;
315313

316314
return false;
@@ -320,13 +318,12 @@ bool FunctionBodyScope::lookupLocalsOrMembers(
320318
DeclConsumer consumer) const {
321319
if (auto *paramList = decl->getParameters()) {
322320
for (auto *paramDecl : *paramList)
323-
if (consumer.consume({paramDecl}, DeclVisibilityKind::FunctionParameter))
321+
if (consumer.consume({paramDecl}))
324322
return true;
325323
}
326324

327325
if (decl->getDeclContext()->isTypeContext()) {
328-
return consumer.consume({decl->getImplicitSelfDecl()},
329-
DeclVisibilityKind::FunctionParameter);
326+
return consumer.consume({decl->getImplicitSelfDecl()});
330327
}
331328

332329
// Consider \c var t: T { (did/will/)get/set { ... t }}
@@ -335,7 +332,7 @@ bool FunctionBodyScope::lookupLocalsOrMembers(
335332
// then t needs to be found as a local binding:
336333
if (auto *accessor = dyn_cast<AccessorDecl>(decl)) {
337334
if (auto *storage = accessor->getStorage())
338-
if (consumer.consume({storage}, DeclVisibilityKind::LocalVariable))
335+
if (consumer.consume({storage}))
339336
return true;
340337
}
341338

@@ -346,7 +343,7 @@ bool SpecializeAttributeScope::lookupLocalsOrMembers(
346343
DeclConsumer consumer) const {
347344
if (auto *params = whatWasSpecialized->getGenericParams())
348345
for (auto *param : params->getParams())
349-
if (consumer.consume({param}, DeclVisibilityKind::GenericParameter))
346+
if (consumer.consume({param}))
350347
return true;
351348
return false;
352349
}
@@ -356,7 +353,7 @@ bool DifferentiableAttributeScope::lookupLocalsOrMembers(
356353
auto visitAbstractFunctionDecl = [&](AbstractFunctionDecl *afd) {
357354
if (auto *params = afd->getGenericParams())
358355
for (auto *param : params->getParams())
359-
if (consumer.consume({param}, DeclVisibilityKind::GenericParameter))
356+
if (consumer.consume({param}))
360357
return true;
361358
return false;
362359
};
@@ -371,20 +368,10 @@ bool DifferentiableAttributeScope::lookupLocalsOrMembers(
371368
}
372369

373370
bool BraceStmtScope::lookupLocalsOrMembers(DeclConsumer consumer) const {
374-
// All types and functions are visible anywhere within a brace statement
375-
// scope. When ordering matters (i.e. var decl) we will have split the brace
376-
// statement into nested scopes.
377-
//
378-
// Don't stop at the first one, there may be local funcs with same base name
379-
// and want them all.
380-
SmallVector<ValueDecl *, 32> localBindings;
381-
for (auto braceElement : stmt->getElements()) {
382-
if (auto localBinding = braceElement.dyn_cast<Decl *>()) {
383-
if (auto *vd = dyn_cast<ValueDecl>(localBinding))
384-
localBindings.push_back(vd);
385-
}
386-
}
387-
if (consumer.consume(localBindings, DeclVisibilityKind::LocalVariable))
371+
if (consumer.consume(localFuncsAndTypes))
372+
return true;
373+
374+
if (consumer.consumePossiblyNotInScope(localVars))
388375
return true;
389376

390377
if (consumer.finishLookupInBraceStmt(stmt))
@@ -400,18 +387,15 @@ bool PatternEntryInitializerScope::lookupLocalsOrMembers(
400387
decl->getInitContext(0));
401388
if (initContext) {
402389
if (auto *selfParam = initContext->getImplicitSelfDecl()) {
403-
return consumer.consume({selfParam},
404-
DeclVisibilityKind::FunctionParameter);
390+
return consumer.consume({selfParam});
405391
}
406392
}
407393
return false;
408394
}
409395

410396
bool CaptureListScope::lookupLocalsOrMembers(DeclConsumer consumer) const {
411397
for (auto &e : expr->getCaptureList()) {
412-
if (consumer.consume(
413-
{e.Var},
414-
DeclVisibilityKind::LocalVariable)) // or FunctionParameter??
398+
if (consumer.consume({e.Var}))
415399
return true;
416400
}
417401
return false;
@@ -420,26 +404,24 @@ bool CaptureListScope::lookupLocalsOrMembers(DeclConsumer consumer) const {
420404
bool ClosureParametersScope::lookupLocalsOrMembers(
421405
DeclConsumer consumer) const {
422406
for (auto param : *closureExpr->getParameters())
423-
if (consumer.consume({param}, DeclVisibilityKind::FunctionParameter))
407+
if (consumer.consume({param}))
424408
return true;
425409
return false;
426410
}
427411

428412
bool ConditionalClausePatternUseScope::lookupLocalsOrMembers(
429413
DeclConsumer consumer) const {
430-
return lookupLocalBindingsInPattern(
431-
pattern, DeclVisibilityKind::LocalVariable, consumer);
414+
return lookupLocalBindingsInPattern(pattern, consumer);
432415
}
433416

434417
bool ASTScopeImpl::lookupLocalBindingsInPattern(const Pattern *p,
435-
DeclVisibilityKind vis,
436418
DeclConsumer consumer) {
437419
if (!p)
438420
return false;
439421
bool isDone = false;
440422
p->forEachVariable([&](VarDecl *var) {
441423
if (!isDone)
442-
isDone = consumer.consume({var}, vis);
424+
isDone = consumer.consume({var});
443425
});
444426
return isDone;
445427
}

lib/AST/Decl.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1447,7 +1447,8 @@ void PatternBindingEntry::setInit(Expr *E) {
14471447
VarDecl *PatternBindingEntry::getAnchoringVarDecl() const {
14481448
SmallVector<VarDecl *, 8> variables;
14491449
getPattern()->collectVariables(variables);
1450-
assert(!variables.empty());
1450+
if (variables.empty())
1451+
return nullptr;
14511452
return variables[0];
14521453
}
14531454

0 commit comments

Comments
 (0)