Skip to content

Commit cb7c13f

Browse files
CopilotT-Gro
andcommitted
Complete fix for duplicate .cctor issue and add release notes
Co-authored-by: T-Gro <46543583+T-Gro@users.noreply.github.com>
1 parent 60e11b3 commit cb7c13f

File tree

4 files changed

+38
-0
lines changed

4 files changed

+38
-0
lines changed

docs/release-notes/.FSharp.Compiler.Service/10.0.100.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
### Fixed
66

7+
* Fix duplicate .cctor issue for discriminated unions with generic statics ([Issue #18767](https://github.com/dotnet/fsharp/issues/18767))
78
* Fix SignatureHash to include constant values in hash computation ([Issue #18758](https://github.com/dotnet/fsharp/issues/18758))
89
* Fix parsing errors using anonymous records and units of measures ([PR #18543](https://github.com/dotnet/fsharp/pull/18543))
910
* Fix parsing errors using anonymous records and code quotations ([PR #18603](https://github.com/dotnet/fsharp/pull/18603))

src/Compiler/AbstractIL/il.fs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4120,6 +4120,7 @@ let cdef_cctorCode2CodeOrCreate tag imports f (cd: ILTypeDef) =
41204120
mkILClassCtor body
41214121
| multipleCctors ->
41224122
// Handle multiple .cctor methods by merging their instruction bodies
4123+
// This resolves the "duplicate entry '.cctor' in method table" error
41234124
// Extract the instruction sequences from all .cctor methods (excluding the final 'ret')
41244125
let allInstrs =
41254126
multipleCctors
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
// #NoMono #NoMT #CodeGen #EmittedIL
2+
// Regression test for duplicate .cctor issue: https://github.com/dotnet/fsharp/issues/18767
3+
// This test verifies that discriminated unions with generic statics and nullary cases
4+
// generate only one .cctor method instead of failing with "duplicate entry '.cctor' in method table"
5+
6+
type TestUnion<'T when 'T: comparison> =
7+
| A of 'T
8+
| B of string
9+
| C // nullary case that triggers union erasure .cctor for constant field initialization
10+
11+
// Static member that triggers incremental class .cctor generation
12+
static member val StaticProperty = "test" with get, set
13+
14+
// Another static member to ensure .cctor has meaningful initialization
15+
static member CompareStuff x y = compare x y

tests/FSharp.Compiler.ComponentTests/Misc.fs

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,3 +30,24 @@ IL_0005: ret"""
3030
"""
3131
IL_0000: call !!0[] [runtime]System.Array::Empty<!!0>()
3232
IL_0005: ret""" ]
33+
34+
[<Fact>]
35+
let ``Discriminated union with generic statics generates single merged cctor``() =
36+
FSharp """
37+
module DuplicateCctorFix
38+
39+
type TestUnion<'T when 'T: comparison> =
40+
| A of 'T
41+
| B of string
42+
| C // nullary case that triggers union erasure .cctor for constant field initialization
43+
44+
// Static member that triggers incremental class .cctor generation
45+
static member val StaticProperty = "test" with get, set
46+
47+
// Another static member to ensure .cctor has meaningful initialization
48+
static member CompareStuff x y = compare x y
49+
"""
50+
|> compile
51+
|> shouldSucceed
52+
|> verifyIL [""".method private specialname rtspecialname static
53+
void .cctor() cil managed"""]

0 commit comments

Comments
 (0)