-
Notifications
You must be signed in to change notification settings - Fork 86
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Unable to handle null
return types from Rust
#581
Comments
This is expected. Rust type |
Hey, we're trying to understand what you mean here. Rust is warning us that
it produces this Rust: // This is an experimental feature to generate Rust binding from Candid.
// You may want to manually adjust some of the types.
use ic_cdk::export::candid::{self, CandidType, Deserialize};
use ic_cdk::api::call::CallResult;
struct SERVICE(candid::Principal);
impl SERVICE{
pub async fn getNull(&self) -> CallResult<((),)> {
ic_cdk::call(self.0, "getNull", ()).await
}
pub async fn printNull(&self, arg0: ()) -> CallResult<((),)> {
ic_cdk::call(self.0, "printNull", (arg0,)).await
}
} null in parameters and return types is represented in the generated Rust code as Furthermore, when we use To me I'm wondering if |
Actually...we just tried |
Perhaps #[ic_cdk_macros::query]
fn get_null() -> () {} cargo expands to: #![feature(prelude_import)]
#[prelude_import]
use std::prelude::rust_2018::*;
#[macro_use]
extern crate std;
#[export_name = "canister_query get_null"]
fn get_null_0_() {
ic_cdk::setup();
ic_cdk::spawn(async {
let () = ic_cdk::api::call::arg_data();
let result = get_null();
ic_cdk::api::call::reply(())
});
}
fn get_null() -> () {} #[ic_cdk_macros::query]
fn get_null() -> (()) {} cargo expands to: #![feature(prelude_import)]
#[prelude_import]
use std::prelude::rust_2018::*;
#[macro_use]
extern crate std;
#[export_name = "canister_query get_null"]
fn get_null_0_() {
ic_cdk::setup();
ic_cdk::spawn(async {
let () = ic_cdk::api::call::arg_data();
let result = get_null();
ic_cdk::api::call::reply((result,))
});
}
fn get_null() -> (()) {}
|
Perhaps instead of this |
Sorry, we keep figuring more things out that you probably already knew. This candid:
generates this Rust with // This is an experimental feature to generate Rust binding from Candid.
// You may want to manually adjust some of the types.
use ic_cdk::export::candid::{self, CandidType, Deserialize};
use ic_cdk::api::call::CallResult;
struct SERVICE(candid::Principal);
impl SERVICE{
pub async fn getNull(&self) -> CallResult<()> {
ic_cdk::call(self.0, "getNull", ()).await
}
} And this Candid:
generates this Rust with // This is an experimental feature to generate Rust binding from Candid.
// You may want to manually adjust some of the types.
use ic_cdk::export::candid::{self, CandidType, Deserialize};
use ic_cdk::api::call::CallResult;
struct SERVICE(candid::Principal);
impl SERVICE{
pub async fn getNull(&self) -> CallResult<((),)> {
ic_cdk::call(self.0, "getNull", ()).await
}
} So there is a differentiation that we weren't taking into account. This just seems strange to us, so maybe you can enlighten us. I do wonder if a |
When reading candid, `()` means `()` in Rust and `null` means `(())`` in Rust. So, if we encounter the empty tuple, we need to convert that to a tuple containing the empty tumple. See the disccusion on dfinity/agent-js#581.
You are right. Some facts:
Therefore, when we see a return type |
@dansteren do you consider this issue resolved? |
I'm not sure this is resolved, this situation has given us quite a bit of confusion while developing Azle. If the real answer is developing |
@krpeacock we were able to work around this as soon as we understood the syntax you guys require. But I agree with @lastmjs, the syntax was quite confusing and not intuitive. Given that there is already a precedence for other candid types such as Empty and Required, I also think it would be best if we pursued creating a |
Describe the bug
When using the JS agent to make requests to Rust canisters methods that return
null
, the agent throws the error:Wrong number of return values
.To Reproduce
dfx new --type=rust actor_test
cd actor_test
Null
type):dfx start
dfx deploy
get_null
canister methoddfx canister call actor_test get_null
=>(null: null)
Expected behavior
The agent should handle the
null
return value instead of throwing an error, and both the call and the result (null) should be displayed in the output log in the Candid UI.Screenshots
Desktop (please complete the following information):
Additional context
This is only a problem for Rust and Azle canisters. The agent handles
null
responses from Motoko canisters without problem. For example, consider the following Motoko canister:The candid file for both this motoko canister and the provided Rust canister are the same, namely:
Therefore, it should be that the the agent can handle both canisters the same. However, only the
null
value being returned by the Motoko canister is correctly handled by the JS Agent.Also worth noting is that although the JS Agent doesn't handle the Rust return values, both canisters return
(null: null)
when executingdfx canister call agent_test get_null
from the command line.The text was updated successfully, but these errors were encountered: