You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: docs/adr/0115-csharp-to-gsharp-migration-tool.md
+1-1Lines changed: 1 addition & 1 deletion
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -686,7 +686,7 @@ Fields:
686
686
-**`diagnostic.id` for stage 1.** A `translation-unsupported` failure has no G# diagnostic (no `.gs` is produced for the construct), so the pipeline emits a stable synthetic id: `CS2GS-UNSUPPORTED` for an unmapped construct, or `CS2GS-ROUNDTRIP` for an emitted `.gs` that fails to re-parse. Stage 2 uses the real `GSxxxx`.
687
687
-**`sourceLocation` null rules.** The translator does not yet carry a per-line C#↔G# position map, so the two ends of `sourceLocation` are filled by *whichever* side the failure is anchored to and the other sub-fields are left `null` (the schema permits this): a stage-1 `translation-unsupported` fills `cs*` from the Roslyn node location and leaves `gs*` null; a stage-2 `compile-error` fills `gs*` from the `gsc` diagnostic and leaves `cs*` null. Correspondingly, `offendingCSharpConstruct` for a stage-1 failure is the C# construct (kind = Roslyn syntax-kind, snippet = the C# line), while for a stage-2 failure it is the *emitted G# construct*`gsc` flagged (kind classified from the G# line, snippet = the G# line). Wiring a real source map so stage-2/stage-3 artifacts also point back to the originating C# is deferred to a later step.
688
688
- **Stage 3 (`ilverify`) artifacts and labels.** `IlVerifyStage` runs only after a green stage-2 compile (it reads the emitted assembly path the `CompileStage` publishes on the shared context). It invokes the repo-pinned `dotnet-ilverify` (`.config/dotnet-tools.json`, tool `dotnet-ilverify` 10.0.8, command `ilverify`) via `dotnet tool run ilverify <assembly> -s System.Private.CoreLib -r <eachReference>` with the process **working directory anchored at the repo root** (so the local tool manifest is discovered) and **all paths passed absolute**; `dotnet tool restore` is run once, lazily, only when the tool probe fails. The reference set is the host runtime BCL (`System.Private.CoreLib.dll`, `System.*.dll`, `mscorlib.dll`, `netstandard.dll` from the shared-framework dir) plus the corpus app's `ReferencedAssemblies`, mirroring `test/Compiler.Tests/IlVerifier.cs`. A non-zero exit with real verification errors yields category `ilverify-failure`, one artifact per distinct **error-code + failing-method skeleton**, with `diagnostic.id` = the ilverify error code (e.g. `StackUnexpected`), `severity` = `error`, `message` = the trimmed `[IL]: Error […]` line, and `offendingCSharpConstruct.kind` = the failing `Type::Method(sig)` parsed from the line (documented fallback `IlMethod` when ilverify reports no method). `sourceLocation.gsFile` points at the emitted `.gs`; all positions are `null` (no source map yet). Labels are **`Oats` + `cil-emit`** (per the §D label list). The fingerprint reuses the §D.2 hash over `category|stage|diagnostic.id|construct.kind|normalizedShape`.
689
-
- **Stage 3 ilverify false-positive bundles (the only suppressions).** `dotnet-ilverify` 10.0.8 has two documented FALSE POSITIVES that are verifier limitations, **not** emitter bugs — the same minimal pattern emitted by `csc` fails identically and the JIT accepts the IL. The pipeline passes these as `ilverify -g <code>` ignore flags (and filters them defensively from parsed output) via the named constant `IlVerifyRunner.KnownIlVerifyFalsePositives`, so no spurious `ilverify-failure` gap is filed: (1) **`ReturnPtrToStack`** — by-value returns of a user-declared `ref struct` (track [dotnet/runtime#129030](https://github.com/dotnet/runtime/issues/129030)); (2) the static-virtual `constrained.` + `call` bundle **`CallAbstract`** + **`Constrained`** — ADR-0089 / issue #755 (track [dotnet/runtime#49558](https://github.com/dotnet/runtime/issues/49558)). These cite the same upstream issues as `IlVerifier.KnownIssues`. Any *other* ilverify error in a green-compiling app is a genuine `cil-emit` compiler gap and is captured (never suppressed). The whole stage no-ops to PASS when `GSHARP_SKIP_ILVERIFY=1` (for environments without the tool), matching `IlVerifier`.
689
+
- **Stage 3 ilverify false-positive bundles (the only suppressions).** `dotnet-ilverify` 10.0.8 has two documented FALSE POSITIVES that are verifier limitations, **not** emitter bugs — the same minimal pattern emitted by `csc` fails identically and the JIT accepts the IL. The pipeline passes these as `ilverify -g <code>` ignore flags (and filters them defensively from parsed output) via the named constant `IlVerifyRunner.KnownIlVerifyFalsePositives`, so no spurious `ilverify-failure` gap is filed: (1) **`ReturnPtrToStack`** — by-value returns of a user-declared `ref struct` (track [dotnet/runtime#129030](https://github.com/dotnet/runtime/issues/129030)); (2) the static-virtual `constrained.` + `call` bundle **`CallAbstract`** + **`Constrained`** — ADR-0089 / issue #755 (track [dotnet/runtime#49558](https://github.com/dotnet/runtime/issues/49558)). These cite the same upstream issues as `IlVerifier.KnownIssues`. Any *other* ilverify error in a green-compiling app is a genuine `cil-emit` compiler gap and is captured (never suppressed). An abnormal tool exit is instead `verification-incomplete`: the runner excludes the member named by verbose output and retries to recover findings from the remaining members, while the stage stays failed and emits a separate `IlVerifyIncomplete` artifact. The whole stage no-ops to PASS when `GSHARP_SKIP_ILVERIFY=1` (for environments without the tool), matching `IlVerifier`.
690
690
-**Stage 4 (`test-parity`) modes, artifacts, and labels.**`TestParityStage` runs only after a green stage-3 (it is appended last in `MigrationPipeline.DefaultStages()`, so it short-circuits with the rest — L2/L3, which stop at stage 1 today, never reach it). It proves the migrated program behaves identically to the original C# against the §E oracle, selecting one of two modes by the corpus app:
691
691
-**Executable apps with a captured stdout golden (e.g. L1) → stdout parity.** The stage runs the stage-2/3 **emitted assembly** (the `EmittedAssemblyPath` the `CompileStage` publishes on the shared context) via `dotnet <emitted>.dll`, captures stdout, and compares it to `baseline.stdout.golden` with the L1 end-to-end normalization (CRLF→LF, single trailing newline). A divergence — or a non-zero exit — yields category `test-parity-failure`, one artifact with `diagnostic.id` = `STDOUT-MISMATCH`, `message` = the first differing line (expected-vs-actual), and `offendingCSharpConstruct.kind` = `ProgramStdout`. **L1 is the first corpus app green end-to-end across all four stages.**
692
692
- **Library apps with a sibling `.Tests` oracle (L2/L3) → xUnit pass/fail-set parity.** The stage translates the C# `.Tests` project to a G# xUnit project (`@Fact`/`@Theory`/`@InlineData`/`Assert.*`), scaffolds an **isolated** test `.gsproj` consuming the **locally-built** `Gsharp.NET.Sdk` nupkg (copied into the repo `.nugs` feed and pinned), runs `dotnet test` producing a TRX, parses it into the `{name, outcome}` set, and compares it to `baseline.tests.json`. Any **missing**, **extra**, or **outcome-mismatch** test yields category `test-parity-failure`, **one artifact per differing test**, with `diagnostic.id` = `TESTPARITY-<Missing|Extra|OutcomeMismatch>`, `message` = expected-vs-actual outcome, and `offendingCSharpConstruct.kind` = the failing test name. The TRX parse mirrors `corpus/trx-to-baseline.py` (only `UnitTestResult` rows; namespace-agnostic by local name; sorted by name) so the comparison is apples-to-apples. Because C#-xUnit-test → G# translation is part of the not-yet-complete *map-advanced* step, the stage **skips the library path with an explicit, recorded reason** (`test-parity.log`: "test-translation pending map-advanced") when an unsupported construct, a round-trip-parse failure, or a G# build failure is hit — it never fabricates a pass and never emits an artifact except on a real outcome mismatch from a successful run. The live orchestration (`GsharpTestProjectRunner`) is proven on a minimal translated G# lib+test that builds and `dotnet test`s green against the local SDK.
0 commit comments