Potentially critical issue: If the expression (e.g. a function call) inside a match ... with returns a struct union (e.g. ValueOption<_>, Result<_,_> or a custom struct union), the expression is evaluated twice, including any side effects.
Repro steps
Repro solution: Test.zip ConsoleApp1.zip
The repro solution consists of a console app with the following code, showing various examples and aspects of this bug:
open System
type CustomValueUnion = V
[<Struct>]
type CustomStructUnion = S
[<Struct>]
type CustomStructRecord =
{ A: CustomStructUnion }
[<EntryPoint>]
let main argv =
match printfn "Option inlined"; Some () with
| Some () -> ()
| None -> ()
let x = printfn "Option outside"; Some ()
match x with
| Some () -> ()
| None -> ()
match printfn "ValueOption inlined"; ValueSome () with
| ValueSome () -> ()
| ValueNone -> ()
let x = printfn "ValueOption outside"; ValueSome ()
match x with
| ValueSome () -> ()
| ValueNone -> ()
match printfn "Result inlined"; Ok () with
| Ok () -> ()
| Error () -> ()
let x = printfn "Result outside"; Ok ()
match x with
| Ok () -> ()
| Error () -> ()
match printfn "Custom value union inlined"; V with
| V -> ()
let x = printfn "Custom value union outside"; V
match x with
| V -> ()
match printfn "Custom struct union inlined"; S with
| S -> ()
let x = printfn "Custom struct union outside"; S
match x with
| S -> ()
match printfn "Custom struct union inlined with catch-all"; S with
| _ -> ()
match printfn "Custom struct record inlined"; { A = S } with
| { A = S } -> ()
printfn "Press Enter to exit..."
Console.ReadLine() |> ignore
0
Expected behavior
The message should only be printed once for each use of match.
Actual behavior

Known workarounds
Bind the expression to a named value and use that value in the match expression, like the example shows.
Related information
- Visual Studio version: 15.8.5
- Visual F# tools 10.2 for F# 4.5, 15.8.0.0, commit hash 92247b8
- Severity: Assumed high
Potentially critical issue: If the expression (e.g. a function call) inside a
match ... withreturns a struct union (e.g.ValueOption<_>,Result<_,_>or a custom struct union), the expression is evaluated twice, including any side effects.Repro steps
Repro solution:
Test.zipConsoleApp1.zipThe repro solution consists of a console app with the following code, showing various examples and aspects of this bug:
Expected behavior
The message should only be printed once for each use of
match.Actual behavior
Known workarounds
Bind the expression to a named value and use that value in the
matchexpression, like the example shows.Related information