@@ -864,27 +864,35 @@ class OverrideFilteringConsumer : public VisibleDeclConsumer {
864
864
865
865
struct KeyPathDynamicMemberConsumer : public VisibleDeclConsumer {
866
866
VisibleDeclConsumer &consumer;
867
- std::function<bool (DeclBaseName)> seenBaseName;
867
+ std::function<bool (DeclBaseName)> seenStaticBaseName;
868
+ llvm::DenseSet<DeclBaseName> seen;
868
869
869
870
SubscriptDecl *currentSubscript = nullptr ;
870
871
Type currentBaseType = Type();
871
872
872
873
KeyPathDynamicMemberConsumer (VisibleDeclConsumer &consumer,
873
874
std::function<bool (DeclBaseName)> seenBaseName)
874
- : consumer(consumer), seenBaseName(std::move(seenBaseName)) {}
875
+ : consumer(consumer), seenStaticBaseName(std::move(seenBaseName)) {}
876
+
877
+ bool checkShadowed (ValueDecl *VD) {
878
+ // Dynamic lookup members are only visible if they are not shadowed by
879
+ // other members.
880
+ return !isa<SubscriptDecl>(VD) && seen.insert (VD->getBaseName ()).second &&
881
+ !seenStaticBaseName (VD->getBaseName ());
882
+ }
875
883
876
884
void foundDecl (ValueDecl *VD, DeclVisibilityKind reason,
877
885
DynamicLookupInfo dynamicLookupInfo) override {
886
+ assert (dynamicLookupInfo.getKind () !=
887
+ DynamicLookupInfo::KeyPathDynamicMember);
888
+
878
889
// Only variables and subscripts are allowed in a keypath.
879
890
if (!isa<AbstractStorageDecl>(VD))
880
891
return ;
881
892
882
- assert (dynamicLookupInfo.getKind () !=
883
- DynamicLookupInfo::KeyPathDynamicMember);
884
-
885
893
// Dynamic lookup members are only visible if they are not shadowed by
886
894
// non-dynamic members.
887
- if (isa<SubscriptDecl> (VD) || ! seenBaseName (VD-> getBaseName () ))
895
+ if (checkShadowed (VD))
888
896
consumer.foundDecl (VD, DeclVisibilityKind::DynamicLookup,
889
897
{currentSubscript, currentBaseType, reason});
890
898
}
@@ -913,7 +921,39 @@ static void lookupVisibleDynamicMemberLookupDecls(
913
921
Type baseType, KeyPathDynamicMemberConsumer &consumer,
914
922
const DeclContext *dc, LookupState LS, DeclVisibilityKind reason,
915
923
LazyResolver *typeResolver, GenericSignatureBuilder *GSB,
916
- VisitedSet &visited) {
924
+ VisitedSet &visited, llvm::DenseSet<TypeBase *> &seenDynamicLookup);
925
+
926
+ // / Enumerates all members of \c baseType, including both directly visible and
927
+ // / members visible by keypath dynamic member lookup.
928
+ // /
929
+ // / \note This is an implementation detail of \c lookupVisibleMemberDecls and
930
+ // / exists to create the correct recursion for dynamic member lookup.
931
+ static void lookupVisibleMemberAndDynamicMemberDecls (
932
+ Type baseType, VisibleDeclConsumer &consumer,
933
+ KeyPathDynamicMemberConsumer &dynamicMemberConsumer, const DeclContext *DC,
934
+ LookupState LS, DeclVisibilityKind reason, LazyResolver *typeResolver,
935
+ GenericSignatureBuilder *GSB, VisitedSet &visited,
936
+ llvm::DenseSet<TypeBase *> &seenDynamicLookup) {
937
+ lookupVisibleMemberDeclsImpl (baseType, consumer, DC, LS, reason, typeResolver,
938
+ GSB, visited);
939
+ lookupVisibleDynamicMemberLookupDecls (baseType, dynamicMemberConsumer, DC, LS,
940
+ reason, typeResolver, GSB, visited,
941
+ seenDynamicLookup);
942
+ }
943
+
944
+ // / Enumerates all keypath dynamic members of \c baseType, as seen from the
945
+ // / context \c dc.
946
+ // /
947
+ // / If \c baseType is \c @dynamicMemberLookup, this looks up any keypath
948
+ // / dynamic member subscripts and looks up the members of the keypath's root
949
+ // / type.
950
+ static void lookupVisibleDynamicMemberLookupDecls (
951
+ Type baseType, KeyPathDynamicMemberConsumer &consumer,
952
+ const DeclContext *dc, LookupState LS, DeclVisibilityKind reason,
953
+ LazyResolver *typeResolver, GenericSignatureBuilder *GSB,
954
+ VisitedSet &visited, llvm::DenseSet<TypeBase *> &seenDynamicLookup) {
955
+ if (!seenDynamicLookup.insert (baseType.getPointer ()).second )
956
+ return ;
917
957
918
958
if (!hasDynamicMemberLookupAttribute (baseType))
919
959
return ;
@@ -946,8 +986,9 @@ static void lookupVisibleDynamicMemberLookupDecls(
946
986
KeyPathDynamicMemberConsumer::SubscriptChange (consumer, subscript,
947
987
baseType);
948
988
949
- lookupVisibleMemberDeclsImpl (memberType, consumer, dc, LS, reason,
950
- typeResolver, GSB, visited);
989
+ lookupVisibleMemberAndDynamicMemberDecls (memberType, consumer, consumer, dc,
990
+ LS, reason, typeResolver, GSB,
991
+ visited, seenDynamicLookup);
951
992
}
952
993
}
953
994
@@ -963,15 +1004,14 @@ static void lookupVisibleMemberDecls(
963
1004
GenericSignatureBuilder *GSB) {
964
1005
OverrideFilteringConsumer overrideConsumer (BaseTy, CurrDC, TypeResolver);
965
1006
KeyPathDynamicMemberConsumer dynamicConsumer (
966
- overrideConsumer ,
1007
+ Consumer ,
967
1008
[&](DeclBaseName name) { return overrideConsumer.seenBaseName (name); });
968
1009
969
1010
VisitedSet Visited;
970
- lookupVisibleMemberDeclsImpl (BaseTy, overrideConsumer, CurrDC, LS, Reason,
971
- TypeResolver, GSB, Visited);
972
-
973
- lookupVisibleDynamicMemberLookupDecls (BaseTy, dynamicConsumer, CurrDC, LS,
974
- Reason, TypeResolver, GSB, Visited);
1011
+ llvm::DenseSet<TypeBase *> seenDynamicLookup;
1012
+ lookupVisibleMemberAndDynamicMemberDecls (
1013
+ BaseTy, overrideConsumer, dynamicConsumer, CurrDC, LS, Reason,
1014
+ TypeResolver, GSB, Visited, seenDynamicLookup);
975
1015
976
1016
// Report the declarations we found to the real consumer.
977
1017
for (const auto &DeclAndReason : overrideConsumer.DeclsToReport )
0 commit comments