E3031

E3031 — impl Copy for X where one of X's fields is a type that moves. Copy promises a value survives being assigned elsewhere, and a field that does not survive it breaks that promise for the whole type — which would be a way to duplicate a tensor, or any other placed value, without saying so.

What the compiler reports

Error[E3031]{{.*}}'HoldsTensor' cannot be `Copy`: its field 't' has type Tensor<f32, [4]>
Error[E3031]{{.*}}'CarriesTensor' cannot be `Copy`: its variant 'WithTensor' has type Tensor<f32, [4]>
Error[E3031]{{.*}}'HoldsPlain' cannot be `Copy`: its field 'p' has type Plain

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

//
// A type may declare itself `Copy` only if everything it holds is `Copy` too. `Copy`
// promises a value survives being assigned somewhere else, and a field that does not
// survive it breaks that promise for the whole type.
//
// The tensor cases are why the rule exists rather than being a tidiness measure. A
// tensor is linear because moving it is what the placement discipline is made of, and
// duplicating one is an explicit `transfer`. A struct holding a tensor that was allowed
// to be `Copy` would be a way to duplicate that tensor without saying so -- and the same
// through an enum payload, which is the second case.
//
// The third holds no tensor at all: `Plain` is an ordinary struct that has not declared
// `Copy`, so it moves, so a `Copy` type cannot hold one either. That case is here because
// the rule is about what moves, not about tensors.

trait Copy {}

struct HoldsTensor {
  t : Tensor<f32, [4]>,
  n : i32,
}

impl Copy for HoldsTensor {}

enum CarriesTensor {
  Plain,
  WithTensor(Tensor<f32, [4]>),
}

impl Copy for CarriesTensor {}

struct Plain {
  a : i32,
}

struct HoldsPlain {
  p : Plain,
}

impl Copy for HoldsPlain {}

fn main() -> i32 {
  return 0;
}

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

Related