cairo-lang-lowering 2.21.0

Cairo lowering phase.
Documentation
//! > Test nopanic function cycle.

//! > test_runner_name
test_function_lowering(expect_diagnostics: true)

//! > cairo_code
#[target_function]
fn foo(x: felt252) nopanic {
    foo(x);
}

//! > semantic_diagnostics

//! > lowering_diagnostics
error[E3008]: Call cycle of `nopanic` functions is not allowed.
 --> lib.cairo:1:1-4:1
  #[target_function]
 _^
| ...
| }
|_^

//! > lowering_flat
<Failed lowering function - run with RUST_LOG=warn (or less) to see diagnostics>

//! > ==========================================================================

//! > Test explicit gas handling.

//! > test_runner_name
test_function_lowering(expect_diagnostics: false)

//! > cairo_code
#[target_function]
fn foo(x: felt252) {
    match core::gas::withdraw_gas() {
        Some(_) => foo(x),
        None => {},
    }
}

//! > semantic_diagnostics

//! > lowering_diagnostics

//! > lowering_flat
Parameters: v0: core::RangeCheck, v1: core::gas::GasBuiltin, v2: core::felt252
blk0 (root):
Statements:
End:
  Match(match core::gas::withdraw_gas(v0, v1) {
    Option::Some(v3, v4) => blk1,
    Option::None(v5, v6) => blk2,
  })

blk1:
Statements:
  (v7: core::gas::GasBuiltin) <- core::gas::redeposit_gas(v4)
  (v8: core::RangeCheck, v9: core::gas::GasBuiltin) <- test::foo(v3, v7, v2)
End:
  Return(v8, v9)

blk2:
Statements:
  (v10: core::gas::GasBuiltin) <- core::gas::redeposit_gas(v6)
End:
  Return(v5, v10)

//! > ==========================================================================

//! > Test nopanic function cycle with withdraw gas.

//! > test_runner_name
test_function_lowering(expect_diagnostics: false)

//! > cairo_code
#[target_function]
fn foo(x: felt252, costs: core::gas::BuiltinCosts) nopanic {
    match core::gas::withdraw_gas_all(costs) {
        Some(_) => foo(x, costs),
        None => {},
    }
}

//! > semantic_diagnostics

//! > lowering_diagnostics

//! > lowering_flat
Parameters: v0: core::RangeCheck, v1: core::gas::GasBuiltin, v2: core::felt252, v3: core::gas::BuiltinCosts
blk0 (root):
Statements:
End:
  Match(match core::gas::withdraw_gas_all(v0, v1, v3) {
    Option::Some(v4, v5) => blk1,
    Option::None(v6, v7) => blk2,
  })

blk1:
Statements:
  (v8: core::gas::GasBuiltin) <- core::gas::redeposit_gas(v5)
  (v9: core::RangeCheck, v10: core::gas::GasBuiltin) <- test::foo(v4, v8, v2, v3)
End:
  Return(v9, v10)

blk2:
Statements:
  (v11: core::gas::GasBuiltin) <- core::gas::redeposit_gas(v7)
End:
  Return(v6, v11)

//! > ==========================================================================

//! > Test destructor basic cycle.

//! > test_runner_name
test_function_lowering(expect_diagnostics: true)

//! > cairo_code
struct A {}
impl ADestruct of Destruct<A> {
    fn destruct(self: A) nopanic {
        let A { } = self;
        B {};
    }
}

struct B {}
impl BDestruct of Destruct<B> {
    fn destruct(self: B) nopanic {
        let B { } = self;
        A {};
    }
}
#[target_function]
fn foo() {}

//! > semantic_diagnostics

//! > lowering_diagnostics
error[E3008]: Call cycle of `nopanic` functions is not allowed.
 --> lib.cairo:3:5-6:5
      fn destruct(self: A) nopanic {
 _____^
| ...
|     }
|_____^

error[E3008]: Call cycle of `nopanic` functions is not allowed.
 --> lib.cairo:11:5-14:5
      fn destruct(self: B) nopanic {
 _____^
| ...
|     }
|_____^

//! > lowering_flat
Parameters:
blk0 (root):
Statements:
End:
  Return()

//! > ==========================================================================

//! > Test self-referential Destruct impl in no-gas mode does not hang (issue #9894).

//! > test_runner_name
test_function_lowering(expect_diagnostics: false, no_gas: true)

//! > cairo_code
struct D {}
impl DDestruct of Destruct<D> {
    fn destruct(self: D) nopanic {}
}
#[target_function]
fn foo() {
    let _ = D {};
}

//! > semantic_diagnostics

//! > lowering_diagnostics

//! > lowering_flat
Parameters:
blk0 (root):
Statements:
  (v0: test::D) <- struct_construct()
  () <- test::DDestruct::destruct(v0)
End:
  Return()

//! > ==========================================================================

//! > Test gas check placed on the first defined function of a cycle.

//! > test_runner_name
test_function_lowering(expect_diagnostics: false)

//! > cairo_code
mod a {
    pub fn ping(n: felt252) -> felt252 {
        if n == 0 {
            return 0;
        }
        super::pong(n - 1)
    }
}

#[target_function]
fn pong(n: felt252) -> felt252 {
    if n == 0 {
        return 1;
    }
    a::ping(n - 1)
}

//! > semantic_diagnostics

//! > lowering_diagnostics

//! > lowering_flat
Parameters: v0: core::RangeCheck, v1: core::gas::GasBuiltin, v2: core::felt252
blk0 (root):
Statements:
End:
  Match(match core::felt252_is_zero(v2) {
    IsZeroResult::Zero => blk1,
    IsZeroResult::NonZero(v3) => blk2,
  })

blk1:
Statements:
  (v4: core::gas::GasBuiltin) <- core::gas::redeposit_gas(v1)
  (v5: core::felt252) <- 1
  (v6: (core::felt252,)) <- struct_construct(v5)
  (v7: core::panics::PanicResult::<(core::felt252,)>) <- PanicResult::Ok(v6)
End:
  Return(v0, v4, v7)

blk2:
Statements:
  (v8: core::gas::GasBuiltin) <- core::gas::redeposit_gas(v1)
  (v9: core::felt252) <- 1
  (v10: core::felt252) <- core::felt252_sub(v2, v9)
  (v11: core::RangeCheck, v12: core::gas::GasBuiltin, v13: core::panics::PanicResult::<(core::felt252,)>) <- test::a::ping(v0, v8, v10)
End:
  Return(v11, v12, v13)