Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

type_append: Assertion 0 failed #2867

Open
patternspandemic opened this issue Aug 24, 2018 · 7 comments
Open

type_append: Assertion 0 failed #2867

patternspandemic opened this issue Aug 24, 2018 · 7 comments

Comments

@patternspandemic
Copy link
Contributor

patternspandemic commented Aug 24, 2018

I have written code triggering a pony_assert(0) found in genname.c type_append:

...
Generating
 Reachability
src/libponyc/codegen/genname.c:63: type_append: Assertion `0` failed.
...

Backtrace

Attempting to compile the code triggering the error (detailed below) inside LLDB reveals the following backtrace (frame # 3 being where pony_assert fails):

(lldb) bt
* thread #1, name = 'ponyc', stop reason = signal SIGABRT
    frame #0: 0x00007ffff3680be0 libc.so.6`__GI_raise + 256
    frame #1: 0x00007ffff3681dc1 libc.so.6`__GI_abort + 321
    frame #2: 0x00000000004c4010 ponyc`ponyint_assert_fail(expr=<unavailable>, file=<unavailable>, line=<unavailable>, func=<unavailable>) at ponyassert.c:60
  * frame #3: 0x00000000004baac7 ponyc`type_append(buf=0x00007fffe9f4cdc0, type=0x00007fffe9567b00, first=<unavailable>) at genname.c:63
    frame #4: 0x00000000004ba8fa ponyc`types_append(buf=0x00007fffe9f4cdc0, elements=<unavailable>) at genname.c:77
    frame #5: 0x00000000004bac5f ponyc`genname_fun at genname.c:69
    frame #6: 0x00000000004bac4f ponyc`genname_fun(cap=TK_TAG, name="_muxed_sink", typeargs=0x00007fffe9571a80) at genname.c:174
    frame #7: 0x00000000004a4101 ponyc`add_rmethod(r=0x00007fffea1c9500, t=0x00007fffec78ed00, n=0x00007fffe9569c80, cap=TK_TAG, typeargs=0x00007fffe9571a80, opt=0x00007fffffffb140, internal=false) at reach.c:334
    frame #8: 0x00000000004a50ba ponyc`reachable_method(r=0x00007fffea1c9500, reify=<unavailable>, type=<unavailable>, name="_muxed_sink", typeargs=0x00007fffe9571a80, opt=0x00007fffffffb140) at reach.c:1327
    frame #9: 0x00000000004a53e1 ponyc`reachable_fun(r=0x00007fffea1c9500, reify=0x00007fffe9569bc0, ast=<unavailable>, opt=0x00007fffffffb140) at reach.c:1071
    frame #10: 0x00000000004a576e ponyc`reachable_expr at reach.c:1096
    frame #11: 0x00000000004a5718 ponyc`reachable_expr(r=0x00007fffea1c9500, reify=0x00007fffe9569bc0, ast=0x00007ffff11cdc40, opt=0x00007fffffffb140) at reach.c:1192
    frame #12: 0x00000000004a5528 ponyc`reachable_expr(r=0x00007fffea1c9500, reify=0x00007fffe9569bc0, ast=<unavailable>, opt=0x00007fffffffb140) at reach.c:1307
    frame #13: 0x00000000004a5da7 ponyc`reach at reach.c:1383
    frame #14: 0x00000000004a5d61 ponyc`reach(r=0x00007fffea1c9500, type=<unavailable>, name=<unavailable>, typeargs=<unavailable>, opt=0x00007fffffffb140) at reach.c:1413
    frame #15: 0x00000000004b4465 ponyc`genexe(c=0x00007fffffffac90, program=0x00007ffff31f9c80) at genexe.c:506
    frame #16: 0x0000000000483489 ponyc`codegen(program=0x00007ffff31f9c80, opt=0x00007fffffffb140) at codegen.c:875
    frame #17: 0x0000000000423a66 ponyc`compile_package(path=<unavailable>, opt=0x00007fffffffb140, print_program_ast=<unavailable>, print_package_ast=<unavailable>) at main.c:67
    frame #18: 0x000000000042356d ponyc`main(argc=<unavailable>, argv=0x00007fffffffb318) at main.c:111
    frame #19: 0x00007ffff366db8e libc.so.6`__libc_start_main + 238
    frame #20: 0x000000000042397a ponyc`_start at start.S:120
(lldb) frame variable *type->t
(token_t) *type->t = {
  id = TK_TYPEPARAMREF
  source = 0x00007ffff2855cc0
  line = 109
  pos = 61
  printed = 0x0000000000000000
   = {
     = (string = 0x0000000000000000, str_length = 0)
    real = 0
    integer = (low = 0, high = 0)
  }
  frozen = false
}

Possibly helpful, as you can see above, probing the frame variable type reveals ast_id(type) to be that of TK_TYPEPARAMREF.

Triggering Code

patternspandemic/pony-reactors@90685be

I could not duplicate the error in a simpler case, and so offer the original code to reproduce it. The commit as linked above is also tagged type_append. The above failed assertion can be reproduced by compiling the program found in examples/basic/.

As much as I understand it, the compiler does not like my use / combination of, or closure over partially applied generic methods as seen here. The method open basically packages up a partially applied behavior in a val object for latter use, by for example..

Another line, found here, is an example of when such a method will be called. In fact commenting out this line results in not triggering the assert in question, perhaps because the compiler determined the partially applied method could no longer be reached.

Please let me be of assistance if you have an questions about the provided source. I am sure my intentions are not easy to decipher when they are laid out in generics, partial application, subtyping, and various object literals. I will continue to attempt to find a simpler example reproducing the assert.

pony version:

0.24.4 [debug]
compiled with: llvm 3.9.1 -- gcc (GCC) 7.3.0
Defaults: pic=false ssl=openssl_0.9.0
  • Updated to reference tagged commit in triggering source.
@patternspandemic
Copy link
Contributor Author

I have been able to get around this failed assertion by replacing the partially applied behavior with a call to the behavior on a captured reference of the actor as seen here. The relevant bits:

...
//      let pa_muxed: {(C)} val = recover val this~_muxed_sink[C](channel_tag) end
      let self: Reactor[E] tag = this
      // Build the connector.
      let connector = Connector[C, E](
        where
          channel' = object val is Channel[C]
            let _channel_tag: ChannelTag = channel_tag
//            let _pa_muxed: {(C)} val = pa_muxed
            fun channel_tag(): ChannelTag => _channel_tag
            fun shl(ev: C) =>
//              _pa_muxed(consume ev)
              self.muxed_sink[C](_channel_tag, consume ev)
          end,
          events' = BuildEvents.emitter[C](),
          reactor_state' = reactor_state(),
          reservation' = reservation
      )
...

The two look equivalent to me, but I suppose the cases are handled differently or at different times by the compiler. Hopefully this can provide some insight.

A working examples/basic is also provided at patternspandemic/pony-reactors@305966e, which resolves a separate matching issue that may have something to do with #2584 (not sure).

@mfelsche
Copy link
Contributor

I am still wraping my head around this, trying to create a simplified example and understanding the issue. It seems the typeargs to some function are not completely reified, they still are a typeparamref to the typeparam C.

Here is the AST for the expression below:

let pa_muxed: {(C)} val = recover val this~_muxed_sink[C](channel_tag) end

where C should be a (ChannelReservation | None) and the type argument to the trait containing the fun with the call above is None. Dunno if this helps. @Praetonus does this ring a bell to you?

(class:scope
  (id $1$18)
  (typeparams (typeparam (id C) (nominal (id $0) (id Any) x #share x x) x))
  ref
  x
  (members
    (fvar
      (id channel_tag)
      (nominal (id $3) (id ChannelTag) x tag x x)
      x
      x
      [nominal (id $3) (id ChannelTag) x tag x x]
    )
    (fvar
      (id $1$17)
      (nominal (id $1) (id Main) x tag x x)
      x
      x
      [nominal (id $1) (id Main) x tag x x]
    )
    (fun:scope
      box
      (id apply)
      x
      (params
        (param

          (id event)
          (typeparamref (id C) #share x)
          x
          [typeparamref (id C) #share x]
        )
      )
      (nominal (id $0) (id None) x val x x)
      x
      (seq
        (call
          (beref
            (beref
              (fvarref
                (this
                  [->
                    thistype
                    (nominal
                      (id $1)
                      (id $1$18)
                      (typeargs (typeparamref (id C) #share x))
                      ref
                      x
                      x
                    )
                  ]
                )
                ((id $1$17) [nominal (id $1) (id Main) x tag x x])
                [nominal (id $1) (id Main) x tag x x]
              )
              (id _muxed_sink)
              [funtype
                tag
                (typeparams
                  (typeparam (id T) (nominal (id $0) (id Any) x #share x x) x)
                )
                (params
                  (param
                    (id channel_tag)
                    (nominal (id $0) (id Any) x tag x x)
                    x
                  )
                  (param (id event) (typeparamref (id T) #share x) x)
                )
                (nominal (id $0) (id None) x val x x)
              ]
            )
            (typeargs (typeparamref (id C) #share x))
            [funtype
              tag
              x
              (params
                (param (id channel_tag) (nominal (id $0) (id Any) x tag x x) x)
                (param (id event) (typeparamref (id C) #share x) x)
              )
              (nominal (id $0) (id None) x val x x)
            ]
          )
          (positionalargs
            (seq
              (fvarref
                (this
                  [->
                    thistype
                    (nominal
                      (id $1)
                      (id $1$18)
                      (typeargs (typeparamref (id C) #share x))
                      ref
                      x
                      x
                    )
                  ]
                )
                ((id channel_tag) [nominal (id $3) (id ChannelTag) x tag x x])
                [nominal (id $3) (id ChannelTag) x tag x x]
              )
              [nominal (id $3) (id ChannelTag) x tag x x]
            )
         (seq
              (consume
                x
                (paramref (id event) [typeparamref (id C) #share x])
                [typeparamref (id C) #share ^]
              )
              [typeparamref (id C) #share ^]
            )
          )
          x
          x
          [nominal (id $0) (id None) x val x x]
        )
        (call
          (newref
            (typeref x (id None) x [nominal (id $0) (id None) x val x x])
            (id create)
            [funtype val x x (nominal (id $0) (id None) x val ^ x)]
          )
          x
          x
          x
          [nominal (id $0) (id None) x val ^ x]
        )
        [nominal (id $0) (id None) x val ^ x]
      )
      x
    )
    (new:scope
      val
      (id create)
      x
      (params
        (param
          (id $1$19)
          (nominal (id $1) (id Main) x tag x x)
          x
          [nominal (id $1) (id Main) x tag x x]
        )
        (param
          (id $1$20)
          (nominal (id $3) (id ChannelTag) x tag x x)
          x
          [nominal (id $3) (id ChannelTag) x tag x x]
        )
      )
      (nominal
        (id $1)
        (id $1$18)
        (typeargs (typeparamref (id C) #share x))
        val
        ^
        x
      )

     x
      (seq
        (true [nominal (id $0) (id Bool) x val x x])
        (=
          (fvarref
            (this
              [nominal
                (id $1)
                (id $1$18)
                (typeargs (typeparamref (id C) #share x))
                ref
                x
                x
              ]
            )
            ((id $1$17) [nominal (id $1) (id Main) x tag x x])
            [nominal (id $1) (id Main) x tag x x]
          )
          (consume
            x
            (paramref (id $1$19) [nominal (id $1) (id Main) x tag x x])
            [nominal (id $1) (id Main) x tag ^ x]
          )
          [nominal (id $1) (id Main) x tag ^ x]
        )
        (=

    (fvarref
            (this
              [nominal
                (id $1)
                (id $1$18)
                (typeargs (typeparamref (id C) #share x))
                ref
                x
                x
              ]
            )
            ((id channel_tag) [nominal (id $3) (id ChannelTag) x tag x x])
            [nominal (id $3) (id ChannelTag) x tag x x]
          )
          (consume
            x
            (paramref (id $1$20) [nominal (id $3) (id ChannelTag) x tag x x])
            [nominal (id $3) (id ChannelTag) x tag ^ x]
          )
          [nominal (id $3) (id ChannelTag) x tag ^ x]
        )
        [nominal (id $3) (id ChannelTag) x tag ^ x]
      )
      x
    )
  )
  x
  x
)

@patternspandemic
Copy link
Contributor Author

and the type argument to the trait containing the fun with the call above is None.

This sounds right given open is called from Main, a Reactor[None], in the example program.

actor Main is Reactor[None]
...
    let conn = open[(ChannelReservation | None)]()
...

@patternspandemic
Copy link
Contributor Author

patternspandemic commented Sep 12, 2018

I just wanted to make part of the record a simpler example which was thought to be possibly connected (as discussed on IRC). The insight being that the compiler is reporting type names as the type parameter variables themselves, indicating that something's perhaps not being reified.

Here is the playground, and the error:

0.24.4 [release]
compiled with: llvm 3.9.1 -- cc (Ubuntu 5.4.0-6ubuntu1~16.04.10) 5.4.0 20160609
Defaults: pic=false ssl=openssl_0.9.0
Error:
main.pony:20:1: type does not implement its provides list
class _MappedEvents[T: Any #share, R: Any #share] is Events[R]
^
    Info:
    main.pony:11:18: Any #share is not a subtype of R #share: the type parameter has no lower bounds
      fun ref map[R: Any #share](
                     ^
    main.pony:12:8: parameter R #share is not a supertype of R #share
        f: {(T): R}) // A lambda which transforms T to R
           ^
    main.pony:12:8: {(T): R}[R #share, R #share] ref is not a subtype of {(T): R}[R #share, R #share] ref: method 'apply' has an incompatible signature
        f: {(T): R}) // A lambda which transforms T to R
           ^
    main.pony:11:3: parameter {(T): R}[R #share, R #share] ref is not a supertype of {(T): R}[R #share, R #share] ref
      fun ref map[R: Any #share](
      ^
    main.pony:11:3: _MappedEvents[T #share, R #share] ref is not a subtype of Events[R #share] ref: method 'map' has an incompatible signature
      fun ref map[R: Any #share](
      ^

Edit: This comment since broken out into a separate issue: #2881

@jemc
Copy link
Member

jemc commented Sep 12, 2018

Chatted about this on the sync call.

I think @mfelsche is onto something when it comes to Main being treated specially. In genexe, we call reach for Main.create and Env.create, but we maybe need to call reach_type on the trait if Main has any traits attached to it.

@mfelsche
Copy link
Contributor

Unfortunately i think this issue is not related to special treatment of the Main actor. I rewrote the example to be implemented on another actor in the same way and i was able to reproduce the same assertion as mentioned above.

@patternspandemic
Copy link
Contributor Author

patternspandemic commented Sep 13, 2018

Unfortunately i think this issue is not related to special treatment of the Main actor.

I was about to mention the same after listening to the sync call. Do you still think the related example is connected in any way? If not I suppose a new issue is in order. For what it's worth, I've worked around the assert presented in this issue, but cannot get around the above problem.

Both examples involve object literals and generics. I'm thinking the issue still lies somewhere therein.

I am going to have another go at attempting a simpler repro soon.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants