Skip to content

Commit c56ab07

Browse files
committed
ASTScope: Add finishLookupInBraceStmt parameter to ASTScope::lookupLocalDecls()
This will be used to implement re-declaration checking for local declarations. Currently this is handled by parse-time lookup. To make it work with ASTScope, we need to perform lookups that look into the innermost local scope only; for example, this is an invalid redeclaration: do { let x = 321 let x = 123 } But the following is fine, even though both VarDecls are in the same *DeclContext*: do { let x = 321 do { let x = 123 } }
1 parent 17a0b41 commit c56ab07

File tree

3 files changed

+46
-10
lines changed

3 files changed

+46
-10
lines changed

include/swift/AST/NameLookup.h

Lines changed: 22 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -594,18 +594,33 @@ class AbstractASTScopeDeclConsumer {
594594
virtual ~AbstractASTScopeDeclConsumer() = default;
595595

596596
/// Called for every ValueDecl visible from the lookup.
597-
/// Returns true if the lookup can be stopped at this point.
598-
/// BaseDC is per legacy
597+
///
599598
/// Takes an array in order to batch the consumption before setting
600599
/// IndexOfFirstOuterResult when necessary.
600+
///
601+
/// \param baseDC either a type context or the local context of a
602+
/// `self` parameter declaration. See LookupResult for a discussion
603+
/// of type -vs- instance lookup results.
604+
///
605+
/// \return true if the lookup should be stopped at this point.
601606
virtual bool consume(ArrayRef<ValueDecl *> values, DeclVisibilityKind vis,
602607
NullablePtr<DeclContext> baseDC = nullptr) = 0;
603608

604-
/// Eventually this functionality should move into ASTScopeLookup
609+
/// Look for members of a nominal type or extension scope.
610+
///
611+
/// \return true if the lookup should be stopped at this point.
605612
virtual bool
606613
lookInMembers(DeclContext *const scopeDC,
607614
NominalTypeDecl *const nominal) = 0;
608615

616+
/// Called right before looking at the parent scope of a BraceStmt.
617+
///
618+
/// \return true if the lookup should be stopped at this point.
619+
virtual bool
620+
finishLookupInBraceStmt(BraceStmt *stmt) {
621+
return false;
622+
}
623+
609624
#ifndef NDEBUG
610625
virtual void startingNextLookupStep() = 0;
611626
virtual void finishingLookup(std::string) const = 0;
@@ -661,7 +676,11 @@ class ASTScope {
661676

662677
/// Lookup that only finds local declarations and does not trigger
663678
/// interface type computation.
679+
///
680+
/// \param stopAfterInnermostBraceStmt If lookup should consider
681+
/// local declarations inside the innermost syntactic scope only.
664682
static void lookupLocalDecls(SourceFile *, DeclName, SourceLoc,
683+
bool stopAfterInnermostBraceStmt,
665684
SmallVectorImpl<ValueDecl *> &);
666685

667686
/// Returns the result if there is exactly one, nullptr otherwise.

lib/AST/ASTScopeLookup.cpp

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -383,7 +383,13 @@ bool BraceStmtScope::lookupLocalsOrMembers(DeclConsumer consumer) const {
383383
localBindings.push_back(vd);
384384
}
385385
}
386-
return consumer.consume(localBindings, DeclVisibilityKind::LocalVariable);
386+
if (consumer.consume(localBindings, DeclVisibilityKind::LocalVariable))
387+
return true;
388+
389+
if (consumer.finishLookupInBraceStmt(stmt))
390+
return true;
391+
392+
return false;
387393
}
388394

389395
bool PatternEntryInitializerScope::lookupLocalsOrMembers(

lib/AST/UnqualifiedLookup.cpp

Lines changed: 17 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -736,13 +736,16 @@ namespace {
736736

737737
class ASTScopeDeclConsumerForLocalLookup
738738
: public AbstractASTScopeDeclConsumer {
739-
SmallVectorImpl<ValueDecl *> &results;
740739
DeclName name;
740+
bool stopAfterInnermostBraceStmt;
741+
SmallVectorImpl<ValueDecl *> &results;
741742

742743
public:
743744
ASTScopeDeclConsumerForLocalLookup(
744-
SmallVectorImpl<ValueDecl *> &results, DeclName name)
745-
: results(results), name(name) {}
745+
DeclName name, bool stopAfterInnermostBraceStmt,
746+
SmallVectorImpl<ValueDecl *> &results)
747+
: name(name), stopAfterInnermostBraceStmt(stopAfterInnermostBraceStmt),
748+
results(results) {}
746749

747750
bool consume(ArrayRef<ValueDecl *> values, DeclVisibilityKind vis,
748751
NullablePtr<DeclContext> baseDC) override {
@@ -753,14 +756,18 @@ class ASTScopeDeclConsumerForLocalLookup
753756
results.push_back(value);
754757
}
755758

756-
return !results.empty();
759+
return (!stopAfterInnermostBraceStmt && !results.empty());
757760
}
758761

759762
bool lookInMembers(DeclContext *const,
760763
NominalTypeDecl *const) override {
761764
return true;
762765
}
763766

767+
bool finishLookupInBraceStmt(BraceStmt *stmt) override {
768+
return stopAfterInnermostBraceStmt;
769+
}
770+
764771
#ifndef NDEBUG
765772
void startingNextLookupStep() override {}
766773
void finishingLookup(std::string) const override {}
@@ -773,15 +780,19 @@ class ASTScopeDeclConsumerForLocalLookup
773780
/// Lookup that only finds local declarations and does not trigger
774781
/// interface type computation.
775782
void ASTScope::lookupLocalDecls(SourceFile *sf, DeclName name, SourceLoc loc,
783+
bool stopAfterInnermostBraceStmt,
776784
SmallVectorImpl<ValueDecl *> &results) {
777-
ASTScopeDeclConsumerForLocalLookup consumer(results, name);
785+
ASTScopeDeclConsumerForLocalLookup consumer(name, stopAfterInnermostBraceStmt,
786+
results);
778787
ASTScope::unqualifiedLookup(sf, loc, consumer);
779788
}
780789

781790
ValueDecl *ASTScope::lookupSingleLocalDecl(SourceFile *sf, DeclName name,
782791
SourceLoc loc) {
783792
SmallVector<ValueDecl *, 1> result;
784-
ASTScope::lookupLocalDecls(sf, name, loc, result);
793+
ASTScope::lookupLocalDecls(sf, name, loc,
794+
/*finishLookupInBraceStmt=*/false,
795+
result);
785796
if (result.size() != 1)
786797
return nullptr;
787798
return result[0];

0 commit comments

Comments
 (0)