Skip to content

Incorrect Michelson code generated from LIGO

Compiling this (seemingly type-correct) CameLIGO code results on an incorrect Michelson code:

let rec ref_join
  (params: int * (int -> int -> int))
  : int * int =
  let left = 1 in
  ref_join
    ( 1
    , (fun (mem: int) (new_: int) ->
        if left > 0 then 0 else left+1)
    )

let main (ign: unit * unit): operation list * unit =
  let ign = ref_join (1, (fun (m: int) (r: int) -> 0)) in
  ([] : operation list), ()

(I extracted this snippet from a longer code, hence it doesn't make any sense as-is).

Output:

Error(s) occurred while type checking the contract:
Ill typed contract:
  01: { parameter unit ;
  02:   storage unit ;
  03:   code { DROP
  04:          /* [] */ ;
  05:          LAMBDA
  06:            int
  07:            (lambda int int)
  08:            { /* [ @arg int ] */
  09:              DROP
  10:              /* [] */ ;
  11:              LAMBDA
  12:                int
  13:                int
  14:                { /* [ @arg int ] */ DROP /* [] */ ; PUSH int 0 /* [ int ] */ }
  15:              /* [ lambda int int ] */ }
  16:          /* [ lambda int (lambda int int) ] */ ;
  17:          PUSH int 1
  18:          /* [ int : lambda int (lambda int int) ] */ ;
  19:          PAIR
  20:          /* [ pair int (lambda int (lambda int int)) ] */ ;
  21:          LEFT (pair int int)
  22:          /* [ or (pair int (lambda int (lambda int int))) (pair int int) ] */ ;
  23:          LOOP_LEFT
  24:            { DROP
  25:              /* [] */ ;
  26:              PUSH int 1
  27:              /* [ int ] */ ;
  28:              LAMBDA
  29:                (pair (pair int int) int)
  30:                (lambda int int)
  31:                { CAR
  32:                  /* [ pair int int ] */ ;
  33:                  LAMBDA
  34:                    (pair (pair int int) int)
  35:                    int
  36:                    { CAR
  37:                      /* [ pair int int ] */ ;
  38:                      PUSH int 0
  39:                      /* [ int : pair int int ] */ ;
  40:                      SWAP
  41:                      /* [ pair int int : int ] */ ;
  42:                      DUP
  43:                      /* [ pair int int : pair int int : int ] */ ;
  44:                      DUG 2
  45:                      /* [ pair int int : int : pair int int ] */ ;
  46:                      COMPARE ;
  47:                      GT ;
  48:                      IF { DROP ; PUSH int 0 } { PUSH int 1 ; ADD } } ;
  49:                  SWAP ;
  50:                  APPLY } ;
  51:              SWAP ;
  52:              APPLY ;
  53:              PUSH int 1 ;
  54:              PAIR ;
  55:              LEFT (pair int int) } ;
  56:          DROP ;
  57:          PUSH unit Unit ;
  58:          NIL operation ;
  59:          PAIR } }
At line 46 characters 21 to 28, wrong stack type for instruction COMPARE:
  [ pair int int : int : ... ].
Bad stack item 1.
Type pair int int is not compatible with type int.

My uninformed guess is that something is going wrong when capturing a value from outer scope inside the lambda. However, I couldn't pinpoint the exact reason, since on this example seemingly irrelevant changes can also make the error disappear. Also, the issue is not with COMPARE instruction, pretty much anything you do inside the callback using left from outer scope won't type check.

If this is indeed an error, I would appreciate if someone can point out to me the exact reason, so I can try to find a workaround on my code.


I can reproduce the issue both with LIGO 5.0 and the current tip of the dev branch (7bbd81f8).