@@ -273,6 +273,17 @@ class UnqualifiedLookupFactory {
273
273
// / the result.
274
274
void recordCompletionOfAScope ();
275
275
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
+
276
287
#pragma mark normal (non-ASTScope-based) lookup declarations
277
288
278
289
void lookupOperatorInDeclContexts (DCAndUnresolvedIsCascadingUse);
@@ -334,6 +345,7 @@ class UnqualifiedLookupFactory {
334
345
bool isOutsideBodyOfFunction (const AbstractFunctionDecl *const AFD) const ;
335
346
336
347
void addGenericParametersHereAndInEnclosingScopes (DeclContext *dc);
348
+ void addGenericParametersHereAndInEnclosingScopes (GenericParamList *);
337
349
338
350
// / Consume generic parameters
339
351
void addGenericParametersForFunction (AbstractFunctionDecl *AFD);
@@ -508,26 +520,23 @@ void UnqualifiedLookupFactory::lookInScopeForASTScopeLookup(
508
520
for (auto local : localBindings) {
509
521
Consumer.foundDecl (local, getLocalDeclVisibilityKind (state.scope ));
510
522
}
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 ();
516
526
517
527
// 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)
525
535
return ;
526
- }
527
536
528
537
// If there is a declaration context associated with this scope, we might
529
538
// want to look in it.
530
- lookIntoDeclarationContextForASTScopeLookup (state);
539
+ runIfNotDoneYet ([&] { lookIntoDeclarationContextForASTScopeLookup (state); } );
531
540
}
532
541
533
542
void UnqualifiedLookupFactory::lookIntoDeclarationContextForASTScopeLookup (
@@ -610,11 +619,10 @@ void UnqualifiedLookupFactory::lookIntoDeclarationContextForASTScopeLookup(
610
619
ResultFinderForSelfsConformances (
611
620
defaultNextState.selfDC ? defaultNextState.selfDC : scopeDC, scopeDC),
612
621
isCascadingUseResult, baseNLOptions, scopeDC);
613
- recordCompletionOfAScope ();
614
- if (isFirstResultEnough ())
615
- return ;
616
622
// Forget the 'self' declaration.
617
- lookInScopeForASTScopeLookup (defaultNextState.withSelfDC (nullptr ));
623
+ runIfNotDoneYet ([&] {
624
+ lookInScopeForASTScopeLookup (defaultNextState.withSelfDC (nullptr ));
625
+ });
618
626
}
619
627
620
628
#pragma mark context-based lookup definitions
@@ -664,22 +672,21 @@ void UnqualifiedLookupFactory::finishLookingInContext(
664
672
// because the member could still be named by qualifying it. But there is no
665
673
// corresponding way to qualify a generic parameter.
666
674
// So, look for genrics first.
667
- if (addGenericParameters == AddGenericParameters::Yes) {
675
+ if (addGenericParameters == AddGenericParameters::Yes)
668
676
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
+ });
683
690
}
684
691
685
692
void UnqualifiedLookupFactory::findResultsAndSaveUnavailables (
@@ -695,10 +702,11 @@ void UnqualifiedLookupFactory::lookupInModuleScopeContext(
695
702
DeclContext *dc, Optional<bool > isCascadingUse) {
696
703
if (auto SF = dyn_cast<SourceFile>(dc))
697
704
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
+ });
702
710
}
703
711
704
712
void UnqualifiedLookupFactory::lookupNamesIntroducedByPatternBindingInitializer (
@@ -720,18 +728,17 @@ void UnqualifiedLookupFactory::lookupNamesIntroducedByPatternBindingInitializer(
720
728
PatternBindingInitializer *PBI, ParamDecl *selfParam,
721
729
Optional<bool > isCascadingUse) {
722
730
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
+ });
735
742
}
736
743
737
744
void UnqualifiedLookupFactory::
@@ -784,61 +791,64 @@ void UnqualifiedLookupFactory::lookupNamesIntroducedByFunctionDecl(
784
791
void UnqualifiedLookupFactory::lookupNamesIntroducedByMemberFunction (
785
792
AbstractFunctionDecl *AFD, bool isCascadingUse) {
786
793
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
+ });
811
822
}
812
823
813
824
void UnqualifiedLookupFactory::lookupNamesIntroducedByPureFunction (
814
825
AbstractFunctionDecl *AFD, bool isCascadingUse) {
815
826
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
+ } );
824
835
}
825
836
826
837
827
838
void UnqualifiedLookupFactory::lookupNamesIntroducedByClosure (
828
839
AbstractClosureExpr *ACE, Optional<bool > isCascadingUse) {
829
- if (auto *CE = dyn_cast<ClosureExpr>(ACE)) {
840
+ if (auto *CE = dyn_cast<ClosureExpr>(ACE))
830
841
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
+ });
842
852
}
843
853
844
854
template <typename NominalTypeDeclOrExtensionDecl>
@@ -894,14 +904,12 @@ void UnqualifiedLookupFactory::lookForLocalVariablesIn(
894
904
895
905
namelookup::FindLocalVal localVal (SM, Loc, Consumer);
896
906
localVal.visit (AFD->getBody ());
897
- recordCompletionOfAScope ();
898
- if (isFirstResultEnough ())
899
- return ;
900
907
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
+ });
905
913
}
906
914
907
915
void UnqualifiedLookupFactory::lookForLocalVariablesIn (ClosureExpr *CE) {
@@ -912,12 +920,10 @@ void UnqualifiedLookupFactory::lookForLocalVariablesIn(ClosureExpr *CE) {
912
920
namelookup::FindLocalVal localVal (SM, Loc, Consumer);
913
921
if (auto body = CE->getBody ())
914
922
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
+ });
921
927
}
922
928
923
929
void UnqualifiedLookupFactory::lookForLocalVariablesIn (SourceFile *SF) {
@@ -928,7 +934,6 @@ void UnqualifiedLookupFactory::lookForLocalVariablesIn(SourceFile *SF) {
928
934
// local types.
929
935
namelookup::FindLocalVal localVal (SM, Loc, Consumer);
930
936
localVal.checkSourceFile (*SF);
931
- recordCompletionOfAScope ();
932
937
}
933
938
934
939
bool UnqualifiedLookupFactory::isOutsideBodyOfFunction (
@@ -956,16 +961,19 @@ void UnqualifiedLookupFactory::addGenericParametersHereAndInEnclosingScopes(
956
961
// Generics can be nested, so visit the generic list, innermost first.
957
962
// Cannot use DeclContext::forEachGenericContext because this code breaks out
958
963
// 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
+ }
964
966
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
+ });
969
977
}
970
978
971
979
void UnqualifiedLookupFactory::addGenericParametersForFunction (
@@ -974,7 +982,6 @@ void UnqualifiedLookupFactory::addGenericParametersForFunction(
974
982
if (GenericParams) {
975
983
namelookup::FindLocalVal localVal (SM, Loc, Consumer);
976
984
localVal.checkGenericParams (GenericParams);
977
- recordCompletionOfAScope ();
978
985
}
979
986
}
980
987
0 commit comments