@@ -252,27 +252,36 @@ convertToUnqualifiedLookupOptions(NameLookupOptions options) {
252252 return newOptions;
253253}
254254
255+ // / HACK: Qualified lookup cannot be allowed to synthesize CodingKeys because
256+ // / it would lead to a number of egregious cycles through QualifiedLookupRequest
257+ // / when we resolve the protocol conformance. Codable's magic has pushed its way
258+ // / so deeply into the compiler, when doing unqualified lookup we have to
259+ // / pessimistically force every nominal context above this one to synthesize it
260+ // / in the event the user needs it from e.g. a non-primary input.
261+ // /
262+ // / We can undo this if Codable's semantic content is divorced from its
263+ // / syntactic content - so we synthesize just enough to allow lookups to
264+ // / succeed, but don't force protocol conformances while we're doing it.
265+ static void synthesizeCodingKeysIfNeededForUnqualifiedLookup (ASTContext &ctx,
266+ DeclContext *dc,
267+ DeclNameRef name) {
268+ if (name.getBaseIdentifier () != ctx.Id_CodingKeys )
269+ return ;
270+
271+ for (auto typeCtx = dc->getInnermostTypeContext (); typeCtx != nullptr ;
272+ typeCtx = typeCtx->getParent ()->getInnermostTypeContext ()) {
273+ if (auto *nominal = typeCtx->getSelfNominalTypeDecl ())
274+ nominal->synthesizeSemanticMembersIfNeeded (name.getFullName ());
275+ }
276+ }
277+
255278LookupResult TypeChecker::lookupUnqualified (DeclContext *dc, DeclNameRef name,
256279 SourceLoc loc,
257280 NameLookupOptions options) {
258281 auto &ctx = dc->getASTContext ();
259- // HACK: Qualified lookup cannot be allowed to synthesize CodingKeys because
260- // it would lead to a number of egregious cycles through
261- // QualifiedLookupRequest when we resolve the protocol conformance. Codable's
262- // magic has pushed its way so deeply into the compiler, we have to
263- // pessimistically force every nominal context above this one to synthesize
264- // it in the event the user needs it from e.g. a non-primary input.
265- // We can undo this if Codable's semantic content is divorced from its
266- // syntactic content - so we synthesize just enough to allow lookups to
267- // succeed, but don't force protocol conformances while we're doing it.
268- if (name.getBaseIdentifier () == ctx.Id_CodingKeys ) {
269- for (auto typeCtx = dc->getInnermostTypeContext (); typeCtx != nullptr ;
270- typeCtx = typeCtx->getParent ()->getInnermostTypeContext ()) {
271- if (auto *nominal = typeCtx->getSelfNominalTypeDecl ()) {
272- nominal->synthesizeSemanticMembersIfNeeded (name.getFullName ());
273- }
274- }
275- }
282+
283+ // HACK: Synthesize CodingKeys if needed.
284+ synthesizeCodingKeysIfNeededForUnqualifiedLookup (ctx, dc, name);
276285
277286 auto ulOptions = convertToUnqualifiedLookupOptions (options);
278287 auto descriptor = UnqualifiedLookupDescriptor (name, dc, loc, ulOptions);
@@ -314,6 +323,10 @@ TypeChecker::lookupUnqualifiedType(DeclContext *dc, DeclNameRef name,
314323 SourceLoc loc,
315324 NameLookupOptions options) {
316325 auto &ctx = dc->getASTContext ();
326+
327+ // HACK: Synthesize CodingKeys if needed.
328+ synthesizeCodingKeysIfNeededForUnqualifiedLookup (ctx, dc, name);
329+
317330 auto ulOptions = convertToUnqualifiedLookupOptions (options) |
318331 UnqualifiedLookupFlags::TypeLookup;
319332 {
0 commit comments