happygilmore
happygilmore

Reputation: 3105

F# code works fine in REPL but gives stack overflow during compile

I would like to know if this is a bug or if I am doing something wrong. I am running F# in mono/linux, the following code crashes giving me a stack overflow without any stack trace.

let rec gcd a b =
    match b with
       | x when x = 0 -> a
       | _ -> gcd b (a%b)

let z = (gcd 12 3)

printfn "%A" z

this works fine when I run the same code in the REPL.

Interestingly enough this works fine

let rec gcd a b =
    match b with
       | x when x = 0 -> a
       | _ -> gcd b (a%b)

printfn "%A" (gcd 12 3)

EDIT:

Trying the --optimize solution doesn't help, interestingly I found that following John Palmer's advice and replacing x when x = 0 with just 0 worked, however when trying the same technique with int64, 0L again gives me the same stack overflow. I don't see how this is a tail optimization problem since 3 is a factor of 12 the stack depth is low. I am putting this down as a bug unless someone else can enlighten me what is happening here.

Upvotes: 2

Views: 79

Answers (1)

John Palmer
John Palmer

Reputation: 25516

In general, the fsi often is set up to use --optimize (definitely on windows from within Visual Studio, not sure about on mono).

As a result, the REPL will apply tail calls, but an unoptimized compiled app won't. You can probably fix this by compiling with fsharpc --optimize+ ...

also, change

|x when x = 0

to

|0

EDIT: I think this might actually be a compiler / mono bug - adding a printf anywhere gets rid of it.

Decompiled versions:

bug:

IL_0000:  ldarg.1 
IL_0001:  brtrue.s IL_0005
IL_0003:  ldarg.0 
IL_0004:  ret 
IL_0005:  ldarg.1 
IL_0006:  ldarg.0 
IL_0007:  ldarg.1 
IL_0008:  rem 
IL_0009:  starg.s 1
IL_000b:  starg.s 0
IL_000d:  br.s IL_0000

and good:

IL_0000:  ldarg.1 
IL_0001:  switch (
  IL_0014)
IL_000a:  ldarg.1 
IL_000b:  ldarg.0 
IL_000c:  ldarg.1 
IL_000d:  rem 
IL_000e:  starg.s 1
IL_0010:  starg.s 0
IL_0012:  br.s IL_0000

IL_0014:  ldarg.0 
IL_0015:  ret 

Nothing that seems weird to me.

I am running mono 3.2.8 and a reasonably modern F# compiler - I will test on latest git when I have time to recompile the compiler.

Upvotes: 3

Related Questions