E3021
E3021 — An enum variant whose payload is a tensor. A payload is stored into the variant's tagged-union slot with llvm.insertvalue, which takes primitive operands, and a tensor is a memref descriptor. The AST path dropped such a payload silently: the construction emitted the tag and nothing else, so a program carrying a tensor through an enum compiled, ran, and lost it with no diagnostic. A struct field holding a tensor is the same representational gap in another position.
What the compiler reports
E3021 … payload argument 1 of Payload::Weights … cannot carry a tensor
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 payload is stored into the variant's slot with `llvm.insertvalue`,
// which takes primitive operands, and a tensor is a memref descriptor.
//
// This was accepted and miscompiled rather than refused: the construction
// emitted the tag and dropped the tensor, so the program compiled, ran, and
// lost the payload with nothing said. A scalar payload is unaffected and stays
// legal -- `Val(i32)` below constructs and matches.
//
enum Payload {
Weights(Tensor<f32, [2, 2]>),
Val(i32),
}
fn main() -> i32 {
let ok = Payload::Val(7);
let a = Tensor<f32>([2, 2]);
let bad = Payload::Weights(a);
return 0;
}
From tests/frontend/fail/enum_variant_cannot_carry_a_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.