@@ -166,27 +166,25 @@ namespace {
166
166
// / Try to avoid situations where resolving the type of a witness calls back
167
167
// / into associated type inference.
168
168
struct TypeReprCycleCheckWalker : ASTWalker {
169
+ ASTContext &ctx;
169
170
llvm::SmallDenseSet<Identifier, 2 > circularNames;
170
171
ValueDecl *witness;
171
172
bool found;
172
173
173
174
TypeReprCycleCheckWalker (
175
+ ASTContext &ctx,
174
176
const llvm::SetVector<AssociatedTypeDecl *> &allUnresolved)
175
- : witness(nullptr ), found(false ) {
177
+ : ctx(ctx), witness(nullptr ), found(false ) {
176
178
for (auto *assocType : allUnresolved) {
177
179
circularNames.insert (assocType->getName ());
178
180
}
179
181
}
180
182
181
183
PreWalkAction walkToTypeReprPre (TypeRepr *T) override {
182
- // FIXME: We should still visit any generic arguments of this member type.
183
- // However, we want to skip 'Foo.Element' because the 'Element' reference is
184
- // not unqualified.
185
- if (auto *memberTyR = dyn_cast<MemberTypeRepr>(T)) {
186
- return Action::SkipChildren ();
187
- }
184
+ // FIXME: Visit generic arguments.
188
185
189
186
if (auto *identTyR = dyn_cast<SimpleIdentTypeRepr>(T)) {
187
+ // If we're inferring `Foo`, don't look at a witness mentioning `Foo`.
190
188
if (circularNames.count (identTyR->getNameRef ().getBaseIdentifier ()) > 0 ) {
191
189
// If unqualified lookup can find a type with this name without looking
192
190
// into protocol members, don't skip the witness, since this type might
@@ -195,7 +193,6 @@ struct TypeReprCycleCheckWalker : ASTWalker {
195
193
identTyR->getNameRef (), witness->getDeclContext (),
196
194
identTyR->getLoc (), UnqualifiedLookupOptions ());
197
195
198
- auto &ctx = witness->getASTContext ();
199
196
auto results =
200
197
evaluateOrDefault (ctx.evaluator , UnqualifiedLookupRequest{desc}, {});
201
198
@@ -208,6 +205,34 @@ struct TypeReprCycleCheckWalker : ASTWalker {
208
205
}
209
206
}
210
207
208
+ if (auto *memberTyR = dyn_cast<MemberTypeRepr>(T)) {
209
+ // If we're looking at a member type`Foo.Bar`, check `Foo` recursively.
210
+ auto *baseTyR = memberTyR->getBaseComponent ();
211
+ baseTyR->walk (*this );
212
+
213
+ // If we're inferring `Foo`, don't look at a witness mentioning `Self.Foo`.
214
+ if (auto *identTyR = dyn_cast<SimpleIdentTypeRepr>(baseTyR)) {
215
+ if (identTyR->getNameRef ().getBaseIdentifier () == ctx.Id_Self ) {
216
+ // But if qualified lookup can find a type with this name without
217
+ // looking into protocol members, don't skip the witness, since this
218
+ // type might be a candidate witness.
219
+ SmallVector<ValueDecl *, 2 > results;
220
+ witness->getInnermostDeclContext ()->lookupQualified (
221
+ witness->getDeclContext ()->getSelfTypeInContext (),
222
+ identTyR->getNameRef (), SourceLoc (), NLOptions (), results);
223
+
224
+ // Ok, resolving this member type would trigger associated type
225
+ // inference recursively. We're going to skip this witness.
226
+ if (results.empty ()) {
227
+ found = true ;
228
+ return Action::Stop ();
229
+ }
230
+ }
231
+ }
232
+
233
+ return Action::SkipChildren ();
234
+ }
235
+
211
236
return Action::Continue ();
212
237
}
213
238
@@ -362,7 +387,7 @@ AssociatedTypeInference::inferTypeWitnessesViaValueWitnesses(
362
387
abort ();
363
388
}
364
389
365
- TypeReprCycleCheckWalker cycleCheck (allUnresolved);
390
+ TypeReprCycleCheckWalker cycleCheck (dc-> getASTContext (), allUnresolved);
366
391
367
392
InferredAssociatedTypesByWitnesses result;
368
393
0 commit comments