Skip to content

Commit 9f28f80

Browse files
authored
Merge pull request #33586 from CodaFi/the-coding-keys-to-the-castle
[5.3] Patch A Regression in Lookup for CodingKeys
2 parents 716688c + 53a38f9 commit 9f28f80

File tree

3 files changed

+35
-1
lines changed

3 files changed

+35
-1
lines changed

lib/Sema/TypeCheckNameLookup.cpp

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -232,8 +232,26 @@ convertToUnqualifiedLookupOptions(NameLookupOptions options) {
232232
LookupResult TypeChecker::lookupUnqualified(DeclContext *dc, DeclNameRef name,
233233
SourceLoc loc,
234234
NameLookupOptions options) {
235-
auto ulOptions = convertToUnqualifiedLookupOptions(options);
236235
auto &ctx = dc->getASTContext();
236+
// HACK: Qualified lookup cannot be allowed to synthesize CodingKeys because
237+
// it would lead to a number of egregious cycles through
238+
// QualifiedLookupRequest when we resolve the protocol conformance. Codable's
239+
// magic has pushed its way so deeply into the compiler, we have to
240+
// pessimistically force every nominal context above this one to synthesize
241+
// it in the event the user needs it from e.g. a non-primary input.
242+
// We can undo this if Codable's semantic content is divorced from its
243+
// syntactic content - so we synthesize just enough to allow lookups to
244+
// succeed, but don't force protocol conformances while we're doing it.
245+
if (name.getBaseIdentifier() == ctx.Id_CodingKeys) {
246+
for (auto typeCtx = dc->getInnermostTypeContext(); typeCtx != nullptr;
247+
typeCtx = typeCtx->getParent()->getInnermostTypeContext()) {
248+
if (auto *nominal = typeCtx->getSelfNominalTypeDecl()) {
249+
nominal->synthesizeSemanticMembersIfNeeded(name.getFullName());
250+
}
251+
}
252+
}
253+
254+
auto ulOptions = convertToUnqualifiedLookupOptions(options);
237255
auto descriptor = UnqualifiedLookupDescriptor(name, dc, loc, ulOptions);
238256
auto lookup = evaluateOrDefault(ctx.evaluator,
239257
UnqualifiedLookupRequest{descriptor}, {});

test/decl/protocol/special/coding/Inputs/struct_codable_simple_multi1.swift

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,3 +21,11 @@ struct SimpleStruct : Codable {
2121
let _ = SimpleStruct.CodingKeys.z // expected-error {{type 'SimpleStruct.CodingKeys' has no member 'z'}}
2222
}
2323
}
24+
25+
// SR-13137 Ensure unqualified lookup installs CodingKeys regardless of the
26+
// order of primaries.
27+
struct A: Codable {
28+
var property: String
29+
static let propertyName = CodingKeys.property.stringValue
30+
}
31+

test/decl/protocol/special/coding/Inputs/struct_codable_simple_multi2.swift

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,3 +8,11 @@ func foo() {
88
// struct.
99
let _ = SimpleStruct.CodingKeys.self // expected-error {{'CodingKeys' is inaccessible due to 'private' protection level}}
1010
}
11+
12+
struct B {
13+
static let propertyName = A.propertyName
14+
15+
struct Nest {
16+
static let propertyName = A.propertyName
17+
}
18+
}

0 commit comments

Comments
 (0)