Files
core/test/rust/compiler/task/select.rs
T
2026-11-03 03:32:07 +00:00

117 lines
4.2 KiB
Rust

use super::linked;
#[test]
fn selection_checks_named_outputs_static_fallback_and_affine_ownership() {
let prefix = "work() (value: Int) { value = 1 }\nfallback() (value: Int) { value = 2 }\n";
for body in [
"value = timeout(run(work()), 1, fallback)",
"first = run(work())\n second = run(work())\n value = race(first, second)",
] {
assert!(linked(&format!("{prefix}main() (value: Int) {{ {body} }}")).is_ok());
}
for (extra, body, code) in [
(
"wrong() (answer: Int) { answer = 0 }",
"value = timeout(run(work()), 1, wrong)",
"C005",
),
(
"wrong(input: Int) (value: Int) { value = input }",
"value = timeout(run(work()), 1, wrong)",
"C005",
),
(
"wrong() (answer: Int) { answer = 0 }",
"value = race(run(work()), run(wrong()))",
"C005",
),
("", "value = race(run(work()))", "C005"),
("", "value = race(run(work()), 1)", "C005"),
(
"",
"pending = run(work())\n value = race(pending, pending)",
"C013",
),
(
"",
"pending = run(work())\n value = timeout(pending, 1, fallback)\n again = wait(pending)",
"C013",
),
("", "value = timeout(run(work()), 1.0e0, fallback)", "C005"),
] {
let source = format!("{prefix}{extra}\nmain() (value: Int) {{ {body} }}");
assert_eq!(linked(&source).unwrap_err().code, code, "{source}");
}
}
#[test]
fn timeout_retains_task_ownership_while_duration_is_awaited() {
let source = "work() (value: Int) { value = 1 }\nfallback() (value: Int) { value = 2 }\nduration() (value: Int) { dever.task.sleep(0)\n value = 1 }\nmain() (value: Int) { value = timeout(run(work()), duration(), fallback) }";
assert!(linked(source).is_ok());
assert_eq!(linked("work() () {}\nfallback() () { dever.io.println(\"blocked\") }\nmain() () { timeout(run(work()), 1, fallback) }").unwrap_err().code, "C013");
}
#[test]
fn cancellation_does_not_discharge_input_error_obligations() {
let prefix = "type Result { Done\n error Failed(message: Text) }\nhandle(value: Result) () recover(\"handles input\") {}\nempty() () {}\n";
for body in [
"timeout(run(handle(Result.Failed(\"first\"))), 1, empty)",
"race(run(handle(Result.Failed(\"first\"))), run(handle(Result.Failed(\"second\"))))",
"problem = Result.Failed(\"shared\")\n race(run(handle(problem)), run(empty()))",
] {
assert_eq!(
linked(&format!("{prefix}main() () {{ {body} }}"))
.unwrap_err()
.code,
"C012"
);
}
assert!(linked(&format!("{prefix}main() () {{ problem = Result.Failed(\"shared\")\n race(run(handle(problem)), run(handle(problem))) }}")).is_ok());
}
#[test]
fn selected_error_values_must_be_returned_or_handled() {
let prefix = "type Result { Done(value: Int)\n error Failed(message: Text) }\nwork() (value: Result) { value = Result.Failed(\"reason\") }\nfallback() (value: Result) { value = Result.Done(0) }\n";
for operation in [
"timeout(run(work()), 1, fallback)",
"race(run(work()), run(work()))",
] {
assert_eq!(
linked(&format!("{prefix}main() () {{ lost = {operation} }}"))
.unwrap_err()
.code,
"C012"
);
assert!(
linked(&format!(
"{prefix}main() (value: Result) {{ value = {operation} }}"
))
.is_ok()
);
}
}
#[test]
fn selected_ranges_include_fallback_and_each_possible_winner() {
let prefix = "one() (value: Int) { value = 1 }\ntwo() (value: Int) { value = 2 }\n";
for operation in [
"timeout(run(one()), 1, two)",
"race(run(one()), run(two()))",
] {
assert_eq!(
linked(&format!(
"{prefix}main() (value: Int <= 1) {{ value = {operation} }}"
))
.unwrap_err()
.code,
"C011"
);
assert!(
linked(&format!(
"{prefix}main() (value: Int <= 2) {{ value = {operation} }}"
))
.is_ok()
);
}
}