@@ -220,8 +220,26 @@ convertToUnqualifiedLookupOptions(NameLookupOptions options) {
220220LookupResult TypeChecker::lookupUnqualified (DeclContext *dc, DeclNameRef name,
221221 SourceLoc loc,
222222 NameLookupOptions options) {
223- auto ulOptions = convertToUnqualifiedLookupOptions (options);
224223 auto &ctx = dc->getASTContext ();
224+ // HACK: Qualified lookup cannot be allowed to synthesize CodingKeys because
225+ // it would lead to a number of egregious cycles through
226+ // QualifiedLookupRequest when we resolve the protocol conformance. Codable's
227+ // magic has pushed its way so deeply into the compiler, we have to
228+ // pessimistically force every nominal context above this one to synthesize
229+ // it in the event the user needs it from e.g. a non-primary input.
230+ // We can undo this if Codable's semantic content is divorced from its
231+ // syntactic content - so we synthesize just enough to allow lookups to
232+ // succeed, but don't force protocol conformances while we're doing it.
233+ if (name.getBaseIdentifier () == ctx.Id_CodingKeys ) {
234+ for (auto typeCtx = dc->getInnermostTypeContext (); typeCtx != nullptr ;
235+ typeCtx = typeCtx->getParent ()->getInnermostTypeContext ()) {
236+ if (auto *nominal = typeCtx->getSelfNominalTypeDecl ()) {
237+ nominal->synthesizeSemanticMembersIfNeeded (name.getFullName ());
238+ }
239+ }
240+ }
241+
242+ auto ulOptions = convertToUnqualifiedLookupOptions (options);
225243 auto descriptor = UnqualifiedLookupDescriptor (name, dc, loc, ulOptions);
226244 auto lookup = evaluateOrDefault (ctx.evaluator ,
227245 UnqualifiedLookupRequest{descriptor}, {});
0 commit comments