[swift5] fix: annotate the query-parameter dictionary so large operations type-check - #24871
[swift5] fix: annotate the query-parameter dictionary so large operations type-check#24871wiebren wants to merge 1 commit into
Conversation
… inferring it api.mustache emitted the (wrappedValue:, isExplode:) tuple dictionary as an un-annotated literal passed straight to APIHelper.mapValuesToQueryItems. For operations with many heterogeneous query parameters the constraint solver has to consider every encodeToJSON() overload for every entry at once and gives up with 'the compiler is unable to type-check this expression in reasonable time'. Bind the literal to a local with the parameter type of mapValuesToQueryItems spelled out, the same way the localVariableNillableHeaders literal is already annotated. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01CxDNCjqJycKTfzVWg2SeTJ
There was a problem hiding this comment.
2 issues found across 29 files
Prompt for AI agents (unresolved issues)
Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.
<file name="modules/openapi-generator/src/main/resources/swift5/api.mustache">
<violation number="1" location="modules/openapi-generator/src/main/resources/swift5/api.mustache:432">
P2: When an operation has a query parameter named `localVariableQueryParameters`, this declaration collides with the generated method parameter and makes the Swift client fail to compile. Generate a collision-free local name or scope the typed dictionary separately.</violation>
<violation number="2" location="modules/openapi-generator/src/main/resources/swift5/api.mustache:437">
P3: The PR description states the typed-dictionary fix was also applied to the Swift6 template and that Swift6 samples should be re-generated, but the diff only changes swift5/api.mustache. swift6/api.mustache:307 still passes the unannotated dictionary literal directly to mapValuesToQueryItems, so Swift6-generated code for operations with many query parameters keeps hitting the same 'expression too complex' compile-time blow-up this PR fixes. Either apply the same annotation to the Swift6 template (using the `(wrappedValue: (any Sendable)?, isExplode: Bool)` tuple type matching its APIHelper signature) or correct the PR description and rollout notes so they don't claim Swift6 was changed.</violation>
</file>
Reply with feedback, questions, or to request a fix.
Re-trigger cubic
| {{/bodyParam}}{{#hasQueryParams}} | ||
| var localVariableUrlComponents = URLComponents(string: localVariableURLString) | ||
| localVariableUrlComponents?.queryItems = APIHelper.mapValuesToQueryItems([{{^queryParams}}:{{/queryParams}} | ||
| let localVariableQueryParameters: [String: (wrappedValue: Any?, isExplode: Bool)] = [{{^queryParams}}:{{/queryParams}} |
There was a problem hiding this comment.
P2: When an operation has a query parameter named localVariableQueryParameters, this declaration collides with the generated method parameter and makes the Swift client fail to compile. Generate a collision-free local name or scope the typed dictionary separately.
Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At modules/openapi-generator/src/main/resources/swift5/api.mustache, line 432:
<comment>When an operation has a query parameter named `localVariableQueryParameters`, this declaration collides with the generated method parameter and makes the Swift client fail to compile. Generate a collision-free local name or scope the typed dictionary separately.</comment>
<file context>
@@ -429,11 +429,12 @@ extension {{projectName}}API {
{{/bodyParam}}{{#hasQueryParams}}
var localVariableUrlComponents = URLComponents(string: localVariableURLString)
- localVariableUrlComponents?.queryItems = APIHelper.mapValuesToQueryItems([{{^queryParams}}:{{/queryParams}}
+ let localVariableQueryParameters: [String: (wrappedValue: Any?, isExplode: Bool)] = [{{^queryParams}}:{{/queryParams}}
{{#queryParams}}
{{> _param}},
</file context>
| {{/queryParams}} | ||
| ]){{/hasQueryParams}}{{^hasQueryParams}} | ||
| ] | ||
| localVariableUrlComponents?.queryItems = APIHelper.mapValuesToQueryItems(localVariableQueryParameters){{/hasQueryParams}}{{^hasQueryParams}} |
There was a problem hiding this comment.
P3: The PR description states the typed-dictionary fix was also applied to the Swift6 template and that Swift6 samples should be re-generated, but the diff only changes swift5/api.mustache. swift6/api.mustache:307 still passes the unannotated dictionary literal directly to mapValuesToQueryItems, so Swift6-generated code for operations with many query parameters keeps hitting the same 'expression too complex' compile-time blow-up this PR fixes. Either apply the same annotation to the Swift6 template (using the (wrappedValue: (any Sendable)?, isExplode: Bool) tuple type matching its APIHelper signature) or correct the PR description and rollout notes so they don't claim Swift6 was changed.
Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At modules/openapi-generator/src/main/resources/swift5/api.mustache, line 437:
<comment>The PR description states the typed-dictionary fix was also applied to the Swift6 template and that Swift6 samples should be re-generated, but the diff only changes swift5/api.mustache. swift6/api.mustache:307 still passes the unannotated dictionary literal directly to mapValuesToQueryItems, so Swift6-generated code for operations with many query parameters keeps hitting the same 'expression too complex' compile-time blow-up this PR fixes. Either apply the same annotation to the Swift6 template (using the `(wrappedValue: (any Sendable)?, isExplode: Bool)` tuple type matching its APIHelper signature) or correct the PR description and rollout notes so they don't claim Swift6 was changed.</comment>
<file context>
@@ -429,11 +429,12 @@ extension {{projectName}}API {
{{/queryParams}}
- ]){{/hasQueryParams}}{{^hasQueryParams}}
+ ]
+ localVariableUrlComponents?.queryItems = APIHelper.mapValuesToQueryItems(localVariableQueryParameters){{/hasQueryParams}}{{^hasQueryParams}}
let localVariableUrlComponents = URLComponents(string: localVariableURLString){{/hasQueryParams}}
</file context>
|
The |
Operations with many query parameters generate swift5 code that the compiler refuses to
type-check. Against a real production spec (listing endpoints with 9+ heterogeneous
optional query parameters),
swift buildfails 520 times with:The cause
api.mustachepasses the dictionary of(wrappedValue:, isExplode:)tuples toAPIHelper.mapValuesToQueryItemsas one un-annotated literal.mapValuesToQueryItemsisoverloaded and every entry's value goes through an
encodeToJSON()call that is itselfresolved by overload, so the constraint solver has to consider every combination across
every entry at once. With enough entries of different parameter types (
String?,Int?,Bool?,AnyCodable?, …) it exceeds its budget and gives up. This is the standard Swiftexpression-too-complex failure, and the standard remedy is to state the type instead of
making the solver infer it.
The fix
Bind the literal to an explicitly typed local before the call — the parameter type of
mapValuesToQueryItemsspelled out at the call site:With the annotation each entry is checked independently against
(wrappedValue: Any?, isExplode: Bool), so solver time is linear in the number of parameters. The same filealready uses this pattern two lines down:
let localVariableNillableHeaders: [String: Any?] = [...]. Wire behavior is unchanged — the same overload ofmapValuesToQueryItemsis selected as before, with the same values.The swift6 generator's
api.mustachebuilds the same un-annotated literal and the samechange applies there; happy to extend this PR or follow up, whichever you prefer.
Tests / verification
Swift5ClientCodegenTest#queryParameterDictionaryIsTypeAnnotatedTestgenerates thepetstore
PetAPI.swiftand asserts the typed binding; it fails on master and passeswith the fix. Full swift5 test classes pass.
./bin/generate-samples.sh ./bin/configs/swift5-*.yaml; thediff is exactly the mechanical two-line reshaping of each query-parameter dictionary.
swift buildin aswift:6.1container), confirming the annotated form compiles for explode andnon-explode, required and optional parameters. Demonstrating the 520-error timeout
disappearing requires the large production spec; the annotation is the remedy
swiftcitself suggests for this failure class.
Existing upstream issues: none found for the type-check timeout (searched
"reasonable time" swift,mapValuesToQueryItems). #12449 and #6906 concern the runtimedesign of
mapValuesToQueryItems, not compile-time blowup.PR checklist
./bin/generate-samples.sh ./bin/configs/swift5-*.yaml; docs export unchanged).Generated with Claude Code
Summary by cubic
Fixes swift5 generated code failing to type-check for operations with many query parameters.
encodeToJSON()overload at once, timing out on 9+ heterogeneous parameters.Written for commit 1aadb75. Summary will update on new commits.