tact-lang / tact

Tact compiler main repository
https://tact-lang.org
MIT License
275 stars 56 forks source link

Recursive type definition #347

Open 0kenx opened 1 month ago

0kenx commented 1 month ago

Compilation error when types are defined recursively:

struct A {
   a: Int;
   b: A;
}

or

message A {
   a: Int;
   b: A;
}

gives error

⏳ Compiling...   > 👀 Enabling debug
Tact compilation failed
RangeError: Maximum call stack size exceeded

To circumvent this limitation, I currently define the struct as:

message A {
   a: Int;
   b: Cell;
}

and translate the implementation of generated FunC $A$_load(slice sc_0) into Tact and load b using this function. Now after compilation I have 2 identical FunC functions: $Slice$_fun_load_a(slice $self) and $A$_load(slice sc_0). Not sure whether this is optimized away in fift compilation or not.

0kenx commented 1 month ago

Actually, Tact doesn't by default put nested A in a Cell, it puts it in a Slice instead.

So the question becomes, a) is there a way to call the generated FunC function fun $A$_load(s: Slice): A directly in Tact code? b) is there a way to force some data fields to go in their own Cells?

0kenx commented 2 weeks ago

Following up on this, I suggest adding a Ref<struct | message> type:

struct A {
    a: Int;
}

struct B {
    x: A; // stores A as Slice
    y: Ref<A>; // stores A as Cell in a ref