Ошибка компилятора в F # 4?

У меня есть источник F # 4.0, который отлично компилируется в Debug, но не в Release.

Нет никаких условных определений, изменений в выводимых типах и ничего более, о чем я могу думать, которые могут объяснить эту разницу мне.

Я действительно наткнулся на ошибку компилятора?

Это фрагмент с проблемным кодом.

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 ->

Сообщение об ошибке относится к последнему использованию "oldItems" перед ключевым словом "with" в конце длинной строки. Сообщение об ошибке:

Undefined значение 'oldItems: список UserDisplayItem'

Что!? oldItems находится на виду несколько строк выше, и это компилируется в Debug, так почему бы не в Release? Что означает это сообщение об ошибке?

UserDisplayItem - простой класс. newItems - это ResizeArray of UserDisplayItem

Я просмотрел историю сборки и отлично компилировался в Release, когда UserDisplayItem был неизменяемой записью F #, а не классом.

Visual Studio 2015, F # 4.0, любой CPU, Release,.NET 4.5.2.

UPDATE:

Ниже приведен полный пример. Вы можете создать консольное приложение F # и вставить его в Program.fs. Я ожидаю, что он будет компилироваться в Debug, но не 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 -> ()

ОБНОВЛЕНИЕ 2:

Еще более короткий образец.

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 -> ()

Ответы

Ответ 1

Кажется, это ошибка компилятора (возможно, связанная с 1020).
Может воспроизвести его с кодом и F # версии 14.0.23413.0
Теперь установлен текущий preview, который является F # версии 14.0.23618.0, и он работает.

Ответ 2

Пока у вас не будет исправления этой проблемы (см. DAXaholic ответ для окончательного исправления), вы можете использовать это обходное решение, как объясняется здесь dsyme:

https://github.com/Microsoft/visualfsharp/issues/759#issuecomment-162243299

Исправление применяется к последнему образцу в вопросе. Сначала добавьте это.

// do something that doesn't get optimized away
let workaround() = null |> ignore  

а затем добавьте только вызов обходного пути функции в нужном месте (точках), которое находится прямо перед любым циклом, где вы получаете эту ошибку.

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