I have some F# 4.0 source that compiles fine in Debug, but not in Release.
There are no conditional defines, no changes in the inferred types, and nothing else I can think of, that can explain this difference to me.
Did I really stumble on a compiler bug?
This is a snippet with the problematic code.
let oldItems = userDisplayItems |> Seq.toList
for newItem in newItems do
match List.tryFind (fun (itemOfOld: UserDisplay.UserDisplayItem) -> itemOfOld.Id = newItem.Id) oldItems with
| Some oldItem ->
The error message refers to the last use of "oldItems", before the "with" keyword at the end of the long line. The error message is:
Undefined value 'oldItems : UserDisplayItem list'
What!? oldItems is in plain sight a few lines above, and this compiles in Debug, so why not in Release? What does that error message actually mean?
UserDisplayItem is a simple class. newItems is a ResizeArray of UserDisplayItem
I looked into the build history, and it compiled fine in Release when UserDisplayItem was an F# immutable record, and not a class.
Visual Studio 2015, F# 4.0, Any CPU, Release, .NET 4.5.2 targeted.
UPDATE:
The following is a complete example. You can create an F# console application, and paste this into Program.fs. I expect it will compile in Debug, but not Release.
open System.Collections.ObjectModel
type User = { Id: int }
[<AllowNullLiteral>]
type UserDisplayItem(id: int) =
let mutable id = id
member x.Id with get() = id and set(v) = id <- v
let userDisplayItems = new ObservableCollection<UserDisplayItem>()
let refreshList () =
let newItems = userDisplayItems
let oldItems = userDisplayItems |> Seq.toList
for newItem in newItems do
match List.tryFind (fun (itemOfOld: UserDisplayItem) -> itemOfOld.Id = newItem.Id) oldItems with
| Some oldItem -> ()
| None -> ()
UPDATE 2 :
An even shorter sample.
type UserDisplayItem = { Id: int }
let refreshList () =
let newItems = new ResizeArray<UserDisplayItem>()
let oldItems = new ResizeArray<UserDisplayItem>() |> Seq.toList
for newItem in newItems do
match List.tryFind (fun (itemOfOld: UserDisplayItem) -> itemOfOld.Id = newItem.Id) oldItems with
| Some oldItem -> ()
| None -> ()
Seems to be compiler bug (maybe related to 1020).
Could reproduce it with your code and F# version 14.0.23413.0
Now installed current preview which is F# version 14.0.23618.0 and it works.
Until you have the fix for this issue (see DAXaholic's answer for final fix), you can use this workaround, as explained by dsyme here:
https://github.com/Microsoft/visualfsharp/issues/759#issuecomment-162243299
The fix applied to the last sample in the question. First add this.
// do something that doesn't get optimized away
let workaround() = null |> ignore
and then only add a call to the function workaround in the right place(s), which is right before any loop where you get this error.
let oldItems = new ResizeArray<UserDisplayItem>() |> Seq.toList
workaround()
for newItem in newItems do
match List.tryFind (fun (itemOfOld: UserDisplayItem) -> itemOfOld.Id = newItem.Id) oldItems with
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With