From 7dcdb8cdfcc74538c710e3613472b45d29ce9ab6 Mon Sep 17 00:00:00 2001 From: KirtiRamchandani Date: Sun, 14 Jun 2026 07:30:19 +0000 Subject: [PATCH 1/2] Fix StructLayout Size for struct discriminated unions Struct DUs carry a compiler-generated tag field but were emitted with StructLayout Size=1 when they had no declared instance fields. Fixes #18125 --- src/Compiler/CodeGen/IlxGen.fs | 1 + .../EmittedIL/Structure/StructUnionLayout18125.fs | 12 ++++++++++++ .../EmittedIL/Structure/Structure.fs | 7 +++++++ 3 files changed, 20 insertions(+) create mode 100644 tests/FSharp.Compiler.ComponentTests/EmittedIL/Structure/StructUnionLayout18125.fs diff --git a/src/Compiler/CodeGen/IlxGen.fs b/src/Compiler/CodeGen/IlxGen.fs index de180807269..c11d18c0342 100644 --- a/src/Compiler/CodeGen/IlxGen.fs +++ b/src/Compiler/CodeGen/IlxGen.fs @@ -12019,6 +12019,7 @@ and GenTypeDef cenv mgbuf lazyInitInfo eenv m (tycon: Tycon) : ILTypeRef option // Structs with no instance fields get size 1, pack 0 if tycon.AllFieldsArray |> Array.exists (fun f -> not f.IsStatic) + || tycon.IsUnionTycon || // Reflection emit doesn't let us emit 'pack' and 'size' for generic structs. // In that case we generate a dummy field instead diff --git a/tests/FSharp.Compiler.ComponentTests/EmittedIL/Structure/StructUnionLayout18125.fs b/tests/FSharp.Compiler.ComponentTests/EmittedIL/Structure/StructUnionLayout18125.fs new file mode 100644 index 00000000000..9c4f7ee99a1 --- /dev/null +++ b/tests/FSharp.Compiler.ComponentTests/EmittedIL/Structure/StructUnionLayout18125.fs @@ -0,0 +1,12 @@ +// Regression test for https://github.com/dotnet/fsharp/issues/18125 +module StructUnionLayout18125 + +[] +type ABC = A | B | C + +let verifySize () = + // Struct DU has a compiler-generated _tag field; sizeof must not be 1. + if sizeof <> 4 then + failwith $"Expected sizeof = 4, got {sizeof}" + +verifySize () diff --git a/tests/FSharp.Compiler.ComponentTests/EmittedIL/Structure/Structure.fs b/tests/FSharp.Compiler.ComponentTests/EmittedIL/Structure/Structure.fs index cef637ee350..c1b31d83346 100644 --- a/tests/FSharp.Compiler.ComponentTests/EmittedIL/Structure/Structure.fs +++ b/tests/FSharp.Compiler.ComponentTests/EmittedIL/Structure/Structure.fs @@ -235,3 +235,10 @@ module Structure = compilation |> getCompilation |> verifyExecution + + // SOURCE=StructUnionLayout18125.fs SCFLAGS="-r:CodeGenHelper.dll" # StructUnionLayout18125.fs + [] + let ``StructUnionLayout18125_fs`` compilation = + compilation + |> getCompilation + |> verifyExecution From ef9374e0641f4abe5cfe0bfd5d1c90143eccf5be Mon Sep 17 00:00:00 2001 From: KirtiRamchandani Date: Mon, 15 Jun 2026 06:25:51 +0000 Subject: [PATCH 2/2] Add release notes for struct union StructLayout Size fix Required for check_release_notes on #19946. --- docs/release-notes/.FSharp.Compiler.Service/11.0.100.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/release-notes/.FSharp.Compiler.Service/11.0.100.md b/docs/release-notes/.FSharp.Compiler.Service/11.0.100.md index a41b15a78ac..cb55afdd373 100644 --- a/docs/release-notes/.FSharp.Compiler.Service/11.0.100.md +++ b/docs/release-notes/.FSharp.Compiler.Service/11.0.100.md @@ -1,5 +1,6 @@ ### Fixed +* Fix `StructLayout` `Size` for struct discriminated unions so emitted IL matches the computed layout size. ([Issue #18125](https://github.com/dotnet/fsharp/issues/18125), [PR #19946](https://github.com/dotnet/fsharp/pull/19946)) * Fix internal error (FS0193) when calling an indexed property setter with a named argument that matches an indexer parameter. ([Issue #16034](https://github.com/dotnet/fsharp/issues/16034), [PR #19851](https://github.com/dotnet/fsharp/pull/19851)) * Fix missing FS1182 ("unused binding") warning for unused `let` function bindings inside class types. ([Issue #13849](https://github.com/dotnet/fsharp/issues/13849), [PR #19805](https://github.com/dotnet/fsharp/pull/19805)) * Fix inner mutually-recursive `let rec ... and ...` functions under `--realsig+` not being lifted to top-level static methods (TLR), causing `FSharpFunc` closure allocations and loss of `tail.` opcodes — the large struct-mutual-recursion perf regression reported in [Issue #17607](https://github.com/dotnet/fsharp/issues/17607). ([PR #19882](https://github.com/dotnet/fsharp/pull/19882))