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