From 6fd128ff676b9142a258e48642d123dc9d788568 Mon Sep 17 00:00:00 2001 From: Hamish Knight Date: Fri, 13 Jun 2025 19:33:00 +0100 Subject: [PATCH] [Sema] Scale back CodingKeys hack in `TypeChecker::lookupUnqualifiedType` I previously added this hack to match the logic in `TypeChecker::lookupUnqualified`, but it turns out that can introduce request cycles for cases where `CodingKeys` is used in a generic requirement for one of `Codable`'s potential value witnesses. Scale back the hack such that it's only done when we get an initial empty lookup result, ensuring we maintain source compatibility. Both these lookup hacks should go away once we properly handle CodingKeys synthesis. rdar://153096639 --- lib/Sema/TypeCheckNameLookup.cpp | 14 +++++++++----- test/Sema/rdar153096639.swift | 18 ++++++++++++++++++ 2 files changed, 27 insertions(+), 5 deletions(-) create mode 100644 test/Sema/rdar153096639.swift diff --git a/lib/Sema/TypeCheckNameLookup.cpp b/lib/Sema/TypeCheckNameLookup.cpp index 9eb184aaffd41..7d4853b9d3738 100644 --- a/lib/Sema/TypeCheckNameLookup.cpp +++ b/lib/Sema/TypeCheckNameLookup.cpp @@ -325,9 +325,6 @@ TypeChecker::lookupUnqualifiedType(DeclContext *dc, DeclNameRef name, NameLookupOptions options) { auto &ctx = dc->getASTContext(); - // HACK: Synthesize CodingKeys if needed. - synthesizeCodingKeysIfNeededForUnqualifiedLookup(ctx, dc, name); - auto ulOptions = convertToUnqualifiedLookupOptions(options) | UnqualifiedLookupFlags::TypeLookup; { @@ -336,8 +333,15 @@ TypeChecker::lookupUnqualifiedType(DeclContext *dc, DeclNameRef name, name, dc, loc, ulOptions - UnqualifiedLookupFlags::AllowProtocolMembers); - auto lookup = - evaluateOrDefault(ctx.evaluator, UnqualifiedLookupRequest{desc}, {}); + UnqualifiedLookupRequest req(desc); + auto lookup = evaluateOrDefault(ctx.evaluator, req, {}); + + // HACK: Try synthesize CodingKeys if we got an empty result. + if (lookup.allResults().empty() && name.isSimpleName(ctx.Id_CodingKeys)) { + synthesizeCodingKeysIfNeededForUnqualifiedLookup(ctx, dc, name); + lookup = evaluateOrDefault(ctx.evaluator, req, {}); + } + if (!lookup.allResults().empty()) return lookup; } diff --git a/test/Sema/rdar153096639.swift b/test/Sema/rdar153096639.swift new file mode 100644 index 0000000000000..a5960ccb544c5 --- /dev/null +++ b/test/Sema/rdar153096639.swift @@ -0,0 +1,18 @@ +// RUN: %target-typecheck-verify-swift + +// Make sure we don't run into a request cycle for the below use of 'CodingKeys' +// in an `init(from:)` signature. + +protocol P { + associatedtype X +} + +struct S: Codable { + var foo: String? + + enum CodingKeys: CodingKey { + case foo + } + + init(from: T) where T.X == CodingKeys {} +}