E3031
E3031 —impl Copy for Xwhere one ofX's fields is a type that moves.Copypromises 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
A tour of VxThe chapter covering the rule this code enforces.
All diagnosticsEvery code the compiler can emit, grouped by stage.
E3030An operator applied to operand types it is not defined on —
% on a shaped tensor or on a bool. Refused here because the alternative is worse in both directions: the flat emitter would decline and fall back to a path that cannot lower it either, and an i1 operand would reach arith.remsi and verify.
E3032A chain of generic instantiations that does not end — f<N - 1>() whose base case is never reached. Reported here rather than left to run out of stack, which gave no file, no line and no message.