Skip to content

Bugfix :: Fix F# exception serialization to preserve fields#19342

Open
T-Gro wants to merge 11 commits intomainfrom
codegen/fix-exception-serialization
Open

Bugfix :: Fix F# exception serialization to preserve fields#19342
T-Gro wants to merge 11 commits intomainfrom
codegen/fix-exception-serialization

Conversation

@T-Gro
Copy link
Member

@T-Gro T-Gro commented Feb 20, 2026

Fixes F# exceptions losing their field values during serialization.

Exceptions with fields now emit a GetObjectData override and a deserialization constructor that save/restore the fields via SerializationInfo, enabling correct ISerializable roundtrips.

Note: This fix is primarily relevant for users targeting .NET Framework 4.x or .NET Core ≤7, where BinaryFormatter / ISerializable serialization is still available. On .NET 8+, StreamingContext is removed and the serialization members are not emitted. The entire ISerializable infrastructure is deprecated (SYSLIB0051) — no modern serializer (System.Text.Json, DataContractSerializer, etc.) uses GetObjectData.

FSharp.Core exception caveat: FSharp.Core has [assembly: SecurityTransparent], which on .NET Framework prevents overriding the SecurityCritical method Exception.GetObjectData. FSharp.Core exceptions (e.g. MatchFailureException) therefore get only the base-call deserialization constructor (status quo) but not the GetObjectData override. This is tested explicitly. User-defined exceptions are unaffected — they get full serialization support.

@github-actions
Copy link
Contributor

github-actions bot commented Feb 20, 2026

❗ Release notes required


✅ Found changes and release notes in following paths:

Change path Release notes path Description
src/Compiler docs/release-notes/.FSharp.Compiler.Service/11.0.100.md

@T-Gro T-Gro force-pushed the codegen/fix-exception-serialization branch 3 times, most recently from c9b17c0 to f6f7424 Compare February 20, 2026 17:31
@T-Gro
Copy link
Member Author

T-Gro commented Feb 20, 2026

/azp run fsharp-ci

@azure-pipelines
Copy link

Azure Pipelines successfully started running 1 pipeline(s).

@T-Gro T-Gro force-pushed the codegen/fix-exception-serialization branch from f6f7424 to 675d541 Compare February 20, 2026 19:29
Fixes #878

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@T-Gro T-Gro force-pushed the codegen/fix-exception-serialization branch from 675d541 to 4b0a72e Compare February 20, 2026 19:29
T-Gro and others added 5 commits February 26, 2026 16:08
The generated GetObjectData override on F# exception types must have the
[SecurityCritical] attribute to match the security accessibility of
Exception.GetObjectData on .NET Framework. Without this, the CLR rejects
the override with 'Inheritance security rules violated', causing FS0193
errors when any project references FSharp.Core (which contains
MatchFailureException with the new GetObjectData override).

Also update IL baselines and FSharp.Core surface area baseline.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
FSharp.Core has [assembly: SecurityTransparent] which makes all methods
transparent. On .NET Framework, transparent methods cannot override
SecurityCritical methods (Exception.GetObjectData) nor call SecurityCritical
base constructors (Exception(SerializationInfo, StreamingContext)).
Skip emitting serialization members for FSharp.Core exceptions.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…, add test

FSharp.Core has [assembly: SecurityTransparent]. On .NET Framework,
transparent code cannot override SecurityCritical methods (GetObjectData).
Without GetObjectData to write fields, the field-restoring ctor would crash.

So for FSharp.Core exceptions:
- Keep the base-call-only deserialization ctor (status quo, SecuritySafeCritical base)
- Skip GetObjectData override (can't override SecurityCritical from transparent)

For user exceptions (no SecurityTransparent):
- Emit both GetObjectData and field-restoring ctor (full serialization)

Add test verifying FSharp.Core MatchFailureException:
- Loads without TypeLoadException
- Has deserialization ctor
- Does NOT have GetObjectData override

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
The compilingFSharpCore guard skips GetObjectData, so the surface area
baseline should not include it for MatchFailureException.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@T-Gro T-Gro marked this pull request as ready for review March 6, 2026 11:46
@T-Gro T-Gro requested a review from a team as a code owner March 6, 2026 11:46
@T-Gro T-Gro changed the title WIP :: Bugfix :: Fix F# exception serialization to preserve fields Bugfix :: Fix F# exception serialization to preserve fields Mar 6, 2026
…ctors

Add deserialization constructor bodies (reading fields from SerializationInfo)
and GetObjectData overrides to match the netcore baselines.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: New

Development

Successfully merging this pull request may close these issues.

Serialization of F#-defined exception variants doesn't serialize fields

1 participant