Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions docs/release-notes/.FSharp.Compiler.Service/11.0.100.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
### Fixed

* Fix incorrect `StructLayout(Size = 1)` emission for data-less struct unions where the compiler-generated tag field makes the actual runtime size larger. ([PR #19759](https://github.com/dotnet/fsharp/pull/19759))
* Honor `--nowarn` and `--warnaserror` for warnings emitted during command-line option parsing ([Issue #19576](https://github.com/dotnet/fsharp/issues/19576), [PR #19776](https://github.com/dotnet/fsharp/pull/19776))
* Fix `[<return: X>]` prefix attributes being silently dropped on class members, and fix false-positive `AllowMultiple=false` errors when `[<X>]` and `[<return: X>]` are applied to the same binding. ([Issue #17904](https://github.com/dotnet/fsharp/issues/17904), [Issue #19020](https://github.com/dotnet/fsharp/issues/19020), [PR #19738](https://github.com/dotnet/fsharp/pull/19738))
* Fix attributes on return type of unparenthesized tuple methods being silently dropped from IL. ([Issue #462](https://github.com/dotnet/fsharp/issues/462), [PR #19714](https://github.com/dotnet/fsharp/pull/19714))
Expand Down
14 changes: 3 additions & 11 deletions src/Compiler/CodeGen/IlxGen.fs
Original file line number Diff line number Diff line change
Expand Up @@ -12031,18 +12031,10 @@ and GenTypeDef cenv mgbuf lazyInitInfo eenv m (tycon: Tycon) : ILTypeRef option
}

let layout =
// Structs with no instance fields get size 1, pack 0
// Multi-case struct unions carry a hidden tag field; single-case struct unions
// are handled by the CLR's minimum-1-byte guarantee. No explicit size needed.
if isStructTy g thisTy then
if
(tycon.AllFieldsArray.Length = 0
|| tycon.AllFieldsArray |> Array.exists (fun f -> not f.IsStatic))
&& (alternatives
|> Array.collect (fun a -> a.FieldDefs)
|> Array.exists (fun fd -> not fd.ILField.IsStatic))
then
ILTypeDefLayout.Sequential { Size = None; Pack = None }
else
ILTypeDefLayout.Sequential { Size = Some 1; Pack = Some 0us }
ILTypeDefLayout.Sequential { Size = None; Pack = None }
else
ILTypeDefLayout.Auto

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -397,7 +397,7 @@ module CustomAttributes_Basic =
]

[<Fact>]
let ``StructLayoutAttribute has size=1 for struct DUs with no instance fields`` () =
let ``StructLayoutAttribute doesn't have size=1 for multi-case struct DUs with no instance fields`` () =
Fsx """
[<Struct>] type Option<'T> = None | Some
"""
Expand All @@ -413,8 +413,6 @@ module CustomAttributes_Basic =
[runtime]System.IComparable,
[runtime]System.Collections.IStructuralComparable
{
.pack 0
.size 1
.custom instance void [FSharp.Core]Microsoft.FSharp.Core.StructAttribute::.ctor() = ( 01 00 00 00 )
.custom instance void [runtime]System.Diagnostics.DebuggerDisplayAttribute::.ctor(string) = ( 01 00 15 7B 5F 5F 44 65 62 75 67 44 69 73 70 6C
61 79 28 29 2C 6E 71 7D 00 00 )
Expand All @@ -426,4 +424,28 @@ module CustomAttributes_Basic =
.field public static literal int32 Some = int32(0x00000001)
}
"""
]
]

[<Fact>]
let ``StructLayoutAttribute doesn't have size=1 for single-case struct DU`` () =
Fsx """
[<Struct>] type X = | Y
"""
|> compile
|> shouldSucceed
|> verifyIL [
"""
.class sequential autochar serializable sealed nested public beforefieldinit X
extends [runtime]System.ValueType
implements class [runtime]System.IEquatable`1<valuetype Test/X>,
[runtime]System.Collections.IStructuralEquatable,
class [runtime]System.IComparable`1<valuetype Test/X>,
[runtime]System.IComparable,
[runtime]System.Collections.IStructuralComparable
{
.custom instance void [FSharp.Core]Microsoft.FSharp.Core.StructAttribute::.ctor() = ( 01 00 00 00 )
.custom instance void [runtime]System.Diagnostics.DebuggerDisplayAttribute::.ctor(string) = ( 01 00 15 7B 5F 5F 44 65 62 75 67 44 69 73 70 6C
61 79 28 29 2C 6E 71 7D 00 00 )
.custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 01 00 00 00 00 00 )
"""
]
Loading