I think we’ve discovered a bug in the Rust CDK. Currently ic_cdk_macros allows guard functions on init
, pre_upgrade
, and post_upgrade
. But the expanded code for the guard function macro results in a call to ic0.msg_reject
, which is not allowed from canister_init
, canister_post_upgrade
, or canister_pre_upgrade
according to the current interface spec. We also see this error in our CI tests for guard functions in Azle.
Here’s the expanded code for a guard function:
#[export_name = "canister_pre_upgrade"]
fn pre_upgrade_4_() {
ic_cdk::setup();
let r: Result<(), String> = _cdk_user_defined_preventUpgrades();
if let Err(e) = r {
ic_cdk::api::call::reject(&e);
return;
}
ic_cdk::spawn(async {
let result = pre_upgrade();
});
}
And here’s where the interface spec describes where ic0.msg_reject
can be called from:
ic0.msg_reject : (src : i32, size : i32) → (); // U Q CQ Ry Rt CRy CRt
Seems like the Rust CDK is incorrect in allowing guard functions for init
, pre_upgrade
and post_upgrade
.