E3004

E3004 — Type mismatch in binary operation

What the compiler reports

E3004{{.*}}cannot assign Tensor<f32, [4]> to Tensor<f16, [4]>

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
//
// Storing a widened slice back into half storage has to say so.
//
// A half slice is storage: it widens to f32 on load and the arithmetic happens
// there, so `o[0] * corr` is an f32 slice whatever `corr` is. Assigning that
// into an f16 row is a narrowing conversion, and Vx has no implicit numeric
// conversion -- the program writes `as f16`, exactly as a scalar would.
//
// This used to be accepted, and then crashed the emitter: the lowering widened
// the row, assumed everything else was already f32, and stored a vector<4xf32>
// into a memref<4xf16>. The module did not parse. An `as` the checker demands is
// the difference between a conversion the program asked for and one the backend
// invented.
//

fn main() -> i32 {
  let mut o = Tensor<f16, [ 2, 4 ]>::new();
  // Non-zero and distinct per lane, so the file stays a valid program to run if
  // the refusal below is ever lifted.
  for d in 0..4 {
    o[0][d] = 1.5 + (d as f16);
  }
  let corr : f32 = 0.5;
  o[0] = o[0] * corr;
  return 0;
}

From tests/frontend/fail/slice_narrowing_needs_a_cast.vx, which asserts this diagnostic on every commit.

Related