tact-lang / tact

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

Missing typechecking rules for augmented assignments #353

Closed byakuren-hijiri closed 3 months ago

byakuren-hijiri commented 4 months ago

Augmented assignments could be used with the following operations: "+" | "-" | "*" | "/" | "%".

It seems reasonable that these operations should be applied to numeric types, but this is not always the case.

Consider their behavior on different types:

  1. Bool
    get fun test_bool(): Bool {
        let a: Bool = false;
        a %= true;
        return a;
    }

Generates the following FunC code:

(tuple, int) $SampleTactContract$_fun_test_bool(tuple $self) impure inline_ref {
    var ($self) = $self;
    int $a = false;
    $a = $a % true;
    return ($self, $a);
}

It seems correct from the func perspective, so it passes the compilation. But the question is what the user is expected to get?

  1. String and Address
    get fun test_string(): String {
        let a: String = "foo";
        a %= "bar";
        return a;
    }

The func compilation fails:

💼 Compiling project sample...
   > SampleTactContract: tact compiler
   > SampleTactContract: func compiler
Func compilation error: output/sample_SampleTactContract.code.fc:30:20: error: cannot apply function _%_ : (int, int) -> int to arguments of type (slice, slice): cannot unify type slice with int
      $a1 = $a1 % $a2;
💥 Compilation failed. Skipping packaging
  1. More complex types The FunC compilation fails, as we are trying to apply an arithmetic operation to a non-numeric type.

Therefore, it is suggested to restrict these augmented assignment operations for all non-numeric types. If we are going to add boolean operations later, we should consider this in the typechecking as well.