tact-lang / tact

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

Minimal integer `-(2**256)` makes FunC compilation fail #339

Closed anton-trunov closed 3 months ago

anton-trunov commented 4 months ago

The following snippet

contract Test {

    get fun minInt(): Int {
        // -(2**256)
        return -115792089237316195423570985008687907853269984665640564039457584007913129639936;
    }
}

produces the following FunC compilation error:

Func compilation error: /dist/tact_Test.code.fc:20:23: error: invalid integer constant `115792089237316195423570985008687907853269984665640564039457584007913129639936`
return ($self, (- 115792089237316195423570985008687907853269984665640564039457584007913129639936))

Reported by @novusnota.

novusnota commented 4 months ago

Additional context: https://github.com/tact-lang/tact-docs/pull/206#discussion_r1604070222

This works ($-2^{256} + 1$):

dump(
  -(pow2(255) - 1 + pow2(255))  // -(2**256 - 1)
);

This throws an exit code 4, while it should've fit ($-2^{256}$):

dump(
  -(pow2(255) - 1 + pow2(255)) // -(2**256 - 1) - 1
  - 1
);

Wolfram Alpha link

Gusarich commented 4 months ago

in both cases (https://github.com/tact-lang/tact/issues/339#issue-2302203847 and https://github.com/tact-lang/tact/issues/339#issuecomment-2117116631) you compute positive number first and then negate it via - operator.

integers in TVM are signed 257-bit, which are numbers in range $-2^{256}$; $2^{256}-1$, so $2^{256}$ doesn't fit.

I guess we have to make some change in Tact's way of handling integer constants in order to fix the problem.

novusnota commented 4 months ago

you compute positive number first and then negate it via - operator.

Hmm, I definitely compute $2^{256} - 1$ first, such that it fits, then negate it — and the first example works. But the second unexpectedly fails.

I guess we have to make some change in Tact's way of handling integer constants in order to fix the problem.

May be the case indeed

anton-trunov commented 4 months ago

-115792089237316195423570985008687907853269984665640564039457584007913129639936 is an integer literal (there is no negation per se) in Tact and it should be treated as such in FunC as well

Gusarich commented 4 months ago

interestingly, defining integer constants with these values works (for all of the snippets above), but trying to pass the value without an intermediate constant variable produces an error.

here's the result (in the first case integer literal is being generated correctly and in the second case incorrectly)

(tuple, int) $ConstantTester$_fun_something19(tuple $self) impure inline_ref {
    var ($self) = $self;
    return ($self, -115792089237316195423570985008687907853269984665640564039457584007913129639936);
}

(tuple, int) $ConstantTester$_fun_minInt1(tuple $self) impure inline_ref {
    var ($self) = $self;
    return ($self, (- 115792089237316195423570985008687907853269984665640564039457584007913129639936));
}