Skip to content

Commit 7c508a0

Browse files
authored
Merge pull request swiftlang#33582 from CodaFi/the-coding-keys-to-success
Patch A Regression in Lookup for CodingKeys
2 parents 051f342 + 13cf37a commit 7c508a0

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
@@ -220,8 +220,26 @@ convertToUnqualifiedLookupOptions(NameLookupOptions options) {
220220
LookupResult 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}, {});

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)