ponyc icon indicating copy to clipboard operation
ponyc copied to clipboard

Compiler segmentation fault on complex Map union types

Open EpicEric opened this issue 6 years ago • 6 comments

This code causes a segmentation fault during compilation on latest release:

use "collections"

actor Main
  let map: Map[String, (F32 | Map[U32, F32])] = map.create()
  new create(env: Env) => None
Building builtin -> /usr/local/Cellar/ponyc/0.25.0/packages/builtin
Building . -> /Users/Eric/tmp
Building collections -> /usr/local/Cellar/ponyc/0.25.0/packages/collections
Building ponytest -> /usr/local/Cellar/ponyc/0.25.0/packages/ponytest
Building time -> /usr/local/Cellar/ponyc/0.25.0/packages/time
[1]    3335 segmentation fault  ponyc
$ ponyc --version
0.25.0 [release]
compiled with: llvm 3.9.1 -- Apple LLVM version 10.0.0 (clang-1000.11.45.2)
Defaults: pic=false ssl=openssl_0.9.0

EpicEric avatar Dec 17 '18 08:12 EpicEric

This seems to be a more general issue with type parameters. Here's a more minimal example:

actor Main
  let a: Array[(Array[I8] | I8)]

  new create(env: Env) =>
    a = []

Theodus avatar Dec 17 '18 16:12 Theodus

This seems to be resulting in infinite recursion of this sequence of calls:

exact_nominal( Array[I8 val] ref, Array[(Array[I8 val] ref | I8 val)] ref )
is_eq_typeargs( Array[I8 val] ref, Array[(Array[I8 val] ref | I8 val)] ref )
is_eqtype( I8 val, (Array[I8 val] ref | I8 val) )
is_x_sub_x( I8 val, (Array[I8 val] ref | I8 val) )
is_nominal_sub_x( I8 val, (Array[I8 val] ref | I8 val) )
is_x_sub_x( I8 val, Array[I8 val] ref )
is_nominal_sub_x( I8 val, Array[I8 val] ref )
is_nominal_sub_nominal( I8 val, Array[I8 val] ref )
push_assume( I8 val, Array[I8 val] ref )
check_assume( I8 val, Array[I8 val] ref )

exact_nominal( I8 val, Array[(Array[I8 val] ref | I8 val)] ref )
is_nominal_sub_entity( I8 val, Array[I8 val] ref )
is_x_sub_x( I8 val, I8 val )
is_nominal_sub_x( I8 val, I8 val )
is_nominal_sub_nominal( I8 val, I8 val )
push_assume( I8 val, I8 val )
check_assume( I8 val, I8 val )

exact_nominal( I8 val, Array[(Array[I8 val] ref | I8 val)] ref )
is_nominal_sub_entity( I8 val, I8 val )
is_eq_typeargs( I8 val, I8 val )
is_x_sub_x( (Array[I8 val] ref | I8 val), I8 val )
is_x_sub_x( Array[I8 val] ref, I8 val )
is_nominal_sub_x( Array[I8 val] ref, I8 val )
is_nominal_sub_nominal( Array[I8 val] ref, I8 val )
push_assume( Array[I8 val] ref, I8 val )
check_assume( Array[I8 val] ref, I8 val )

Theodus avatar Dec 17 '18 20:12 Theodus

Here's a backtrace (Using ReadSeq instead of Array)

Theodus avatar Dec 18 '18 17:12 Theodus

This one's using array, like the example: https://gist.github.com/Theodus/a29405cc7f619494140535c5eea1adf0

Theodus avatar Dec 18 '18 17:12 Theodus

I've isolated the frames that repeat (middle chunk, repeats at frame 12), with arguments:

(169) 0: is_subtype( I8 val, (Array[I8 val] ref | I8 val) )

1: is_eq_typeargs( Array[I8 val] ref, Array[(Array[I8 val] ref | I8 val)] ref )
2: exact_nominal( Array[I8 val] ref, Array[(Array[I8 val] ref | I8 val)] ref )
3: check_assume( Array[I8 val] ref, I8 val )
4: push_assume( Array[I8 val] ref, I8 val )
5: is_nominal_sub_nominal( Array[I8 val] ref, I8 val )
6: is_nominal_sub_x( Array[I8 val] ref, I8 val )
7: is_x_sub_x( Array[I8 val] ref, I8 val )
8: is_union_sub_x( (Array[I8 val] ref | I8 val), I8 val )
9: is_x_sub_x( (Array[I8 val] ref | I8 val), I8 val )
10: is_subtype( (Array[I8 val] ref | I8 val), I8 val )
11: is_eqtype( I8 val, (Array[I8 val] ref | I8 val) )

12: is_eq_typeargs( Array[I8 val] ref, Array[(Array[I8 val] ref | I8 val)] ref )

Theodus avatar Dec 18 '18 19:12 Theodus

The only assumption in subtype_assume is

Array[(Array[I8 val] ref | I8 val)] ref <: Array[(Array[I8 val] ref | I8 val)] ref

whenever check_assume is called. That list doesn't seem to grow.

Theodus avatar Dec 18 '18 19:12 Theodus