starkware-libs/cairo-lang

Compilation Bug: itertools: .zip_eq() reached end of one iterator before the other

Th0rgal opened this issue · 2 comments

Hello,

Summary:

I found a cairo code which appears to be valid but causes a compiler crash.

Env:

scarb 2.6.4 (c4c7c0bac 2024-03-19)
cairo: 2.6.3 (https://crates.io/crates/cairo-lang-compiler/2.6.3)
sierra: 1.5.0

Context:

I am building a short but quite logic intense Starknet contract allowing abstract interactions between calls. Instead of just being able to chain calls like in a normal multicall, you can take the output a previous call and use it as the output of a future call. I added some conditional executions feature (like skipping a call given the result of a previous call) and I am now trying to add a kind of "trycatch" feature (if call A fails, perform B, otherwise perform C, then perform D).

My code looks like this:
Check whole code here: https://github.com/starknet-id/composable_multicall/blob/62bf15f3bf48a7cc8e7d82309362628baa181e9b/src/contract.cairo#L141-L150

    fn execute_multicall(
        mut calls: Span<DynamicCall>
    ) -> Array<Result<Span<felt252>, Array<felt252>>> {
        let mut results: Array<Result<Span<felt252>, Array<felt252>>> = ArrayTrait::new();
        let mut idx = 0;
        loop {
            match calls.pop_front() {
                Option::Some(call) => {
                    match call.execution {
                        Execution::Static => {},
                        // here I skipped irrelevant executions for this bug report
                        Execution::Catch(call_id) => {
                            if results.at(*call_id).is_err() {
                                continue;
                            }
                        },
                        Execution::Then(call_id) => {
                            if results.at(*call_id).is_ok() {
                                continue;
                            }
                        },
                    };
                    let call_result = call_contract_syscall(
                        build_input(@results, call.to).try_into().unwrap(),
                        build_input(@results, call.selector),
                        build_inputs(@results, call.calldata.span()).span()
                    );
                    results.append(call_result);
                    idx = idx + 1;
                },
                Option::None(_) => { break; },
            };
        };
        results
    }
}

For a reason I don't understand, the specific lines:

                            if results.at(*call_id).is_err() {
                                continue;
                            }

And:

                            if results.at(*call_id).is_ok() {
                                continue;
                            }

Cause this error when compiling with scarb:

thread 'main' panicked at /Users/runner/.cargo/registry/src/index.crates.io-6f17d22bba15001f/itertools-0.11.0/src/zip_eq_impl.rs:48:13:
itertools: .zip_eq() reached end of one iterator before the other
stack backtrace:
   0:        0x103bbc7c4 - <std::sys_common::backtrace::_print::DisplayBacktrace as core::fmt::Display>::fmt::hb478ebbfb46e27ce
   1:        0x103448b1c - core::fmt::write::he4d5fa2daff1f531
   2:        0x103b9100c - std::io::Write::write_fmt::hc5a47a68eba63d9f
   3:        0x103bbf900 - std::sys_common::backtrace::print::h79bd952cc5812e7a
   4:        0x103bbf0d8 - std::panicking::default_hook::{{closure}}::h82301f6222887737
   5:        0x103bc015c - std::panicking::rust_panic_with_hook::h1e70c5d905e30e9d
   6:        0x1032476a4 - std::panicking::begin_panic::{{closure}}::h6387bab3c3c7976c
   7:        0x103247670 - std::sys_common::backtrace::__rust_end_short_backtrace::h1c77d9eda2282a64
   8:        0x103d19d88 - std::panicking::begin_panic::hfcfbfac8dda19335
   9:        0x103253ff0 - cairo_lang_sierra_generator::local_variables::FindLocalsContext::analyze_branch::h131fed1660be8046
  10:        0x103253c38 - cairo_lang_sierra_generator::local_variables::FindLocalsContext::analyze_call::hf071bbd16d6df1f1
  11:        0x103242718 - cairo_lang_lowering::borrow_check::analysis::BackAnalysis<TAnalyzer>::get_root_info::h7162e9c7b8a27f87
  12:        0x1031fff8c - cairo_lang_sierra_generator::function_generator::priv_function_with_body_sierra_data::h6dbf744a22c42758
  13:        0x1031d5ad8 - salsa::derived::slot::Slot<Q,MP>::read_upgrade::h74fef216b008a522
  14:        0x10322dd00 - <DB as cairo_lang_sierra_generator::db::SierraGenGroup>::priv_function_with_body_sierra_data::__shim::h3e7070a119d5a80d
  15:        0x1031cc868 - salsa::derived::slot::Slot<Q,MP>::read_upgrade::h43fd41e2c3340133
  16:        0x10322ef10 - <DB as cairo_lang_sierra_generator::db::SierraGenGroup>::function_with_body_sierra::__shim::hd791a39340db1b81
  17:        0x1032191dc - cairo_lang_sierra_generator::program_generator::get_sierra_program_for_functions::had22e99b86b32514
  18:        0x1031e1d10 - salsa::derived::slot::Slot<Q,MP>::read_upgrade::h9debe19662d40d50
  19:        0x1032313c8 - <DB as cairo_lang_sierra_generator::db::SierraGenGroup>::get_sierra_program_for_functions::__shim::h025fbb67f3875f2e
  20:        0x1033fdf80 - cairo_lang_test_plugin::compile_test_prepared_db::h0b0dd204866b6857
  21:        0x103af6024 - <scarb::compiler::compilers::test::TestCompiler as scarb::compiler::Compiler>::compile::h21dc7d741a870ac2
  22:        0x103954994 - scarb::ops::compile::compile::h1d74fe7748323707
  23:        0x103b5d9fc - scarb::commands::run::hdaeb29cb348b9ce6
  24:        0x103b23480 - scarb::main::hdb0c7b53413747fb
  25:        0x103b667d0 - std::sys_common::backtrace::__rust_begin_short_backtrace::h06db732967bca231
  26:        0x103b1fd5c - _main
Error: `scarb metadata` exited with error

Stack backtrace:
   0: std::backtrace::Backtrace::capture
   1: anyhow::error::<impl core::convert::From<E> for anyhow::Error>::from
   2: scarb_cairo_test::main
   3: std::sys_common::backtrace::__rust_begin_short_backtrace
   4: _main

To reproduce:

Clone https://github.com/starknet-id/composable_multicall/
Checkout commit 62bf15f3bf48a7cc8e7d82309362628baa181e9b (it's feat: add catch & then feature on branch feat/try_catch)

Note:
It appears that reordering the clauses in the match (moving Catch & Then on top of Except) fixes the bug.