F# Language
Preview
Added
Runtime async:
task/async-style computation expressions can be compiled to use the .NET runtime async support (RuntimeAsync preview feature). (PR #20235)Extension members for operators and SRTP constraints (RFC FS-1043, fslang-suggestions#230, PR #19602): Extension methods now participate in SRTP constraint resolution. This allows defining operators on types you don't own via type extensions:
type System.String with static member (*) (s: string, n: int) = String.replicate n s let inline multiply (x: ^T) (n: int) = x * n let result = multiply "ha" 3 // "hahaha"Feature flag:
--langversion:preview(feature name:ExtensionConstraintSolutions)Includes:
- Extension operators resolve via SRTP constraints (suggestion #230)
- Only public members solve SRTP constraints — a
private,internal, orprotectedmember (even one visible at the definition site, or exposed viaInternalsVisibleTo) is not a valid witness and is rejected at compile time - Intrinsic members take priority over extension members
- FS1215 warning suppressed when defining extension operators with preview langversion
- Weak resolution disabled for inline code, keeping SRTP constraints generic
[<AllowOverloadOnReturnType>]attribute for defining overloads that differ only by return type (suggestion #820). When applied, return-type information is used during overload resolution to disambiguate call sites.- Cross-assembly resolution: extension operators defined in referenced assemblies are resolved via SRTP constraints
- Extension members solve SRTP constraints but do not satisfy nominal static abstract interface constraints (IWSAMs). These are orthogonal mechanisms.
- Tuple type extensions using syntactic tuple notation:
type ('T1 * 'T2) withfor reference tuples andtype struct ('T1 * 'T2) withfor struct tuples. These are transformed toSystem.Tuple<'T1,'T2>andSystem.ValueTuple<'T1,'T2>extensions respectively.
Warn (FS3884) when a function or delegate value is used as an interpolated string argument, since it will be formatted via
ToStringrather than being applied. (PR #19289)Added
MethodOverloadsCachelanguage feature (preview) that caches overload resolution results for repeated method calls, significantly improving compilation performance. (PR #19072)Added
ErrorOnMissingSignatureAttributepreview language feature: makes FS3888 (compiler-semantic attribute on the.fsbut not on the.fsi) an error instead of a warning. (Issue #19560, PR #19880)Support common types of
NotNullIfNotNullAttributeusage. If a method parameter is marked withNotNullIfNotNullAttribute, the compiler will now honor this attribute and mark the return type as non-null. (PR #19977)Spread operator for records (RFC FS-1151, PR #18927)
Added
AccessProtectedBaseFieldFromClosurepreview language feature: a derived member can now read aprotectedbase-class field from an ordinary closure (lambda, delegate,async/seq/lazy,function, or list/array literal), which previously failed with FS1097 even though direct access compiles. Object expressions remain unsupported — bind the field to a local function or expose it through a member. (Issue #5302)Added
ImprovedImpliedArgumentNamesPartTwolanguage feature: when a function with no recoverable parameter names is coerced to a delegate (e.g. a partial application likeSystem.Func<int, int>((+) 1)), the synthesizedInvokeparameters take their names from the delegate's ownInvokesignature instead of syntheticdelegateArg0,delegateArg1, … names. (PR #20001)Added a "most concrete" tiebreaker for overload resolution: when several overloads of a method, constructor, or generic-type member are equally applicable, the one with more concrete parameter types is preferred instead of reporting an ambiguity. Requires
--langversion:preview. (RFC FS-1340, PR #19277)Added support for
System.Runtime.CompilerServices.OverloadResolutionPriorityAttribute(.NET 9): overloads with a higher priority value are preferred during resolution, matching C#. Requires--langversion:preview. (RFC FS-1338, PR #19277)Allow constructing a record via its all-fields constructor, e.g.
MyRecord(a, b), with positional or named arguments (RecordConstructorSyntaxpreview feature). Accessibility matches{ ... }construction. (Suggestion #722, RFC FS-1073, PR #19974)Added support for
System.Diagnostics.CodeAnalysis.RequireNamedArgumentsAttribute: annotated methods and constructors require named arguments, and positional calls report FS3923. The compiler recognises the attribute by full type name, including local polyfills, referenced assemblies, and type-provider metadata.nameofremains allowed. Requires--langversion:preview. (Suggestion #414, RFC FS-1095, Approved API, PR #20340)
Fixed
- Explicit generic type arguments are now unified in constraint-dependency order, so a subtype constraint that references a later type parameter (e.g.
Register<'a, 'b when 'a :> I<'b>>called as<Foo, int>) no longer fails with FS0001 when the argument implements the interface at several instantiations. (Issue #20103, PR #20342) - Bitwise operators (
|||,&&&,^^^) on enums whose underlying type is not an integer type (e.g.char) are now a compile-time error (FS0001, consistent with~~~,<<<,>>>) instead of a runtimeNotSupportedException. (Issue #11785, PR #20322)
Changed
- Inline functions now keep SRTP constraints generic instead of eagerly resolving through weak resolution. This changes inferred types for some inline code — see RFC FS-1043 compatibility section for details and workarounds.
- Remove the always-on
ErrorReportingOnStaticClasseslanguage feature flag. Static-class validation remains unchanged for all supported language versions. (Issue #20180, PR #20513)
11.0
Added
- Simplify implementation of interface hierarchies with equally named abstract slots: when a derived interface provides a Default Interface Member (DIM) implementation for a base interface slot, F# no longer requires explicit interface declarations for the DIM-covered slot. (Language suggestion #1430, RFC FS-1336, PR #19241)
- Support
#elifpreprocessor directive (Language suggestion #1370, RFC FS-1334, PR #XXXXX) - Warn (FS3884) when a function or delegate value is used as an interpolated string argument, since it will be formatted via
ToStringrather than being applied. (PR #19289) - Added
MethodOverloadsCachelanguage feature that caches overload resolution results for repeated method calls, significantly improving compilation performance. (PR #19072) - Added
ErrorOnMissingSignatureAttributelanguage feature: makes FS3888 (compiler-semantic attribute on the.fsbut not on the.fsi) an error instead of a warning. (Issue #19560, PR #19880) [<OptimizeClosureIfNotInlined>], paired with[<InlineIfLambda>]on a curried arity 2–5 callback of an inlined function, makes the optimizer adapt the callback once viaOptimizedClosureswhen it is passed opaquely rather than as a known lambda (featureOptimizeClosureIfNotInlined). (PR #20422)- Support common types of
NotNullIfNotNullAttributeusage. If a method parameter is marked withNotNullIfNotNullAttribute, the compiler will now honor this attribute and mark the return type as non-null. (PR #19977) - Spread operator for records (RFC FS-1151, PR #18927)
- Added
AccessProtectedBaseFieldFromClosurelanguage feature: a derived member can now read aprotectedbase-class field from an ordinary closure (lambda, delegate,async/seq/lazy,function, or list/array literal), which previously failed with FS1097 even though direct access compiles. Object expressions remain unsupported — bind the field to a local function or expose it through a member. (Issue #5302) - Added
ImprovedImpliedArgumentNamesPartTwolanguage feature: when a function with no recoverable parameter names is coerced to a delegate (e.g. a partial application likeSystem.Func<int, int>((+) 1)), the synthesizedInvokeparameters take their names from the delegate's ownInvokesignature instead of syntheticdelegateArg0,delegateArg1, … names. (PR #20001)
Fixed
Changed
- Lines starting with
#:are now ignored (Language suggestion 1440, RFC FS-1337, PR #20212) - Direct delegate construction (PR #19993)
- A delegate built from a method or function now points straight at that method instead of an intermediate closure, so
delegate.Methodis the real target and no closure class is generated. - Two delegates built from the same method and target now compare equal, where the previous closure form produced distinct instances; this also makes
Delegate.Remove(and-=on events) match and remove such a delegate that it previously left in place. - A
nullinstance receiver now faults at delegate construction rather than at the first invoke: anArgumentExceptionfor a non-virtual target (the delegate constructor rejects a nullthis) or aNullReferenceExceptionfor a virtual one (fromldvirtftn), matching how C# builds the same delegate.
- A delegate built from a method or function now points straight at that method instead of an intermediate closure, so
10.0.200
Added
- Add
--disableLanguageFeatureCLI switch and MSBuild property to selectively disable specific F# language features on a per-project basis. (PR #19167)
10.0
Added
- Better generic unmanaged structs handling. (Language suggestion #692, PR #12154)
- Deprecate places where
seqcan be omitted. (Language suggestion #1033, PR #17772) - Added type conversions cache, only enabled for compiler runs (PR#17668)
- Support ValueOption + Struct attribute as optional parameter for methods (Language suggestion #1136, PR #18098)
- Allow
_inuse!bindings values (lift FS1228 restriction) (PR #18487) - Warn when
unitis passed to anobj-typed argument (PR #18330) - Fix parsing errors using anonymous records and units of measures (PR #18543)
- Scoped Nowarn: added the #warnon compiler directive (Language suggestion #278, RFC FS-1146 PR, PR #18049)
- Allow
let!,use!,and!type annotations without requiring parentheses ((PR #18508 and PR #18682)) - Exception names are now validated for illegal characters using the same mechanism as types/modules/namespaces (Issue #18763, PR #18768)
- Support tail calls in computation expressions (PR #18804)
Fixed
- Warn on uppercase identifiers in patterns. (PR #15816)
- Error on invalid declarations in type definitions.(Issue #10066, PR #18813)
- Fix type erasure logic for
nativeptr<'T>overloads to properly preserve element type differences during duplicate member checking. (PR #18911)
Changed
- Removed parsing support for long-deprecated ML constructs and non-light syntax. (PR #19143)
- Released
asr,land,lor,lsl,lsrandlxoras usable keywords (note:modcontinues to be reserved). (PR #19143)
9.0
Added
- Speed up
for x in xs -> …in list & array comprehensions in certain scenarios. (PR #16948) - Lower integral ranges to fast loops in more cases and optimize list and array construction from ranges. (PR #16650, PR #16832)
- Support for nullable reference types (PR #15181)
- Bidirectional F#/C# interop for 'unmanaged' constraint. (PR #12154)
- Make
.Is*discriminated union properties visible. (Language suggestion #222, PR #16341) - Allow returning bool instead of unit option for partial active patterns. (Language suggestion #1041, PR #16473)
- Allow access modifies to auto properties getters and setters (Language suggestion #430, PR 16687, PR 16861, PR 17522)
- Allow #nowarn to support the FS prefix on error codes to disable warnings (Issue #17206, PR #17209)
- Allow ParsedHashDirectives to have argument types other than strings (Issue #17240, PR #17209)
- Support empty-bodied computation expressions. (Language suggestion #1232, PR #17352)
- Allow object expression without overrides. (Language suggestion #632, PR #17387)
- Enable FSharp 9.0 Language Version (Issue #17497), PR))
Fixed
- Allow extension methods without type attribute work for types from imported assemblies. (PR #16368)
- Enforce AttributeTargets on let values and functions. (PR #16692)
- Enforce AttributeTargets on union case declarations. (PR #16764)
- Enforce AttributeTargets on implicit constructors. (PR #16845)
- Enforce AttributeTargets on structs and classes (PR #16790)
- Ensure consistent interaction between ``#line
and#nowarn` directives (PR #17649) - Revert EnforceAttributeTargets Feature. (PR #18005)
Changed
- Lower interpolated strings to string concatenation. (PR #16556)
8.0
Fixed
- Disallow using base to invoke an abstract base method (Issue #13926, PR #16773)
Added
while!(Language suggestion #1038, PR #14238)
type Path =
static member ChangeExtension: path: string * extension: string -> string
static member Combine: path1: string * path2: string -> string + 4 overloads
static member EndsInDirectorySeparator: path: ReadOnlySpan<char> -> bool + 1 overload
static member Exists: path: string -> bool
static member GetDirectoryName: path: ReadOnlySpan<char> -> ReadOnlySpan<char> + 1 overload
static member GetExtension: path: ReadOnlySpan<char> -> ReadOnlySpan<char> + 1 overload
static member GetFileName: path: ReadOnlySpan<char> -> ReadOnlySpan<char> + 1 overload
static member GetFileNameWithoutExtension: path: ReadOnlySpan<char> -> ReadOnlySpan<char> + 1 overload
static member GetFullPath: path: string -> string + 1 overload
static member GetInvalidFileNameChars: unit -> char array
...
Path.Combine( paths: string array) : string
Path.Combine(path1: string, path2: string) : string
Path.Combine(path1: string, path2: string, path3: string) : string
Path.Combine(path1: string, path2: string, path3: string, path4: string) : string
val processFolder: path: string -> processFile: (string -> string) -> string
Path.GetFileNameWithoutExtension(path: System.ReadOnlySpan<char>) : System.ReadOnlySpan<char>
type File =
static member AppendAllBytes: path: string * bytes: byte array -> unit + 1 overload
static member AppendAllBytesAsync: path: string * bytes: byte array * ?cancellationToken: CancellationToken -> Task + 1 overload
static member AppendAllLines: path: string * contents: string seq -> unit + 1 overload
static member AppendAllLinesAsync: path: string * contents: string seq * encoding: Encoding * ?cancellationToken: CancellationToken -> Task + 1 overload
static member AppendAllText: path: string * contents: ReadOnlySpan<char> -> unit + 3 overloads
static member AppendAllTextAsync: path: string * contents: ReadOnlyMemory<char> * encoding: Encoding * ?cancellationToken: CancellationToken -> Task + 3 overloads
static member AppendText: path: string -> StreamWriter
static member Copy: sourceFileName: string * destFileName: string -> unit + 1 overload
static member Create: path: string -> FileStream + 2 overloads
static member CreateSymbolicLink:
path: string *
pathToTarget: string ->
FileSystemInfo
...
File.ReadAllText(path: string, encoding: System.Text.Encoding) : string
type Markdown =
static member Convert:
markdown: string *
renderer: IMarkdownRenderer *
?pipeline: MarkdownPipeline *
?context: MarkdownParserContext ->
obj
static member Normalize: markdown: string * ?options: NormalizeOptions * ?pipeline: MarkdownPipeline * ?context: MarkdownParserContext -> string + 1 overload
static member Parse: markdown: string * ?trackTrivia: bool -> MarkdownDocument + 1 overload
static member ToHtml: markdown: string * ?pipeline: MarkdownPipeline * ?context: MarkdownParserContext -> string + 3 overloads
static member ToPlainText: markdown: string * writer: TextWriter * ?pipeline: MarkdownPipeline * ?context: MarkdownParserContext -> MarkdownDocument + 1 overload
static member Version: string
Markdown.ToHtml(document: Syntax.MarkdownDocument, writer: TextWriter, ?pipeline: MarkdownPipeline) : unit
Markdown.ToHtml( markdown: string, ?pipeline: MarkdownPipeline, ?context: MarkdownParserContext) : string
Markdown.ToHtml( markdown: string, writer: TextWriter, ?pipeline: MarkdownPipeline, ?context: MarkdownParserContext) : Syntax.MarkdownDocument
they need to follow a specific HTML structure.
val transformH3: version: string -> input: string -> string
F# Compiler Guide