dfinity / cdk-rs

Rust canister development kit for the Internet Computer.
Apache License 2.0
202 stars 88 forks source link

Please change syntax to be more noticeable #505

Open vporton opened 2 months ago

vporton commented 2 months ago

Please, change the syntax from

#[update]
fn f(/*...*/) {
  // ...
}

to

#[update]
#[return_immediately]
fn f(/*...*/) {
  // ...
}

Give a warning if used old syntax.

This is because the first syntax deviates from the usual meaning of Rust functions (usual Rust functions never return before their body has finished executing) and can be too easily confused by a user with an async #[update] (or #[query]) function. This is just too much error-prone and the programmer needs to see that the function returns before its execution.

The current practice deviates from the sound Rust practice to be a reliable programming language.

chenyan-dfinity commented 2 months ago

I don't understand this. Functions never return immediately. If you make an inter-canister call, it won't return until the function finishes. The behavior is exactly the same for async functions.

You may be referring to making update calls from the agent side. In that case, it's up to the caller to decide if you want to call the endpoints asynchronously or synchronously. If calling asynchronously, it yields the control, and the agent has to poll to get the result, and you won't get the result until the function returns. If calling synchronously, it waits until the functions returns. Again, this is entirely up to the caller to decide how they want to make the call, it has nothing to do with the canister endpoints.

vporton commented 2 months ago

I don't understand this. Functions never return immediately. If you make an inter-canister call, it won't return until the function finishes. The behavior is exactly the same for async functions.

In Motoko, there are sync methods like this:

public shared func inc() : () { /*...*/ };

(note no async here). Such functions return immediately, before doing /.../ calculations (that may be done after the function returns).

It apparently translates to Rust as:

#[update]
func inc() { /*...*/ };

(note no async).

You may be referring to making update calls from the agent side. In that case, it's up to the caller to decide if you want to call the endpoints asynchronously or synchronously. If calling asynchronously, it yields the control, and the agent has to poll to get the result, and you won't get the result until the function returns. If calling synchronously, it waits until the functions returns. Again, this is entirely up to the caller to decide how they want to make the call, it has nothing to do with the canister endpoints.

This is unrelated.

chenyan-dfinity commented 2 months ago

It apparently translates to Rust as:

[update]

func inc() { /.../ };

No, this is equivalent to public shared func inc() : async (). There is no one-way function attributes in Rust CDK.

vporton commented 2 months ago

There is no one-way function attributes in Rust CDK.

I request it to be implemented.