E3021
E3021 — An enum variant whose payload is aPinnedorReftensor. A payload tensor is stored as its memref descriptor. Its drop frees a tensor in a memory space through the plugin that the memory's type names.PinnedandRefgive the location outside the tensor type, so the drop does not know it, and such a payload is refused.
What the compiler reports
Error[E3021] at {{.*}}.vx:[[@LINE+1]]:10: payload argument 1 of Payload::Kept is {{.*}}. An enum variant cannot carry a `Pinned` or `Ref` tensor yet
{{^}}Semantic check failed on {{.*}}: 1 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
//
// An enum variant can carry a tensor, also one in a memory space such as `W`. Its drop frees
// the tensor through the plugin of `W`. A `Pinned` tensor gives its place outside the tensor
// type, so the drop does not know it, and the variant cannot carry one yet.
//
Memory CPU_DRAM {}
Memory W {
within: Memory::CPU_DRAM, capacity: 4 MiB, managed: explicit, scope: device
}
Topology Dev {
arch: nvptx64,
memory: Memory::W,
visible: [Memory::W],
transfer Memory::CPU_DRAM -> Memory::W : 10,
transfer Memory::W -> Memory::CPU_DRAM : 10
}
enum Payload {
Placed(Tensor<f32, [2, 2], Memory::W>),
Host(Tensor<f32, [2, 2]>),
Kept(Pinned<Tensor<f32, [2, 2]>, Topology::Dev>),
Val(i32),
}
fn keep(t : Pinned<Tensor<f32, [2, 2]>, Topology::Dev>) -> Payload {
return Payload::Kept(t);
}
fn main() -> i32 {
let _ok = Payload::Val(7);
let _host = Payload::Host(Tensor<f32, [2, 2]>::fill(1.0));
let _placed = Payload::Placed(transfer(Tensor<f32, [2, 2]>::fill(1.0), Memory::W));
return 0;
}
From tests/frontend/fail/an_enum_variant_cannot_carry_a_pinned_tensor.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.
E3020A
match that no arm is guaranteed to match. A match over an enum must name every variant or carry a wildcard arm, wherever it sits. The uncovered value falls through, and when every written arm returns, the function falls off its end and hands back whatever was in the return slot. A scrutinee that is not an enum cannot be enumerated, so it is only asked for a wildcard in value position, where the fall-through edge would otherwise have no value to carry — codegen used to paper over that by evaluating the whole match to a constant zero.
E3022An extern function whose signature mentions a tensor. A tensor is a memref, and lowering expands a memref parameter into the seven scalars of its descriptor — allocated pointer, aligned pointer, offset, and a size and stride per rank. So fn c_take(t : Tensor<f32, [?, ?]>) -> i32 declares a C symbol taking seven arguments, which is not a signature anyone writes on the C side; the call links by name and passes something the callee never agreed to. Take a raw pointer and build the tensor in Vx (Tensor<f32, [?, ?]>::from_ptr_2d), which is what the corpus already does.