Skip to content

Commit a596f23

Browse files
authored
Merge pull request #79850 from hamishknight/key-hack
[Sema] Apply CodingKeys hack to `TypeChecker::lookupUnqualifiedType`
2 parents 7214717 + 7ae3ccf commit a596f23

File tree

2 files changed

+44
-17
lines changed

2 files changed

+44
-17
lines changed

lib/Sema/TypeCheckNameLookup.cpp

Lines changed: 30 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -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+
255278
LookupResult 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
{

test/IDE/complete_rdar146055457.swift

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
// RUN: %batch-code-completion
2+
3+
// rdar://146055457 - Make sure we synthesize CodingKeys
4+
5+
struct S: Encodable {
6+
var a: String
7+
var b: String
8+
9+
private var foo: CodingKeys {
10+
.#^COMPLETE^#
11+
// COMPLETE-DAG: Decl[EnumElement]/CurrNominal/Flair[ExprSpecific]/TypeRelation[Convertible]: a[#CodingKeys#]; name=a
12+
// COMPLETE-DAG: Decl[EnumElement]/CurrNominal/Flair[ExprSpecific]/TypeRelation[Convertible]: b[#CodingKeys#]; name=b
13+
}
14+
}

0 commit comments

Comments
 (0)