@@ -165,27 +165,25 @@ namespace {
165165// / Try to avoid situations where resolving the type of a witness calls back
166166// / into associated type inference.
167167struct TypeReprCycleCheckWalker : ASTWalker {
168+ ASTContext &ctx;
168169 llvm::SmallDenseSet<Identifier, 2 > circularNames;
169170 ValueDecl *witness;
170171 bool found;
171172
172173 TypeReprCycleCheckWalker (
174+ ASTContext &ctx,
173175 const llvm::SetVector<AssociatedTypeDecl *> &allUnresolved)
174- : witness(nullptr ), found(false ) {
176+ : ctx(ctx), witness(nullptr ), found(false ) {
175177 for (auto *assocType : allUnresolved) {
176178 circularNames.insert (assocType->getName ());
177179 }
178180 }
179181
180182 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.
187184
188185 if (auto *identTyR = dyn_cast<SimpleIdentTypeRepr>(T)) {
186+ // If we're inferring `Foo`, don't look at a witness mentioning `Foo`.
189187 if (circularNames.count (identTyR->getNameRef ().getBaseIdentifier ()) > 0 ) {
190188 // If unqualified lookup can find a type with this name without looking
191189 // into protocol members, don't skip the witness, since this type might
@@ -194,7 +192,6 @@ struct TypeReprCycleCheckWalker : ASTWalker {
194192 identTyR->getNameRef (), witness->getDeclContext (),
195193 identTyR->getLoc (), UnqualifiedLookupOptions ());
196194
197- auto &ctx = witness->getASTContext ();
198195 auto results =
199196 evaluateOrDefault (ctx.evaluator , UnqualifiedLookupRequest{desc}, {});
200197
@@ -207,6 +204,34 @@ struct TypeReprCycleCheckWalker : ASTWalker {
207204 }
208205 }
209206
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+
210235 return Action::Continue ();
211236 }
212237
@@ -296,7 +321,7 @@ AssociatedTypeInference::inferTypeWitnessesViaValueWitnesses(
296321 abort ();
297322 }
298323
299- TypeReprCycleCheckWalker cycleCheck (allUnresolved);
324+ TypeReprCycleCheckWalker cycleCheck (dc-> getASTContext (), allUnresolved);
300325
301326 InferredAssociatedTypesByWitnesses result;
302327
0 commit comments