F# frontend coverage

The F# constructs that the F# frontend refuses, with their diagnostic codes and examples.

The F# frontend compiles a subset of F#. Before it lowers a document, admission checks the syntax and refuses each construct outside the subset with an error diagnostic. All refusals of a run are reported together, and the frontend writes no model. The overview describes the supported subset.

This page is generated from the admission catalog of the frontend, so it lists every code that admission can report. Each rule has a minimal example that gives only its own code. The conformance corpus has one refusal case for each code. Codes are stable once released.

Codes

CodeConstruct
fsharp.unsupported_mutablemutable binding or field
fsharp.unsupported_assignmentassignment
fsharp.unsupported_looploop
fsharp.unsupported_classclass
fsharp.unsupported_interfaceinterface
fsharp.unsupported_membermember
fsharp.unsupported_object_expressionobject expression
fsharp.unsupported_sequence_expressionsequence expression
fsharp.unsupported_computation_expressioncomputation expression
fsharp.unsupported_comprehensionlist comprehension or range
fsharp.unsupported_arrayarray
fsharp.unsupported_exceptionexception
fsharp.unsupported_active_patternactive pattern
fsharp.unsupported_unit_of_measureunit of measure
fsharp.unsupported_quotationquotation
fsharp.unsupported_anonymous_recordanonymous record
fsharp.unsupported_structstruct type or struct tuple
fsharp.unsupported_inlineinline function
fsharp.unsupported_attributeattribute with an effect
fsharp.unsupported_type_testtype test
fsharp.unsupported_castcast
fsharp.unsupported_nullnull
fsharp.unsupported_useuse binding
fsharp.unsupported_sequentialsequential expression
fsharp.unsupported_literalliteral of an unsupported type
fsharp.unsupported_enumenum
fsharp.unsupported_delegatedelegate
fsharp.unsupported_pattern_guardpattern guard
fsharp.unsupported_or_patternor pattern
fsharp.unsupported_record_patternrecord pattern
fsharp.unsupported_list_patternlist pattern with elements
fsharp.unsupported_named_field_patternnamed field pattern
fsharp.unsupported_conditional_compilationconditional compilation
fsharp.unsupported_signature_filesignature file

The fallback rules below refuse any expression, pattern, type or declaration outside the supported subset that no specific rule refused.

CodeConstruct
fsharp.unsupported_expressionexpression outside the supported subset
fsharp.unsupported_patternpattern outside the supported subset
fsharp.unsupported_typetype outside the supported subset
fsharp.unsupported_declarationdeclaration outside the supported subset

Rules

fsharp.unsupported_mutable

Construct: mutable binding or field

Message: Mutable bindings and fields are not supported; Morphir values are immutable.

Suggestion: Use a new let binding, or a record update, instead of changing a value.

Example. The diagnostic is at mutable.

Example.fs:

namespace Acme.Demo
module Example =
    let mutable total = 0

fsharp.unsupported_assignment

Construct: assignment

Message: Assignment with ‘<-’ is not supported; Morphir values are immutable.

Suggestion: Return a new value instead of changing an existing one.

Example. The diagnostic is at builder.Length <- 0.

Example.fs:

namespace Acme.Demo
module Example =
    let reset (builder: System.Text.StringBuilder) = builder.Length <- 0

fsharp.unsupported_loop

Construct: loop

Message: Loops (‘for’, ‘while’) are not supported; Morphir has no statements.

Suggestion: Use recursion or a List function such as List.map or List.fold.

Example. The diagnostic is at for index in 1 .. 3 do ignore index.

Example.fs:

namespace Acme.Demo
module Example =
    let count () = for index in 1 .. 3 do ignore index

fsharp.unsupported_class

Construct: class

Message: Classes are not supported; Morphir types are records, unions and type abbreviations.

Suggestion: Use a record for the data and module functions for the behavior.

Example. The diagnostic is at this text:

Counter() =
        member _.Value = 1

Example.fs:

namespace Acme.Demo
module Example =
    type Counter() =
        member _.Value = 1

fsharp.unsupported_interface

Construct: interface

Message: Interfaces are not supported; Morphir has no subtyping.

Suggestion: Use a record of functions, or a union of the cases.

Example. The diagnostic is at this text:

IShape =
        abstract Area: float

Example.fs:

namespace Acme.Demo
module Example =
    type IShape =
        abstract Area: float

fsharp.unsupported_member

Construct: member

Message: Members and type extensions are not supported; Morphir types have no methods.

Suggestion: Define a module function that takes the value as a parameter.

Example. The diagnostic is at member this.Double = this.Seats * 2.

Example.fs:

namespace Acme.Demo
module Example =
    type Car = { Seats: int } with
        member this.Double = this.Seats * 2

fsharp.unsupported_object_expression

Construct: object expression

Message: Object expressions are not supported; Morphir has no objects.

Suggestion: Use a record of functions.

Example. The diagnostic is at { new System.Object() with member _.ToString() = "x" }.

Example.fs:

namespace Acme.Demo
module Example =
    let text = { new System.Object() with member _.ToString() = "x" }

fsharp.unsupported_sequence_expression

Construct: sequence expression

Message: Sequence expressions (‘seq { }’) are not supported; Morphir has no lazy sequences.

Suggestion: Use a list and the List functions.

Example. The diagnostic is at { yield 1 }.

Example.fs:

namespace Acme.Demo
module Example =
    let numbers = seq { yield 1 }

fsharp.unsupported_computation_expression

Construct: computation expression

Message: Computation expressions are not supported; Morphir has no effects or builders.

Suggestion: Write the steps as plain functions, for example with Result.bind.

Example. The diagnostic is at { return 1 }.

Example.fs:

namespace Acme.Demo
module Example =
    let work = async { return 1 }

fsharp.unsupported_comprehension

Construct: list comprehension or range

Message: List comprehensions and ranges (’[ for … ]’, ‘[ 1 .. 3 ]’) are not supported.

Suggestion: Use List.map, List.filter or an explicit list.

Example. The diagnostic is at [ for x in [ 1; 2 ] -> x * x ].

Example.fs:

namespace Acme.Demo
module Example =
    let squares = [ for x in [ 1; 2 ] -> x * x ]

fsharp.unsupported_array

Construct: array

Message: Arrays are not supported; Morphir collections are immutable lists.

Suggestion: Use a list.

Example. The diagnostic is at [| 1; 2 |].

Example.fs:

namespace Acme.Demo
module Example =
    let numbers = [| 1; 2 |]

fsharp.unsupported_exception

Construct: exception

Message: Exceptions (’exception’, ’try … with’, ’try … finally’) are not supported; Morphir has no effects.

Suggestion: Return a Result or an option.

Example. The diagnostic is at exception Failed of string.

Example.fs:

namespace Acme.Demo
module Example =
    exception Failed of string

fsharp.unsupported_active_pattern

Construct: active pattern

Message: Active patterns are not supported; Morphir patterns match only constructors and values.

Suggestion: Use a union and a function that returns it.

Example. The diagnostic is at let (|Even|Odd|) n = if n % 2 = 0 then Even else Odd.

Example.fs:

namespace Acme.Demo
module Example =
    let (|Even|Odd|) n = if n % 2 = 0 then Even else Odd

fsharp.unsupported_unit_of_measure

Construct: unit of measure

Message: Units of measure are not supported; Morphir numbers carry no unit.

Suggestion: Use a single-case union to name the quantity.

Example. The diagnostic is at [<Measure>] type kg.

Example.fs:

namespace Acme.Demo
module Example =
    [<Measure>] type kg

fsharp.unsupported_quotation

Construct: quotation

Message: Quotations are not supported; Morphir models values, not code.

Example. The diagnostic is at <@ 1 + 1 @>.

Example.fs:

namespace Acme.Demo
module Example =
    let expression = <@ 1 + 1 @>

fsharp.unsupported_anonymous_record

Construct: anonymous record

Message: Anonymous records are not supported; Morphir record types have names.

Suggestion: Declare a record type.

Example. The diagnostic is at {| X = 1 |}.

Example.fs:

namespace Acme.Demo
module Example =
    let point = {| X = 1 |}

fsharp.unsupported_struct

Construct: struct type or struct tuple

Message: Struct types and struct tuples are not supported; Morphir has no value-type layout.

Suggestion: Remove [] or ‘struct’.

Example. The diagnostic is at struct (1, 2).

Example.fs:

namespace Acme.Demo
module Example =
    let pair = struct (1, 2)

fsharp.unsupported_inline

Construct: inline function

Message: Inline functions are not supported; Morphir functions are not specialized at their call sites.

Suggestion: Remove ‘inline’ and give the parameters concrete types.

Example. The diagnostic is at inline.

Example.fs:

namespace Acme.Demo
module Example =
    let inline double (x: int) = x * 2

fsharp.unsupported_attribute

Construct: attribute with an effect

Message: This attribute changes the meaning of the code and is not supported.

Suggestion: Remove the attribute. Only RequireQualifiedAccess, AutoOpen, CompilationRepresentation, CompiledName and MorphirName are accepted.

Example. The diagnostic is at Literal.

Example.fs:

namespace Acme.Demo
module Example =
    [<Literal>]
    let Limit = 10

fsharp.unsupported_type_test

Construct: type test

Message: Type tests (’:?’) are not supported; Morphir has no runtime types.

Suggestion: Use a union to tell the cases apart.

Example. The diagnostic is at value :? string.

Example.fs:

namespace Acme.Demo
module Example =
    let isText (value: obj) = value :? string

fsharp.unsupported_cast

Construct: cast

Message: Casts (’:>’, ‘:?>’, ‘upcast’, ‘downcast’) are not supported; Morphir has no subtyping.

Example. The diagnostic is at 1 :> obj.

Example.fs:

namespace Acme.Demo
module Example =
    let boxed = (1 :> obj)

fsharp.unsupported_null

Construct: null

Message: ’null’ is not supported; Morphir values are never null.

Suggestion: Use an option.

Example. The diagnostic is at null.

Example.fs:

namespace Acme.Demo
module Example =
    let nothing: string = null

fsharp.unsupported_use

Construct: use binding

Message: ‘use’ bindings are not supported; Morphir has no resources to dispose.

Suggestion: Use ’let’.

Example. The diagnostic is at this text:

use stream = new System.IO.MemoryStream()
        stream.Length

Example.fs:

namespace Acme.Demo
module Example =
    let size () =
        use stream = new System.IO.MemoryStream()
        stream.Length

fsharp.unsupported_sequential

Construct: sequential expression

Message: Sequential expressions (‘a; b’) are not supported; Morphir values have no side effects.

Suggestion: Remove the expression whose value is discarded.

Example. The diagnostic is at this text:

ignore 1
        2

Example.fs:

namespace Acme.Demo
module Example =
    let both () =
        ignore 1
        2

fsharp.unsupported_literal

Construct: literal of an unsupported type

Message: This literal type is not supported; Morphir numbers are Int, Float and Decimal.

Suggestion: Use an int, int64, float or decimal literal.

Example. The diagnostic is at 1uy.

Example.fs:

namespace Acme.Demo
module Example =
    let small = 1uy

fsharp.unsupported_enum

Construct: enum

Message: Enums are not supported; Morphir custom types have no numeric values.

Suggestion: Use a union without fields.

Example. The diagnostic is at this text:

Color =
        | Red = 0
        | Blue = 1

Example.fs:

namespace Acme.Demo
module Example =
    type Color =
        | Red = 0
        | Blue = 1

fsharp.unsupported_delegate

Construct: delegate

Message: Delegates are not supported; Morphir has function types.

Suggestion: Use a function type.

Example. The diagnostic is at Handler = delegate of int -> unit.

Example.fs:

namespace Acme.Demo
module Example =
    type Handler = delegate of int -> unit

fsharp.unsupported_pattern_guard

Construct: pattern guard

Message: Pattern guards (‘when’) are not supported; a Morphir pattern has no condition.

Suggestion: Match the case, then use ‘if’ in its body.

Example. The diagnostic is at n > 3.

Example.fs:

namespace Acme.Demo
module Example =
    let size n =
        match n with
        | n when n > 3 -> "big"
        | _ -> "small"

fsharp.unsupported_or_pattern

Construct: or pattern

Message: Or patterns (‘A | B’) are not supported; a Morphir case has one pattern.

Suggestion: Write one case for each alternative.

Example. The diagnostic is at 1 | 2.

Example.fs:

namespace Acme.Demo
module Example =
    let low n =
        match n with
        | 1 | 2 -> true
        | _ -> false

fsharp.unsupported_record_pattern

Construct: record pattern

Message: Record patterns are not supported.

Suggestion: Bind the record to a variable and read its fields.

Example. The diagnostic is at { Seats = s }.

Example.fs:

namespace Acme.Demo
module Example =
    type Car = { Seats: int }
    let seats car =
        match car with
        | { Seats = s } -> s

fsharp.unsupported_list_pattern

Construct: list pattern with elements

Message: List patterns with elements (’[ a; b ]’) are not supported.

Suggestion: Use ‘::’ and ‘[]’ patterns.

Example. The diagnostic is at [ a ].

Example.fs:

namespace Acme.Demo
module Example =
    let first xs =
        match xs with
        | [ a ] -> a
        | _ -> 0

fsharp.unsupported_named_field_pattern

Construct: named field pattern

Message: Named field patterns (‘Case(field = p)’) are not supported.

Suggestion: Match the fields by position.

Example. The diagnostic is at Rented(days = d).

Example.fs:

namespace Acme.Demo
module Example =
    type Status = Rented of days: int
    let days status =
        match status with
        | Rented(days = d) -> d

fsharp.unsupported_conditional_compilation

Construct: conditional compilation

Message: Conditional compilation (’#if’) is not supported, because this frontend does not choose defines.

Suggestion: Remove the directive, or keep one branch.

Example. The diagnostic is at #if DEBUG.

Example.fs:

namespace Acme.Demo
module Example =
#if DEBUG
    let mode = "debug"
#else
    let mode = "release"
#endif

fsharp.unsupported_signature_file

Construct: signature file

Message: Signature files (’.fsi’) are not supported; access comes from F# visibility and the exposed modules.

Suggestion: Remove the signature file and use ‘private’ or ‘internal’.

Example. The diagnostic is an empty range at the start of the first document.

Example.fsi:

namespace Acme.Demo
module Example =
    val total: int

Example.fs:

namespace Acme.Demo
module Example =
    let total = 1

fsharp.unsupported_expression

Construct: expression outside the supported subset

Message: This kind of expression is not supported by the F# frontend.

Example. The diagnostic is at lazy 1.

Example.fs:

namespace Acme.Demo
module Example =
    let later = lazy 1

fsharp.unsupported_pattern

Construct: pattern outside the supported subset

Message: This kind of pattern is not supported by the F# frontend.

Example. The diagnostic is at (a, _) & (_, b).

Example.fs:

namespace Acme.Demo
module Example =
    let both pair =
        match pair with
        | (a, _) & (_, b) -> a + b

fsharp.unsupported_type

Construct: type outside the supported subset

Message: This kind of type is not supported by the F# frontend.

Example. The diagnostic is at #seq<int>.

Example.fs:

namespace Acme.Demo
module Example =
    let total (values: #seq<int>) = Seq.sum values

fsharp.unsupported_declaration

Construct: declaration outside the supported subset

Message: This kind of declaration is not supported by the F# frontend.

Example. The diagnostic is at do ignore 1.

Example.fs:

namespace Acme.Demo
module Example =
    do ignore 1