@@ -166,27 +166,25 @@ namespace {
166166// / Try to avoid situations where resolving the type of a witness calls back
167167// / into associated type inference.
168168struct TypeReprCycleCheckWalker : ASTWalker {
169+ ASTContext &ctx;
169170 llvm::SmallDenseSet<Identifier, 2 > circularNames;
170171 ValueDecl *witness;
171172 bool found;
172173
173174 TypeReprCycleCheckWalker (
175+ ASTContext &ctx,
174176 const llvm::SetVector<AssociatedTypeDecl *> &allUnresolved)
175- : witness(nullptr ), found(false ) {
177+ : ctx(ctx), witness(nullptr ), found(false ) {
176178 for (auto *assocType : allUnresolved) {
177179 circularNames.insert (assocType->getName ());
178180 }
179181 }
180182
181183 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.
188185
189186 if (auto *identTyR = dyn_cast<SimpleIdentTypeRepr>(T)) {
187+ // If we're inferring `Foo`, don't look at a witness mentioning `Foo`.
190188 if (circularNames.count (identTyR->getNameRef ().getBaseIdentifier ()) > 0 ) {
191189 // If unqualified lookup can find a type with this name without looking
192190 // into protocol members, don't skip the witness, since this type might
@@ -195,7 +193,6 @@ struct TypeReprCycleCheckWalker : ASTWalker {
195193 identTyR->getNameRef (), witness->getDeclContext (),
196194 identTyR->getLoc (), UnqualifiedLookupOptions ());
197195
198- auto &ctx = witness->getASTContext ();
199196 auto results =
200197 evaluateOrDefault (ctx.evaluator , UnqualifiedLookupRequest{desc}, {});
201198
@@ -208,6 +205,34 @@ struct TypeReprCycleCheckWalker : ASTWalker {
208205 }
209206 }
210207
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+
211236 return Action::Continue ();
212237 }
213238
@@ -362,7 +387,7 @@ AssociatedTypeInference::inferTypeWitnessesViaValueWitnesses(
362387 abort ();
363388 }
364389
365- TypeReprCycleCheckWalker cycleCheck (allUnresolved);
390+ TypeReprCycleCheckWalker cycleCheck (dc-> getASTContext (), allUnresolved);
366391
367392 InferredAssociatedTypesByWitnesses result;
368393
0 commit comments