Skip to content

Commit 3c32a41

Browse files
author
David Ungar
committed
Introduce runIfNotDoneYet
1 parent 81c0299 commit 3c32a41

File tree

1 file changed

+124
-117
lines changed

1 file changed

+124
-117
lines changed

lib/AST/UnqualifiedLookup.cpp

Lines changed: 124 additions & 117 deletions
Original file line numberDiff line numberDiff line change
@@ -273,6 +273,17 @@ class UnqualifiedLookupFactory {
273273
/// the result.
274274
void recordCompletionOfAScope();
275275

276+
template <typename Fn> void runIfNotDoneYet(Fn fn) {
277+
recordCompletionOfAScope();
278+
if (!isFirstResultEnough())
279+
fn();
280+
}
281+
282+
template <typename Fn1, typename Fn2> void runIfNotDoneYet(Fn1 fn1, Fn2 fn2) {
283+
runIfNotDoneYet(fn1);
284+
runIfNotDoneYet(fn2);
285+
}
286+
276287
#pragma mark normal (non-ASTScope-based) lookup declarations
277288

278289
void lookupOperatorInDeclContexts(DCAndUnresolvedIsCascadingUse);
@@ -334,6 +345,7 @@ class UnqualifiedLookupFactory {
334345
bool isOutsideBodyOfFunction(const AbstractFunctionDecl *const AFD) const;
335346

336347
void addGenericParametersHereAndInEnclosingScopes(DeclContext *dc);
348+
void addGenericParametersHereAndInEnclosingScopes(GenericParamList *);
337349

338350
/// Consume generic parameters
339351
void addGenericParametersForFunction(AbstractFunctionDecl *AFD);
@@ -508,26 +520,23 @@ void UnqualifiedLookupFactory::lookInScopeForASTScopeLookup(
508520
for (auto local : localBindings) {
509521
Consumer.foundDecl(local, getLocalDeclVisibilityKind(state.scope));
510522
}
511-
512-
recordCompletionOfAScope();
513-
// If we found anything, we're done.
514-
if (isFirstResultEnough())
515-
return;
523+
const bool inBody =
524+
state.scope->getKind() == ASTScopeKind::AbstractFunctionBody &&
525+
state.scope->getAbstractFunctionDecl()->getDeclContext()->isTypeContext();
516526

517527
// When we are in the body of a method, get the 'self' declaration.
518-
if (state.scope->getKind() == ASTScopeKind::AbstractFunctionBody &&
519-
state.scope->getAbstractFunctionDecl()
520-
->getDeclContext()
521-
->isTypeContext()) {
522-
lookInScopeForASTScopeLookup(
523-
state.withSelfDC(state.scope->getAbstractFunctionDecl())
524-
.withParentScope());
528+
runIfNotDoneYet([&] {
529+
if (inBody)
530+
lookInScopeForASTScopeLookup(
531+
state.withSelfDC(state.scope->getAbstractFunctionDecl())
532+
.withParentScope());
533+
});
534+
if (inBody)
525535
return;
526-
}
527536

528537
// If there is a declaration context associated with this scope, we might
529538
// want to look in it.
530-
lookIntoDeclarationContextForASTScopeLookup(state);
539+
runIfNotDoneYet([&] { lookIntoDeclarationContextForASTScopeLookup(state); });
531540
}
532541

533542
void UnqualifiedLookupFactory::lookIntoDeclarationContextForASTScopeLookup(
@@ -610,11 +619,10 @@ void UnqualifiedLookupFactory::lookIntoDeclarationContextForASTScopeLookup(
610619
ResultFinderForSelfsConformances(
611620
defaultNextState.selfDC ? defaultNextState.selfDC : scopeDC, scopeDC),
612621
isCascadingUseResult, baseNLOptions, scopeDC);
613-
recordCompletionOfAScope();
614-
if (isFirstResultEnough())
615-
return;
616622
// Forget the 'self' declaration.
617-
lookInScopeForASTScopeLookup(defaultNextState.withSelfDC(nullptr));
623+
runIfNotDoneYet([&] {
624+
lookInScopeForASTScopeLookup(defaultNextState.withSelfDC(nullptr));
625+
});
618626
}
619627

620628
#pragma mark context-based lookup definitions
@@ -664,22 +672,21 @@ void UnqualifiedLookupFactory::finishLookingInContext(
664672
// because the member could still be named by qualifying it. But there is no
665673
// corresponding way to qualify a generic parameter.
666674
// So, look for genrics first.
667-
if (addGenericParameters == AddGenericParameters::Yes) {
675+
if (addGenericParameters == AddGenericParameters::Yes)
668676
addGenericParametersHereAndInEnclosingScopes(lookupContextForThisContext);
669-
if (isFirstResultEnough())
670-
return;
671-
}
672-
if (resultFinderForSelfsConformances) {
673-
findResultsAndSaveUnavailables(std::move(*resultFinderForSelfsConformances),
674-
*isCascadingUse, baseNLOptions,
675-
lookupContextForThisContext);
676-
recordCompletionOfAScope();
677-
if (isFirstResultEnough())
678-
return;
679-
}
680-
// Recurse into the next context.
681-
lookupNamesIntroducedBy(DCAndUnresolvedIsCascadingUse{
682-
lookupContextForThisContext->getParentForLookup(), isCascadingUse});
677+
678+
runIfNotDoneYet(
679+
[&] {
680+
if (resultFinderForSelfsConformances)
681+
findResultsAndSaveUnavailables(
682+
std::move(*resultFinderForSelfsConformances), *isCascadingUse,
683+
baseNLOptions, lookupContextForThisContext);
684+
},
685+
// Recurse into the next context.
686+
[&] {
687+
lookupNamesIntroducedBy(DCAndUnresolvedIsCascadingUse{
688+
lookupContextForThisContext->getParentForLookup(), isCascadingUse});
689+
});
683690
}
684691

685692
void UnqualifiedLookupFactory::findResultsAndSaveUnavailables(
@@ -695,10 +702,11 @@ void UnqualifiedLookupFactory::lookupInModuleScopeContext(
695702
DeclContext *dc, Optional<bool> isCascadingUse) {
696703
if (auto SF = dyn_cast<SourceFile>(dc))
697704
lookForLocalVariablesIn(SF);
698-
if (isFirstResultEnough())
699-
return;
700-
recordDependencyOnTopLevelName(dc, Name, isCascadingUse.getValueOr(true));
701-
lookupNonlocalsInModuleScopeContext(dc);
705+
runIfNotDoneYet([&] {
706+
// TODO: why isn't the following line unconditional?
707+
recordDependencyOnTopLevelName(dc, Name, isCascadingUse.getValueOr(true));
708+
lookupNonlocalsInModuleScopeContext(dc);
709+
});
702710
}
703711

704712
void UnqualifiedLookupFactory::lookupNamesIntroducedByPatternBindingInitializer(
@@ -720,18 +728,17 @@ void UnqualifiedLookupFactory::lookupNamesIntroducedByPatternBindingInitializer(
720728
PatternBindingInitializer *PBI, ParamDecl *selfParam,
721729
Optional<bool> isCascadingUse) {
722730
Consumer.foundDecl(selfParam, DeclVisibilityKind::FunctionParameter);
723-
recordCompletionOfAScope();
724-
if (isFirstResultEnough())
725-
return;
726-
DeclContext *const patternContainer = PBI->getParent();
727-
// clang-format off
728-
finishLookingInContext(
729-
AddGenericParameters::Yes,
730-
patternContainer,
731-
ResultFinderForSelfsConformances(PBI, patternContainer),
732-
resolveIsCascadingUse(PBI, isCascadingUse,
733-
/*onlyCareAboutFunctionBody=*/false));
734-
// clang-format on
731+
runIfNotDoneYet([&] {
732+
DeclContext *const patternContainer = PBI->getParent();
733+
// clang-format off
734+
finishLookingInContext(
735+
AddGenericParameters::Yes,
736+
patternContainer,
737+
ResultFinderForSelfsConformances(PBI, patternContainer),
738+
resolveIsCascadingUse(PBI, isCascadingUse,
739+
/*onlyCareAboutFunctionBody=*/false));
740+
// clang-format on
741+
});
735742
}
736743

737744
void UnqualifiedLookupFactory::
@@ -784,61 +791,64 @@ void UnqualifiedLookupFactory::lookupNamesIntroducedByFunctionDecl(
784791
void UnqualifiedLookupFactory::lookupNamesIntroducedByMemberFunction(
785792
AbstractFunctionDecl *AFD, bool isCascadingUse) {
786793
lookForLocalVariablesIn(AFD, isCascadingUse);
787-
if (isFirstResultEnough())
788-
return;
789-
// If we're inside a function context, we're about to move to
790-
// the parent DC, so we have to check the function's generic
791-
// parameters first.
792-
addGenericParametersForFunction(AFD);
793-
if (isFirstResultEnough())
794-
return;
795-
DeclContext *const fnDeclContext = AFD->getDeclContext();
796-
// If we're not in the body of the function (for example, we
797-
// might be type checking a default argument expression and
798-
// performing name lookup from there), the base declaration
799-
// is the nominal type, not 'self'.
800-
DeclContext *const BaseDC = isOutsideBodyOfFunction(AFD) ? fnDeclContext : AFD;
801-
// If we are inside of a method, check to see if there are any ivars in
802-
// scope, and if so, whether this is a reference to one of them.
803-
// FIXME: We should persist this information between lookups.
804-
// clang-format off
805-
finishLookingInContext(
806-
AddGenericParameters::Yes,
807-
AFD->getParent(),
808-
ResultFinderForSelfsConformances(BaseDC, fnDeclContext),
809-
isCascadingUse);
810-
// clang-format on
794+
runIfNotDoneYet(
795+
[&] {
796+
// If we're inside a function context, we're about to move to
797+
// the parent DC, so we have to check the function's generic
798+
// parameters first.
799+
// Cannot start here in finishLookingInContext because AFD's
800+
// getOuterParameters may be null even when AFD's parent has generics.
801+
addGenericParametersForFunction(AFD);
802+
},
803+
[&] {
804+
DeclContext *const fnDeclContext = AFD->getDeclContext();
805+
// If we're not in the body of the function (for example, we
806+
// might be type checking a default argument expression and
807+
// performing name lookup from there), the base declaration
808+
// is the nominal type, not 'self'.
809+
DeclContext *const BaseDC =
810+
isOutsideBodyOfFunction(AFD) ? fnDeclContext : AFD;
811+
// If we are inside of a method, check to see if there are any ivars in
812+
// scope, and if so, whether this is a reference to one of them.
813+
// FIXME: We should persist this information between lookups.
814+
// clang-format off
815+
finishLookingInContext(
816+
AddGenericParameters::Yes,
817+
AFD->getParent(),
818+
ResultFinderForSelfsConformances(BaseDC, fnDeclContext),
819+
isCascadingUse);
820+
// clang-format on
821+
});
811822
}
812823

813824
void UnqualifiedLookupFactory::lookupNamesIntroducedByPureFunction(
814825
AbstractFunctionDecl *AFD, bool isCascadingUse) {
815826
lookForLocalVariablesIn(AFD, isCascadingUse);
816-
if (isFirstResultEnough())
817-
return;
818-
// clang-format off
819-
finishLookingInContext(
820-
AddGenericParameters::Yes,
821-
AFD,
822-
None,
823-
isCascadingUse);
827+
runIfNotDoneYet([&] {
828+
// clang-format off
829+
finishLookingInContext(
830+
AddGenericParameters::Yes,
831+
AFD,
832+
None,
833+
isCascadingUse);
834+
});
824835
}
825836

826837

827838
void UnqualifiedLookupFactory::lookupNamesIntroducedByClosure(
828839
AbstractClosureExpr *ACE, Optional<bool> isCascadingUse) {
829-
if (auto *CE = dyn_cast<ClosureExpr>(ACE)) {
840+
if (auto *CE = dyn_cast<ClosureExpr>(ACE))
830841
lookForLocalVariablesIn(CE);
831-
if (isFirstResultEnough())
832-
return;
833-
}
834-
// clang-format off
835-
finishLookingInContext(
836-
AddGenericParameters::Yes,
837-
ACE,
838-
None,
839-
resolveIsCascadingUse(ACE, isCascadingUse,
840-
/*onlyCareAboutFunctionBody=*/false));
841-
// clang-format on
842+
runIfNotDoneYet([&] {
843+
// clang-format off
844+
finishLookingInContext(
845+
AddGenericParameters::Yes,
846+
ACE,
847+
None,
848+
resolveIsCascadingUse(ACE, isCascadingUse,
849+
/*onlyCareAboutFunctionBody=*/false));
850+
// clang-format on
851+
});
842852
}
843853

844854
template <typename NominalTypeDeclOrExtensionDecl>
@@ -894,14 +904,12 @@ void UnqualifiedLookupFactory::lookForLocalVariablesIn(
894904

895905
namelookup::FindLocalVal localVal(SM, Loc, Consumer);
896906
localVal.visit(AFD->getBody());
897-
recordCompletionOfAScope();
898-
if (isFirstResultEnough())
899-
return;
900907

901-
if (auto *P = AFD->getImplicitSelfDecl())
902-
localVal.checkValueDecl(P, DeclVisibilityKind::FunctionParameter);
903-
localVal.checkParameterList(AFD->getParameters());
904-
recordCompletionOfAScope();
908+
runIfNotDoneYet([&] {
909+
if (auto *P = AFD->getImplicitSelfDecl())
910+
localVal.checkValueDecl(P, DeclVisibilityKind::FunctionParameter);
911+
localVal.checkParameterList(AFD->getParameters());
912+
});
905913
}
906914

907915
void UnqualifiedLookupFactory::lookForLocalVariablesIn(ClosureExpr *CE) {
@@ -912,12 +920,10 @@ void UnqualifiedLookupFactory::lookForLocalVariablesIn(ClosureExpr *CE) {
912920
namelookup::FindLocalVal localVal(SM, Loc, Consumer);
913921
if (auto body = CE->getBody())
914922
localVal.visit(body);
915-
recordCompletionOfAScope();
916-
if (isFirstResultEnough())
917-
return;
918-
if (auto params = CE->getParameters())
919-
localVal.checkParameterList(params);
920-
recordCompletionOfAScope();
923+
runIfNotDoneYet([&] {
924+
if (auto params = CE->getParameters())
925+
localVal.checkParameterList(params);
926+
});
921927
}
922928

923929
void UnqualifiedLookupFactory::lookForLocalVariablesIn(SourceFile *SF) {
@@ -928,7 +934,6 @@ void UnqualifiedLookupFactory::lookForLocalVariablesIn(SourceFile *SF) {
928934
// local types.
929935
namelookup::FindLocalVal localVal(SM, Loc, Consumer);
930936
localVal.checkSourceFile(*SF);
931-
recordCompletionOfAScope();
932937
}
933938

934939
bool UnqualifiedLookupFactory::isOutsideBodyOfFunction(
@@ -956,16 +961,19 @@ void UnqualifiedLookupFactory::addGenericParametersHereAndInEnclosingScopes(
956961
// Generics can be nested, so visit the generic list, innermost first.
957962
// Cannot use DeclContext::forEachGenericContext because this code breaks out
958963
// if it finds a match and isFirstResultEnough()
959-
for (GenericParamList *dcGenericParams = getGenericParams(dc);
960-
dcGenericParams;
961-
dcGenericParams = dcGenericParams->getOuterParameters()) {
962-
namelookup::FindLocalVal localVal(SM, Loc, Consumer);
963-
localVal.checkGenericParams(dcGenericParams);
964+
addGenericParametersHereAndInEnclosingScopes(getGenericParams(dc));
965+
}
964966

965-
recordCompletionOfAScope();
966-
if (isFirstResultEnough())
967-
break;
968-
}
967+
void UnqualifiedLookupFactory::addGenericParametersHereAndInEnclosingScopes(
968+
GenericParamList *dcGenericParams) {
969+
if (!dcGenericParams)
970+
return;
971+
namelookup::FindLocalVal localVal(SM, Loc, Consumer);
972+
localVal.checkGenericParams(dcGenericParams);
973+
runIfNotDoneYet([&] {
974+
addGenericParametersHereAndInEnclosingScopes(
975+
dcGenericParams->getOuterParameters());
976+
});
969977
}
970978

971979
void UnqualifiedLookupFactory::addGenericParametersForFunction(
@@ -974,7 +982,6 @@ void UnqualifiedLookupFactory::addGenericParametersForFunction(
974982
if (GenericParams) {
975983
namelookup::FindLocalVal localVal(SM, Loc, Consumer);
976984
localVal.checkGenericParams(GenericParams);
977-
recordCompletionOfAScope();
978985
}
979986
}
980987

0 commit comments

Comments
 (0)