Skip to content

cs2gs: preserve designations on nested untyped property patterns (selfmig nightly regression) - #3631

Merged
DavidObando merged 1 commit into
mainfrom
fix/nested-pattern-designation
Aug 29, 2026
Merged

cs2gs: preserve designations on nested untyped property patterns (selfmig nightly regression)#3631
DavidObando merged 1 commit into
mainfrom
fix/nested-pattern-designation

Conversation

@DavidObando

Copy link
Copy Markdown
Owner

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 migrated src/Core failing to compile — which dropped the gate to 28/52 green against floor 33.

Root cause

TranslateRecursivePattern's untyped branch returned new PropertyPattern(fields) without ever consulting recursive.Designation. A designation on a nested untyped property pattern was silently dropped while the body still referenced the binder:

// TupleElementNamesReader.cs:202 (added by #3622) — the trigger
case { ClrType: { IsGenericType: true, IsGenericTypeDefinition: false } closedClr }:
    ... closedClr.GetGenericArguments() ...

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 a Designator — 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), boolean is-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

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
DavidObando merged commit c7de452 into main Aug 29, 2026
34 checks passed
@DavidObando
DavidObando deleted the fix/nested-pattern-designation branch August 29, 2026 15:25
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>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant