ponyc icon indicating copy to clipboard operation
ponyc copied to clipboard

Wrong reference capability for element of array literal in a recover block

Open chalcolith opened this issue 6 years ago • 1 comments

The following program

    class Foo
      var n: USize
      var bar: (Bar | None)
      
      new create() =>
        n = 0
        bar = None
      
      fun ref set_n(n': USize) =>
        n = n'
      
      fun ref set_bar(bar': Bar) =>
        bar = bar'
        
    class Bar
      let _children: ReadSeq[Foo box] val

      new create(children: ReadSeq[Foo box] val) =>
        _children = children

    class Baz
      let _child: Foo box
      
      new create(child: Foo box) =>
        _child = child


    actor Main
      new create(env: Env) =>
        let foo: Foo val = 
          recover
            let f: Foo ref = Foo
            f.set_n(3)
            let z = Baz(f)
            let b = Bar([f])
            f.set_bar(b)
            f
          end
        env.out.print(foo.n.string())

Produces the output

0.24.0 [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:36:22: array element not a subtype of specified array type
        let b = Bar([f])
                    ^
    Info:
    main.pony:19:32: array type: Foo box
      new create(children: ReadSeq[Foo box] val) =>
                                  ^
    main.pony:33:16: element type: Foo tag
            let f: Foo ref = Foo
                  ^
    main.pony:33:16: Foo tag is not a subtype of Foo box: tag is not a subcap of box
            let f: Foo ref = Foo
                  ^
Error:
main.pony:37:19: cannot infer type of b

        f.set_bar(b)
                  ^

I don't see why the variable f is being treated as a Foo tag in the array literal.

chalcolith avatar Jul 10 '18 20:07 chalcolith

The explicit recover block here is a red herring - this fails in the same way even if that is removed.

The array inference logic here is flawed: https://github.com/ponylang/ponyc/blob/46668e275032586af18f2495d5b99a36cf106951/src/libponyc/expr/array.c#L379-L385

Here, the right side is coming back as Array[Foo ref], while the antecedent is Array[Foo box]. Even though Foo ref is a subtype of Foo box, the same isn't true of Array[Foo ref] and Array[Foo box]. The logic needs to do something else here - it needs to recognize the subtype relationship for the element type, and then just use the antecedent type directly without trying to recover. That check should happen before this check I'm highlighting here, but it isn't.

I can't guarantee I'll find time for this soon, but I'll try. I'll assign myself to this ticket if I start working on it. Otherwise, it's fair game for someone else.

jemc avatar Jul 11 '18 19:07 jemc