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
3 changes: 2 additions & 1 deletion docs/release-notes/.FSharp.Compiler.Service/11.0.100.md
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@
* Fix signature generation: backtick escaping for identifiers containing backticks. ([Issue #15389](https://github.com/dotnet/fsharp/issues/15389), [PR #19586](https://github.com/dotnet/fsharp/pull/19586))
* Fix signature generation: `private` keyword placement for prefix-style type abbreviations. ([Issue #15560](https://github.com/dotnet/fsharp/issues/15560), [PR #19586](https://github.com/dotnet/fsharp/pull/19586))
* Fix signature generation: missing `[<Class>]` attribute for types without visible constructors. ([Issue #16531](https://github.com/dotnet/fsharp/issues/16531), [PR #19586](https://github.com/dotnet/fsharp/pull/19586))
* Fix F# exception serialization now preserves fields. (Issue [#878](https://github.com/dotnet/fsharp/issues/878), [PR #19342](https://github.com/dotnet/fsharp/pull/19342))
* Fix F# exception serialization now preserves fields (gated behind `--langversion:11`). (Issue [#878](https://github.com/dotnet/fsharp/issues/878), [PR #19342](https://github.com/dotnet/fsharp/pull/19342), [PR #19746](https://github.com/dotnet/fsharp/pull/19746))
* Fix methods being tagged as `Member` instead of `Method` in tooltips. ([Issue #10540](https://github.com/dotnet/fsharp/issues/10540), [PR #19507](https://github.com/dotnet/fsharp/pull/19507))
* Fix Debug-mode compilation when mixing resumable and standard computation expressions. ([Issue #19625](https://github.com/dotnet/fsharp/issues/19625), [PR #19630](https://github.com/dotnet/fsharp/pull/19630))
* IlxGen: fix missing CompilationMapping attribute for generic values ([PR #19643](https://github.com/dotnet/fsharp/pull/19643))
Expand All @@ -60,5 +60,6 @@
### Changed

* Improvements in error and warning messages: new error FS3885 when `let!`/`use!` is the final expression in a computation expression; new warning FS3886 when a list literal contains a single tuple element (likely missing `;` separator); improved wording for FS0003, FS0025, FS0039, FS0072, FS0247, FS0597, FS0670, FS3082, and SRTP operator-not-in-scope hints. ([PR #19398](https://github.com/dotnet/fsharp/pull/19398))
* Exception field serialization (`GetObjectData` and field-restoring constructor) is now gated behind `langversion:11` (`LanguageFeature.ExceptionFieldSerializationSupport`). With langversion ≤10, exception codegen is unchanged from pre-#19342 behavior. ([PR #19746](https://github.com/dotnet/fsharp/pull/19746))

### Breaking Changes
123 changes: 59 additions & 64 deletions src/Compiler/CodeGen/IlxGen.fs
Original file line number Diff line number Diff line change
Expand Up @@ -12271,11 +12271,10 @@ and GenExnDef cenv mgbuf eenv m (exnc: Tycon) : ILTypeRef option =
[]

let serializationRelatedMembers =
// do not emit serialization related members if target framework lacks SerializationInfo or StreamingContext
match g.iltyp_SerializationInfo, g.iltyp_StreamingContext with
| Some serializationInfoType, Some streamingContextType ->

let emitSerializationFieldIL emitPerField =
let emitFieldSerializationIL emitPerField =
[
for (_, ilFieldName, ilPropType, _) in fieldNamesAndTypes do
yield! emitPerField ilFieldName ilPropType
Expand All @@ -12285,7 +12284,7 @@ and GenExnDef cenv mgbuf eenv m (exnc: Tycon) : ILTypeRef option =
ty.IsNominal && ty.Boxity = ILBoxity.AsValue

let ilInstrsToRestoreFields =
emitSerializationFieldIL (fun ilFieldName ilPropType ->
emitFieldSerializationIL (fun ilFieldName ilPropType ->
[
mkLdarg0
mkLdarg 1us
Expand Down Expand Up @@ -12318,10 +12317,10 @@ and GenExnDef cenv mgbuf eenv m (exnc: Tycon) : ILTypeRef option =
mkNormalStfld (mkILFieldSpecInTy (ilThisTy, ilFieldName, ilPropType))
])

// FSharp.Core is SecurityTransparent and cannot override SecurityCritical
// Exception.GetObjectData, so field restoration would be unbalanced — skip it.
let shouldRestoreFields =
not g.compilingFSharpCore && not fieldNamesAndTypes.IsEmpty
let emitFieldSerialization =
cenv.g.langVersion.SupportsFeature(LanguageFeature.ExceptionFieldSerializationSupport)
&& not g.compilingFSharpCore
&& not fieldNamesAndTypes.IsEmpty

let ilInstrsForSerialization =
[
Expand All @@ -12330,7 +12329,10 @@ and GenExnDef cenv mgbuf eenv m (exnc: Tycon) : ILTypeRef option =
mkLdarg 2us
mkNormalCall (mkILCtorMethSpecForTy (g.iltyp_Exception, [ serializationInfoType; streamingContextType ]))
]
@ (if shouldRestoreFields then ilInstrsToRestoreFields else [])
@ (if emitFieldSerialization then
ilInstrsToRestoreFields
else
[])
|> nonBranchingInstrsToCode

let ilCtorDefForSerialization =
Expand All @@ -12344,73 +12346,66 @@ and GenExnDef cenv mgbuf eenv m (exnc: Tycon) : ILTypeRef option =
)
|> AddNonUserCompilerGeneratedAttribs g

let ilInstrsToSaveFields =
emitSerializationFieldIL (fun ilFieldName ilPropType ->
if not emitFieldSerialization then
[ ilCtorDefForSerialization ]
else
let ilInstrsToSaveFields =
emitFieldSerializationIL (fun ilFieldName ilPropType ->
[
mkLdarg 1us
I_ldstr ilFieldName
mkLdarg0
mkNormalLdfld (mkILFieldSpecInTy (ilThisTy, ilFieldName, ilPropType))

if isILValueType ilPropType then
I_box ilPropType

mkNormalCallvirt (
mkILNonGenericInstanceMethSpecInTy (
serializationInfoType,
"AddValue",
[ g.ilg.typ_String; g.ilg.typ_Object ],
ILType.Void
)
)
])

let ilInstrsForGetObjectData =
[
mkLdarg 1us
I_ldstr ilFieldName
mkLdarg0
mkNormalLdfld (mkILFieldSpecInTy (ilThisTy, ilFieldName, ilPropType))

if isILValueType ilPropType then
I_box ilPropType

mkNormalCallvirt (
mkLdarg 1us
mkLdarg 2us
mkNormalCall (
mkILNonGenericInstanceMethSpecInTy (
serializationInfoType,
"AddValue",
[ g.ilg.typ_String; g.ilg.typ_Object ],
g.iltyp_Exception,
"GetObjectData",
[ serializationInfoType; streamingContextType ],
ILType.Void
)
)
])
]
@ ilInstrsToSaveFields
|> nonBranchingInstrsToCode

let ilInstrsForGetObjectData =
[
mkLdarg0
mkLdarg 1us
mkLdarg 2us
mkNormalCall (
mkILNonGenericInstanceMethSpecInTy (
g.iltyp_Exception,
let ilGetObjectDataDef =
let securityCriticalAttr =
mkILCustomAttribute (g.attrib_SecurityCriticalAttribute.TypeRef, [], [], [])

let mdef =
mkILNonGenericVirtualInstanceMethod (
"GetObjectData",
[ serializationInfoType; streamingContextType ],
ILType.Void
ILMemberAccess.Public,
[
mkILParamNamed ("info", serializationInfoType)
mkILParamNamed ("context", streamingContextType)
],
mkILReturn ILType.Void,
mkMethodBody (false, [], 8, ilInstrsForGetObjectData, None, eenv.imports)
)
)
]
@ ilInstrsToSaveFields
|> nonBranchingInstrsToCode

let ilGetObjectDataDef =
let mdef =
mkILNonGenericVirtualInstanceMethod (
"GetObjectData",
ILMemberAccess.Public,
[
mkILParamNamed ("info", serializationInfoType)
mkILParamNamed ("context", streamingContextType)
],
mkILReturn ILType.Void,
mkMethodBody (false, [], 8, ilInstrsForGetObjectData, None, eenv.imports)
)

// SecurityCritical is required for .NET Framework where Exception.GetObjectData is security-critical
let securityCriticalAttr =
mkILCustomAttribute (g.attrib_SecurityCriticalAttribute.TypeRef, [], [], [])
mdef.With(customAttrs = mkILCustomAttrs [ securityCriticalAttr ])
|> AddNonUserCompilerGeneratedAttribs g

mdef.With(customAttrs = mkILCustomAttrs [ securityCriticalAttr ])
|> AddNonUserCompilerGeneratedAttribs g

// FSharp.Core has [assembly: SecurityTransparent], making all code transparent.
// On .NET Framework, transparent code cannot override SecurityCritical virtual
// methods like Exception.GetObjectData. Without GetObjectData to write the fields,
// the field-restoring deserialization constructor would crash (fields not in
// SerializationInfo). So for FSharp.Core: emit only the base-call ctor (status quo).
// For user exceptions: emit both GetObjectData and the field-restoring ctor.
if g.compilingFSharpCore || fieldNamesAndTypes.IsEmpty then
[ ilCtorDefForSerialization ]
else
[ ilCtorDefForSerialization; ilGetObjectDataDef ]
| _ -> []

Expand Down
1 change: 1 addition & 0 deletions src/Compiler/FSComp.txt
Original file line number Diff line number Diff line change
Expand Up @@ -1818,3 +1818,4 @@ featurePreprocessorElif,"#elif preprocessor directive"
3885,parsLetBangCannotBeLastInCE,"'%s' cannot be the final expression in a computation expression. Finish with 'return', 'return!', or a simple expression."
3886,tcListLiteralWithSingleTupleElement,"This list expression contains a single tuple element. Did you mean to use ';' instead of ',' to separate list elements?"
3887,ilCustomAttrInvalidArrayElemType,"The type '%s' is not a valid custom attribute argument type. Custom attribute arrays must have elements of primitive types, enums, string, System.Type, or System.Object."
featureExceptionFieldSerializationSupport,"emit GetObjectData and field-restoring deserialization constructor for exception types"
3 changes: 3 additions & 0 deletions src/Compiler/Facilities/LanguageFeatures.fs
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,7 @@ type LanguageFeature =
| MethodOverloadsCache
| ImplicitDIMCoverage
| PreprocessorElif
| ExceptionFieldSerializationSupport

/// LanguageVersion management
type LanguageVersion(versionText, ?disabledFeaturesArray: LanguageFeature array) =
Expand Down Expand Up @@ -251,6 +252,7 @@ type LanguageVersion(versionText, ?disabledFeaturesArray: LanguageFeature array)
// Put stabilized features here for F# 11.0 previews via .NET SDK preview channels
LanguageFeature.WarnWhenFunctionValueUsedAsInterpolatedStringArg, languageVersion110
LanguageFeature.PreprocessorElif, languageVersion110
LanguageFeature.ExceptionFieldSerializationSupport, languageVersion110

// Difference between languageVersion110 and preview - 11.0 gets turned on automatically by picking a preview .NET 11 SDK
// previewVersion is only when "preview" is specified explicitly in project files and users also need a preview SDK
Expand Down Expand Up @@ -453,6 +455,7 @@ type LanguageVersion(versionText, ?disabledFeaturesArray: LanguageFeature array)
| LanguageFeature.MethodOverloadsCache -> FSComp.SR.featureMethodOverloadsCache ()
| LanguageFeature.ImplicitDIMCoverage -> FSComp.SR.featureImplicitDIMCoverage ()
| LanguageFeature.PreprocessorElif -> FSComp.SR.featurePreprocessorElif ()
| LanguageFeature.ExceptionFieldSerializationSupport -> FSComp.SR.featureExceptionFieldSerializationSupport ()

/// Get a version string associated with the given feature.
static member GetFeatureVersionString feature =
Expand Down
1 change: 1 addition & 0 deletions src/Compiler/Facilities/LanguageFeatures.fsi
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,7 @@ type LanguageFeature =
| MethodOverloadsCache
| ImplicitDIMCoverage
| PreprocessorElif
| ExceptionFieldSerializationSupport

/// LanguageVersion management
type LanguageVersion =
Expand Down
5 changes: 5 additions & 0 deletions src/Compiler/xlf/FSComp.txt.cs.xlf

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 5 additions & 0 deletions src/Compiler/xlf/FSComp.txt.de.xlf

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 5 additions & 0 deletions src/Compiler/xlf/FSComp.txt.es.xlf

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 5 additions & 0 deletions src/Compiler/xlf/FSComp.txt.fr.xlf

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 5 additions & 0 deletions src/Compiler/xlf/FSComp.txt.it.xlf

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 5 additions & 0 deletions src/Compiler/xlf/FSComp.txt.ja.xlf

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 5 additions & 0 deletions src/Compiler/xlf/FSComp.txt.ko.xlf

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 5 additions & 0 deletions src/Compiler/xlf/FSComp.txt.pl.xlf

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 5 additions & 0 deletions src/Compiler/xlf/FSComp.txt.pt-BR.xlf

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 5 additions & 0 deletions src/Compiler/xlf/FSComp.txt.ru.xlf

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading