Skip to content
Open
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
2 changes: 1 addition & 1 deletion docs/release-notes/.FSharp.Compiler.Service/11.0.100.md
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
### 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))
* Tooltip "Full name" now shows demangled companion module names (e.g. `MyType.func` instead of `MyTypeModule.func`). ([Issue #17335](https://github.com/dotnet/fsharp/issues/17335), [PR #19867](https://github.com/dotnet/fsharp/pull/19867))
* 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))
* Fix `TypeLoadException` ("Specialize tried to implicitly override a method with weaker type parameter constraints") and the related CLR crash with constrained inline calls by stripping constraints from closure-class typars in `EraseClosures.convIlxClosureDef`. ([Issue #14492](https://github.com/dotnet/fsharp/issues/14492), [Issue #19075](https://github.com/dotnet/fsharp/issues/19075), [PR #19882](https://github.com/dotnet/fsharp/pull/19882))

* Suppress hover/symbol resolution for wildcard `_` patterns inside `member _.…` bodies that incorrectly showed `val _: T` tooltip. ([PR #19760](https://github.com/dotnet/fsharp/pull/19760))
* Deduplicate format specifier locations in computation expressions so editor tooling no longer reports duplicate entries for the same `%` specifier. ([Issue #16419](https://github.com/dotnet/fsharp/issues/16419), [PR #19791](https://github.com/dotnet/fsharp/pull/19791))
* Reject non-function bindings for single-case and partial active pattern names with FS1209, matching the existing multi-case behavior. ([PR #19763](https://github.com/dotnet/fsharp/pull/19763))
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 @@ -12118,18 +12118,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