motoko
motoko copied to clipboard
bug: local async function with non-async expression body are not reject as they (probably) should be.
Looks like we have a bug in the type checker that is allowing these examples:
actor {
func f() : async () {loop ()}; // legal
func g() : async () = async {loop ()}; // legal
func h() : async () = loop (); //should be illegal, body not an async expression
public shared func go() : async () {
let _ = f : () -> async ();
let _ = g : () -> async ();
let _ = h : () -> async ()
}
}
https://m7sm4-2iaaa-aaaab-qabra-cai.raw.ic0.app/?tag=1246906498
However, even if we syntactically reject h(), can we still construct bad functions using generics or even just subtyping? Eg. something like:
func make_h<T>() : () -> T { func () : T = loop() };
let h = make_h<async()>();
Actually, we are probably ok but underlying type assigned to h doesn't look like an async function (missing scope parameter etc) so we can't use it to send a message and awaits will be ill-scoped.
import Timer "mo:base/Timer";
actor {
func f() : async () {loop ()}; // legal
func g() : async () = async {loop ()}; // legal
func h() : async () = loop (); // body not an async expression
let idf = Timer.setTimer<system>(#seconds 0, f);
let idg = Timer.setTimer<system>(#seconds 0, g);
let idh = Timer.setTimer<system>(#seconds 0, h); // rejected
public shared func go() : async () {
let _ = f : () -> async ();
let _ = g : () -> async ();
let _ = h : () -> async ()
};
}
https://m7sm4-2iaaa-aaaab-qabra-cai.raw.ic0.app/?tag=3774773533