As mentioned in #544 , handlers which use multi-shot continuations can duplicate a linear channel. However, it is still possible to break Links without multi-shot continuations by directly using the linear channel in the handler clauses. The reason seems to be that for handle M with H, the current type checking considers the usage of linear resources in M and H individually. The following program illustrates the problem:
fun deadlock() {
var ch = fork(fun(ch) {
var ch = send(42, ch);
close(ch)
});
handle({
# Nondeterministic choice.
ignore(do Flip);
var (i, ch) = receive(ch);
println("Int: " ^^ intToString(i));
close(ch)
}) {
case Return(_) -> ()
case Flip(resume) -> {
var (i, ch) = receive(ch);
println("Int: " ^^ intToString(i));
close(ch);
resume(true)
}
}
}
I think for deep handlers, we should disallow the usage of linear resources in handler clauses. And for shallow handlers, we should split the linear resources context for M and H, and also use the same linear context for every clause in H (just like the typing rule for if or case statement).
As mentioned in #544 , handlers which use multi-shot continuations can duplicate a linear channel. However, it is still possible to break Links without multi-shot continuations by directly using the linear channel in the handler clauses. The reason seems to be that for
handle M with H
, the current type checking considers the usage of linear resources inM
andH
individually. The following program illustrates the problem:I think for deep handlers, we should disallow the usage of linear resources in handler clauses. And for shallow handlers, we should split the linear resources context for
M
andH
, and also use the same linear context for every clause inH
(just like the typing rule forif
orcase
statement).