16
16
//
17
17
// ===----------------------------------------------------------------------===//
18
18
#include " TypeChecker.h"
19
+ #include " swift/AST/ExistentialLayout.h"
19
20
#include " swift/AST/Initializer.h"
20
21
#include " swift/AST/NameLookup.h"
21
22
#include " swift/AST/ProtocolConformance.h"
@@ -120,27 +121,48 @@ namespace {
120
121
if (!Options.contains (NameLookupFlags::ProtocolMembers) ||
121
122
!isa<ProtocolDecl>(foundDC) ||
122
123
isa<GenericTypeParamDecl>(found) ||
123
- (isa<FuncDecl>(found) && cast<FuncDecl>(found)->isOperator ()) ||
124
- foundInType->isAnyExistentialType ()) {
124
+ (isa<FuncDecl>(found) && cast<FuncDecl>(found)->isOperator ())) {
125
125
addResult (found);
126
126
return ;
127
127
}
128
128
129
129
assert (isa<ProtocolDecl>(foundDC));
130
130
131
+ auto conformingType = foundInType;
132
+
133
+ // When performing a lookup on a subclass existential, we might
134
+ // find a member of the class that witnesses a requirement on a
135
+ // protocol that the class conforms to.
136
+ //
137
+ // Since subclass existentials don't normally conform to protocols,
138
+ // pull out the superclass instead, and use that below.
139
+ if (foundInType->isExistentialType ()) {
140
+ auto layout = foundInType->getExistentialLayout ();
141
+ if (layout.superclass )
142
+ conformingType = layout.superclass ;
143
+ }
144
+
131
145
// If we found something within the protocol itself, and our
132
146
// search began somewhere that is not in a protocol or extension
133
147
// thereof, remap this declaration to the witness.
134
148
if (foundInType->is <ArchetypeType>() ||
149
+ foundInType->isExistentialType () ||
135
150
Options.contains (NameLookupFlags::PerformConformanceCheck)) {
136
151
// Dig out the protocol conformance.
137
- auto conformance = TC.conformsToProtocol (foundInType , foundProto, DC,
152
+ auto conformance = TC.conformsToProtocol (conformingType , foundProto, DC,
138
153
conformanceOptions);
139
- if (!conformance)
154
+ if (!conformance) {
155
+ // If there's no conformance, we have an existential
156
+ // and we found a member from one of the protocols, and
157
+ // not a class constraint if any.
158
+ assert (foundInType->isExistentialType ());
159
+ addResult (found);
140
160
return ;
161
+ }
141
162
142
163
if (conformance->isAbstract ()) {
143
- assert (foundInType->is <ArchetypeType>());
164
+ assert (foundInType->is <ArchetypeType>() ||
165
+ foundInType->isExistentialType ());
144
166
addResult (found);
145
167
return ;
146
168
}
@@ -161,6 +183,10 @@ namespace {
161
183
162
184
// FIXME: the "isa<ProtocolDecl>()" check will be wrong for
163
185
// default implementations in protocols.
186
+ //
187
+ // If we have an imported conformance or the witness could
188
+ // not be deserialized, getWitnessDecl() will just return
189
+ // the requirement, so just drop the lookup result here.
164
190
if (witness && !isa<ProtocolDecl>(witness->getDeclContext ()))
165
191
addResult (witness);
166
192
0 commit comments