2016-06-15 16 views
19

Ho una sorgente F # 4.0 che compila bene in Debug, ma non in Release.Errore del compilatore in F # 4?

Non ci sono definizioni condizionali, nessuna modifica nei tipi dedotti e nient'altro a cui riesco a pensare, che possa spiegare questa differenza a me.

Ho davvero inciampato in un bug del compilatore?

Questo è uno snippet con il codice problematico.

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

Il messaggio di errore si riferisce all'ultimo uso di "oldItems", prima che il "con" parola chiave, alla fine della lunga fila. Il messaggio di errore è:

valore indefinito 'oldItems: lista UserDisplayItem'

Cosa !? oldItems è in bella vista alcune righe sopra, e questo compila in Debug, quindi perché non in Release? Cosa significa in realtà quel messaggio di errore?

UserDisplayItem è una classe semplice. newItems è un ResizeArray di UserDisplayItem

Ho esaminato la cronologia di compilazione e ha compilato correttamente in Release quando UserDisplayItem era un record immutabile F # e non una classe.

Visual Studio 2015, F # 4.0, Qualsiasi CPU, versione, .NET 4.5.2 targetizzato.

UPDATE:

Quanto segue è un esempio completo. È possibile creare un'applicazione per console F # e incollarla in Program.fs. Mi aspetto che verrà compilato in Debug, ma non 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:

Un campione ancora più breve.

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

E riguardo 'match oldItems |> List.tryFind (fun itemOfOld -> itemOfOld.Id = newItem.Id) with'? – ildjarn

+0

Ancora lo stesso errore durante il piping, e ancora solo in Release, non in Debug. –

+6

Impossibile riprodurre dal codice e dai tipi fittizi/implementazione e versioni corrispondenti di VS, F #, impostazioni di compilazione e destinazione del framework. Il codice dato non funziona da solo; la fonte del problema potrebbe essere al di fuori di ciò che hai postato. Si prega di fornire una replica minima, completa di eventuali passi noti per ottenere l'errore. – Vandroiy

risposta

10

sembra essere compilatore bug (forse relativi a 1020).
È possibile riprodurlo con il proprio codice e F # versione 14.0.23413.0
Attualmente installato corrente preview che è F # versione 14.0.23618.0 e funziona.

+0

Mi hai battuto rispondendo di alcuni minuti, e penso che entrambi abbiamo alcune informazioni utili a questo proposito. Sembra che ci siano alcuni problemi correlati, probabilmente correlati a un'intera classe di errori. Grazie. –

+0

Yup - ti ha dato una risposta perché non ti ho fornito una soluzione alternativa (oltre all'utilizzo di un compilatore di anteprima :)) – DAXaholic

+1

Il controllo con il compilatore di anteprima ha confermato che è in arrivo una correzione, che mi ha salvato da ulteriori preoccupazioni su cosa fare dopo. Ora posso tornare al lavoro retribuito, quindi grazie ancora. –

9

Fino a quando si ha la correzione di questo problema (si veda la risposta di DAXaholic per correzione finale), è possibile utilizzare questa soluzione, come spiegato da dsyme qui:

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

La correzione applicata al l'ultimo campione in la domanda. Prima aggiungilo.

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

e quindi aggiungere solo una chiamata alla funzione soluzione nel posto giusto (s), che si trova proprio prima di ogni ciclo in cui si ottiene questo errore.

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