ponylang / ponyc

Pony is an open-source, actor-model, capabilities-secure, high performance programming language
http://www.ponylang.io
BSD 2-Clause "Simplified" License
5.71k stars 415 forks source link

twin bugs when calling itertools Iter.fold cause compiler to not terminate #3344

Open erdman opened 5 years ago

erdman commented 5 years ago
use "collections"
use "itertools"

primitive Combinatorics
  fun choose(n: USize, r':USize): USize =>
    let r = r'.min(n - r')
// this code fix compiles and executes as expected
   // let numer = Iter[USize](Range(n, n - r, -1)).fold[USize](1, {(acc, x) => acc * x})

// broken code with two bugs (no Fold type, fold arguments reversed) ... compiler does not terminate?
    let numer = Iter[USize](Range(n, n - r, -1)).fold({(acc, x) => acc * x}, 1)
    let denom = Iter[USize](Range(1, r + 1)).fold[USize](1, {(acc, x) => acc * x})
    numer / denom

actor Main
  new create (env: Env) =>
    env.out.print(Combinatorics.choose(13, 5).string())

Fixing either bug alone allows the compiler to report the remaining bug. It's the two together that seems to be problematic.

$ ponyc --version
0.32.0 [release]
compiled with: llvm 3.9.1 -- cc (Ubuntu 7.3.0-16ubuntu3) 7.3.0
Defaults: pic=true
mfelsche commented 5 years ago

Thanks for reporting!

The compiler on my end runs into a segfault after going into an infinite loop:

frame #65001: 0x00005555555f8b2a ponyc`find_possible_fun_defs(opt=0x00007fffffffd320, ast=0x00007ffff0b111c0, fun_defs=0x00007fffffffc9e8, obj_caps=0x00007fffffffc9f0) at lambda.c:189
    frame #65002: 0x00005555555f8b2a ponyc`find_possible_fun_defs(opt=0x00007fffffffd320, ast=0x00007ffff0b111c0, fun_defs=0x00007fffffffc9e8, obj_caps=0x00007fffffffc9f0) at lambda.c:189
    frame #65003: 0x00005555555f8b2a ponyc`find_possible_fun_defs(opt=0x00007fffffffd320, ast=0x00007ffff0b111c0, fun_defs=0x00007fffffffc9e8, obj_caps=0x00007fffffffc9f0) at lambda.c:189
    frame #65004: 0x00005555555f8b2a ponyc`find_possible_fun_defs(opt=0x00007fffffffd320, ast=0x00007ffff0b111c0, fun_defs=0x00007fffffffc9e8, obj_caps=0x00007fffffffc9f0) at lambda.c:189
    frame #65005: 0x00005555555f8b2a ponyc`find_possible_fun_defs(opt=0x00007fffffffd320, ast=0x00007ffff0b111c0, fun_defs=0x00007fffffffc9e8, obj_caps=0x00007fffffffc9f0) at lambda.c:189
    frame #65006: 0x00005555555f8b2a ponyc`find_possible_fun_defs(opt=0x00007fffffffd320, ast=0x00007ffff0b111c0, fun_defs=0x00007fffffffc9e8, obj_caps=0x00007fffffffc9f0) at lambda.c:189
    frame #65007: 0x00005555555f8b2a ponyc`find_possible_fun_defs(opt=0x00007fffffffd320, ast=0x00007ffff0b111c0, fun_defs=0x00007fffffffc9e8, obj_caps=0x00007fffffffc9f0) at lambda.c:189
    frame #65008: 0x00005555555f8b2a ponyc`find_possible_fun_defs(opt=0x00007fffffffd320, ast=0x00007ffff0b111c0, fun_defs=0x00007fffffffc9e8, obj_caps=0x00007fffffffc9f0) at lambda.c:189
    frame #65009: 0x00005555555f8b2a ponyc`find_possible_fun_defs(opt=0x00007fffffffd320, ast=0x00007ffff0b111c0, fun_defs=0x00007fffffffc9e8, obj_caps=0x00007fffffffc9f0) at lambda.c:189
    frame #65010: 0x00005555555f8b2a ponyc`find_possible_fun_defs(opt=0x00007fffffffd320, ast=0x00007ffff0b111c0, fun_defs=0x00007fffffffc9e8, obj_caps=0x00007fffffffc9f0) at lambda.c:189
    frame #65011: 0x00005555555f8b2a ponyc`find_possible_fun_defs(opt=0x00007fffffffd320, ast=0x00007ffff0b111c0, fun_defs=0x00007fffffffc9e8, obj_caps=0x00007fffffffc9f0) at lambda.c:189

This is during lambda type inference. Will report back with more detailed findings.

mfelsche commented 5 years ago

Here is a minimal sample to reproduce the problem:

actor Main
  new create (env: Env) =>     
    x({(s, t) => s})

fun x[T](t: T) =>
  None

The infinite loop is entered when the type of the parameter, for which we provide a lambda without type annotations, is a type parameter that does is not provided. In this case it seems to reference itself.