nim-lang / Nim

Nim is a statically typed compiled systems programming language. It combines successful concepts from mature languages like Python, Ada and Modula. Its design focuses on efficiency, expressiveness, and elegance (in that order of priority).
https://nim-lang.org
Other
16.52k stars 1.47k forks source link

some mutually recursive type definitions put compiler in infinite loop #8938

Open skilchen opened 6 years ago

skilchen commented 6 years ago

The compilation of this contrived example will never end: It doesn't matter, what follows the type section. The compiler will not see it.

type 
  A = proc(acc, x: int, y: B): int
  B = proc(acc, x: int, y: A): int

proc fact(n: int): int =
  proc g(acc, a: int, b: proc(acc, a: int, b: A): int): A =
    if a == 0:
      acc
    else:
      b(a * acc, a - 1, b)
  g(1, n, g)

I know, that this is silly Nim code, but nevertheless the compiler should not loop forever.

If you like silly contrivances, here is another one. This one only works if you compile using -d:makemecompile:

import typeinfo
import strutils

type Func = proc(acc: float, x: int, b: Any): float {.nimcall.}

proc fact(n: int): float =
  var g = proc(acc: float, a: int, b: Any): float {.nimcall.} =
    if a == 0:
      acc
    else:
      if kind(b) == akProc:
        var b1 = cast[Func](getPointer(b))
        b1(a.float * acc, a - 1, b)
      else:
        when defined(makemecompile):
          echo kind(b)
        1.0
  g(1.0, n, toAny(g))

echo formatFloat(fact(170), ffDecimal, 0)

The else branch where the echo kind(b) is called, will never be executed. But without this echo kind(b), Nim will generate uncompileable C code...

mratsim commented 6 years ago

Duplicate of #8432 (Closure + Generics leads to VM stack overflow)?

LemonBoy commented 6 years ago

Duplicate of #8432 (Closure + Generics leads to VM stack overflow)?

Nope, just a simple case of undetected co-recursion during the parameter lifting phase: the compiler tries to lift B from A and then A from B and so on.

disruptek commented 5 years ago

Here's a fun one I managed to generate. Yeah, I know it's bogus and all, but it seems like it might make a good test case.

type
  string = string
  pigs = object
    horses: string