acton icon indicating copy to clipboard operation
acton copied to clipboard

Compilation error for Hashable extension

Open ddjoh opened this issue 3 years ago • 3 comments

Acton Version

0.14.2.20221201.12.18.21

Steps to Reproduce

class Key:
    @property
    x: int

    def __init__(self, x):
        self.x = x

extension Key(Eq):
    def __eq__(a, b) -> bool:
        return a.x == b.x

extension Key(Hashable):
    def __hash__(self):
        return hash(self.x)

actor main(env):
    var dct: dict[Key, int] = {}

Expected Behavior

Success!

Actual Behavior

Building project in /home/ddjoh/workspaces/act-test-1
  Compiling mod1.act for development
   Finished compilation in   0.111 s
Building executable out/dev/bin/mod1
ERROR: internal compiler error: compilation of generated C code of the root actor failed
NOTE: this is likely a bug in actonc, please report this at:
NOTE: https://github.com/actonlang/acton/issues/new?template=ice.yaml
NOTE: acton 0.14.2.20221201.12.18.21 compiled by ghc 8.10 on linux x86_64
NOTE: cc: 0.10.0
cc stdout:

cc stderr:
ld.lld: error: undefined symbol: mod1$$Hashable$Key$new
>>> referenced by mod1.c:155 (act-test-1/out/types/mod1.c:155)
>>>               mod1.o:(mod1$$main$__init__) in archive /home/ddjoh/workspaces/act-test-1/out/dev/lib/libActonProject.a

ddjoh avatar Dec 13 '22 13:12 ddjoh

Placing __eq__ under the Hashable extension seems to generate working code, e.g:

class Key:
    @property
    x: int

    def __init__(self, x):
        self.x = x

extension Key(Hashable):
    def __eq__(a, b) -> bool:
        return a.x == b.x
    def __hash__(self):
        return hash(self.x)

actor main(env):
    var dct: dict[Key, int] = {}

ddjoh avatar Dec 13 '22 15:12 ddjoh

@nordlander do you know how to fix this? Like if you know exactly what the problem is and how you think it should be fixed?

It seems to me that the problem is that in the CodeGen pass, the Hashable extension for Key is seen as a class and when it's not implementing eq (which it inherited from the Eq protocol) then it is considered an abstract class and won't have the constructor code generated.

I don't think there is such a thing as an abstract extension conceptually - either they implement all the methods or you get an error earlier on. We can also rely on the parent protocols being implemented, so we won't really have any abstract methods.

However, I'm not sure how to differentiate protocols from other classes in CodeGen - if we can? By name? feels ugly. What is even the point of having abstract classes propagated all the way to CodeGen, can't we filter them out earlier so that only concrete classes (including then some extensions) are passed to codegen?

plajjan avatar Jul 18 '25 14:07 plajjan

@plajjan See my comment in #2380

nordlander avatar Jul 19 '25 20:07 nordlander