//! > 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)