cs2gs: preserve designations on nested untyped property patterns (selfmig nightly regression) - #3631
Merged
Merged
Conversation
The untyped recursive-pattern branch of TranslateRecursivePattern never
consulted `recursive.Designation`, so a designation on a nested property
pattern — `case { ClrType: { IsGenericType: true } closedClr }:` — was
silently dropped while the body still referenced the binder, producing
G# that fails GS0125/GS0159. This is the 2026-08-29 selfmig nightly
regression: TupleElementNamesReader.cs (#3622) uses exactly this shape,
so migrated src/Core stopped compiling and 18 downstream apps went red
(28/52 green vs floor 33).
G# already supports the after-brace designator natively (ADR-0166
`PropertyPattern identifier?`), and the code model + printer already
carry it — the translator now populates it, with the reassigned-binder
capture mirroring the var-pattern path. Covers switch statements, switch
expressions, and boolean is-patterns; verified end to end (compile+run
parity with the C#).
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Nng28yiBdPVdeML7mSZphs
DavidObando
added a commit
that referenced
this pull request
Aug 29, 2026
…jection gate (ADR-0172) (#3632) Fixes the remaining systemic failure in the second 2026-08-29 selfmig nightly ([run 33260247720](https://github.com/DavidObando/gsharp/actions/runs/33260247720), which already included #3630/#3631): 32/52 green against floor 33, with migrated **Cs2Gs.Translator** failing `GS0158 Cannot find member Symbol` / `GS0159 Cannot find function Contains` / `GS0116 not indexable` at `CSharpToGSharpTranslator.Constructors.gs:1537-38` — `candidate[0].Symbol` and `reach[head].Contains(symbol)` over `List[List[(syntax …, symbol …)]]` — cascading into 11 downstream apps. ## Root cause A named tuple nested **inside** a generic type argument shares its CLR backing with the unnamed shape (`ValueTuple<…>`), so any keep-symbolic gate that consults only `RequiresSymbolicProjection` (or a direct `is TupleTypeSymbol`) collapses the constructed type to its erased CLR form — and the element names vanish, so member access by name fails. The #3622 projection-gate family covered *direct* named-tuple arguments (`List[(a, b)]`, one level), but not `List[List[(a, b)]]`, `List[[](a, b)]`, or `Dictionary[K, (a, b)]` reached through construction, indexing, or iteration. Minimal repro (failed before, runs now): ```gs let groups = List[List[(a int32, b string)]]() … groups[0][0].a // was GS0158: Cannot find member a ``` ## Fix Widened six keep-symbolic gates with `TypeSymbol.ContainsNamedTupleElements` (already recursive through every constructor shape): the generic ctor-call type-argument resolution (the erasure at the root), the constructed-generic receiver form, the indexer element substitution + its #2365 recursive projection filter, the generic-return construction and indexer property projection in MemberLookup, the conversion-classifier parameter substitution, and the type-clause `ProjectGenericArgument`. Deliberately did **not** widen `ImportedTypeSymbol.HasSubstitutableTypeArgument` itself — it feeds conversion/lowering decisions with broader meaning, and widening it regressed working cases during investigation. ## Verification - New `NestedNamedTupleProjectionTests` (4 end-to-end oracle tests) pin all shapes, including the exact selfmig iteration+index+member chain with an imported interface element type. - Full Core.Tests: **8218/8218 passed**. - Local selfmig proof over the cs2gs subtree: Cs2Gs.Translator's three real compile errors are gone (the only remaining local failures are the known subtree-proof artifact — `GSharpRoundTrip.gs` referencing GSharp.Core, which the subtree run excludes from migration; the nightly migrates it). With this plus #3630/#3631, the next nightly should clear the `b7a89d8f22f8`/`0a665d0d062c`/`ebe7e1f2f6f8` fingerprint family. The `!!` ceiling breach (17516 vs 17400) is a separate ratchet question. 🤖 Generated with [Claude Code](https://claude.com/claude-code) https://claude.ai/code/session_01Nng28yiBdPVdeML7mSZphs Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes the systemic failure in the 2026-08-29 selfmig nightly (run 33234797980): 18 apps shared the same two compile fingerprints (
GS0159 Cannot find function GetGenericArguments/GS0125 Variable 'closedClr' doesn't exist), all cascading from migratedsrc/Corefailing to compile — which dropped the gate to 28/52 green against floor 33.Root cause
TranslateRecursivePattern's untyped branch returnednew PropertyPattern(fields)without ever consultingrecursive.Designation. A designation on a nested untyped property pattern was silently dropped while the body still referenced the binder:translated to a pattern without
closedClr, orphaning the body references.Fix
G# natively supports the after-brace designator (ADR-0166,
PropertyPattern identifier?in the spec grammar), and the code model + printer already carry aDesignator— the translator now populates it, with reassigned-binder capture mirroring the existing var-pattern path, and an explicit unsupported report for tuple designations. Verified that gsc compiles and runs the nested-designation form correctly (narrowed non-nil binding, parity with C# semantics).Tests
NestedPatternDesignationTranslationTests— switch statement (with compile+run parity witness: generic vs nil holder), booleanis-pattern, and switch expression. Full pattern-related Cs2Gs.Tests family green (188/188).Note: this is independent of #3630; the C# trigger shape came from #3622 (merged), so the regression exists on main regardless of the variadic-carriers branch.
🤖 Generated with Claude Code
https://claude.ai/code/session_01Nng28yiBdPVdeML7mSZphs