E6036
E6036 — A token oftransfer_asyncthat the program drops with no.wait(): at the end of its scope, or when an assignment gives its variable a new value. The copy may not be done then, so its target may not hold the data. Call.wait(), which gives the placed tensor.
What the compiler reports
Error[E6036] at {{.*}}.vx:[[@LINE+1]]:3: the transfer token '_never' is dropped with no `.wait()` when its scope ends, so the copy may not be done. Call `_never.wait()`, which gives the placed tensor
Error[E6036] at {{.*}}.vx:[[@LINE+1]]:3: the transfer token 't' is dropped with no `.wait()` when this assignment gives it a new value
Error[E6036] at {{.*}}.vx:[[@LINE+1]]:{{[0-9]+}}: the transfer token 't' is dropped with no `.wait()` when its scope ends
Error[E3004] {{.*}}Cannot index a value of type Token<Tensor<f32, [4], Memory::CPU_DRAM>>
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
//
// A token of `transfer_async` must be waited, or the copy may not be done. Each function here
// drops a token with no `.wait()`, or reads the data before the wait.
//
fn filled(v : f32) -> Tensor<f32, [4]> {
let mut t = unsafe { Tensor<f32, [4]>::uninit() };
t[0] = v;
return t;
}
fn dropped_at_the_end_of_its_scope() -> void {
let _never = transfer_async(filled(1.0), Memory::CPU_DRAM);
}
fn overwritten() -> f32 {
let mut t = transfer_async(filled(1.0), Memory::CPU_DRAM);
t = transfer_async(filled(2.0), Memory::CPU_DRAM);
let x = t.wait();
return x[0];
}
fn takes_a_token_and_drops_it(t : Token<Tensor<f32, [4], Memory::CPU_DRAM>>) -> void {
}
// A function that waits for the token it takes is right.
fn takes_a_token_and_waits(t : Token<Tensor<f32, [4], Memory::CPU_DRAM>>) -> f32 {
let x = t.wait();
return x[0];
}
fn read_before_wait() -> f32 {
let t = transfer_async(filled(1.0), Memory::CPU_DRAM);
let v = t[0];
let x = t.wait();
return v + x[0];
}
fn main() -> i32 {
return 0;
}
From tests/frontend/fail/transfer_tokens_that_are_not_waited.vx, which asserts this diagnostic on every commit.
Related
Topologies and memoryThe chapter covering the rule this code enforces.
All diagnosticsEvery code the compiler can emit, grouped by stage.
E6035A
Memory declaration's within: names a space that is not built in, and that the program and its machine files do not declare. A typo in the name is the usual cause.