E3058
E3058 — Areturn,breakorcontinuethat leaves a task, or a task that joins another task. The last expression of a task body is its result. A task cannot join another task yet. Join both tasks in thetasksblock.
What the compiler reports
Error[E3058] at [[@LINE+4]]:7: a `return` cannot leave a task
Error[E3058] at [[@LINE+5]]:9: a `break` cannot leave a task
Error[E3058] at [[@LINE+7]]:9: a task cannot join another task yet
Error[E4001] at [[@LINE+7]]:5: Use of moved or consumed linear variable: h
{{^}}Semantic check failed on {{.*}}: 11 error(s) emitted
The fragments the test suite holds the compiler to. An ellipsis marks text the test does not constrain; the emitted message also carries a source location.
A program that triggers it
//
// Part of the Vx Project, under the Apache License v2.0 with LLVM Exceptions.
// See LICENSE for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//
// The end of a `tasks` block waits for each task that it started. So a `spawn` must be in a
// `tasks` block, and a task handle must not leave it: its only use is `h.join()`. A task body
// ends with its result, so a `return` or `break` must not leave it.
fn no_tasks_block() -> i32 {
let h = spawn {
1
};
return h.join();
}
fn spawn_in_a_closure() -> void {
tasks {
let f = |x : i32| spawn {
x
};
}
}
fn spawn_directly_in_a_task() -> void {
tasks {
spawn {
spawn {
1
};
};
}
}
fn handle_is_the_value_of_the_block() -> i32 {
return tasks {
let h = spawn {
1
};
h
};
}
fn handle_given_to_a_variable() -> void {
tasks {
let h = spawn {
1
};
let g = h;
}
}
fn spawn_as_an_argument() -> void {
tasks {
print(spawn {
1
});
}
}
fn handle_with_a_wrong_type() -> void {
tasks {
let h : i32 = spawn {
1
};
h.join();
}
}
fn return_from_a_task() -> i32 {
tasks {
spawn {
return 1;
};
}
return 0;
}
fn break_out_of_a_task() -> void {
tasks {
for i in 0..3 {
spawn {
break;
};
}
}
}
fn task_joins_a_task() -> void {
tasks {
let a = spawn {
1
};
let b = spawn {
a.join() + 1
};
b.join();
}
}
fn joined_twice() -> void {
tasks {
let h = spawn {
1
};
h.join();
h.join();
}
}
fn main() -> i32 {
return 0;
}
// The errors above are all the errors.
From tests/frontend/fail/spawn_outside_a_tasks_block_and_handles_that_leave_it.vx, which asserts this diagnostic on every commit.
Related
A tour of VxThe chapter covering the rule this code enforces.
All diagnosticsEvery code the compiler can emit, grouped by stage.
E3057A task handle used in a way other than
h.join(), or a spawn that is not the value of a let or a statement of its own. A task must not leave its tasks block, so the program cannot return a handle, store it, or pass it to a function. Write let h = spawn { .. }; and later h.join().