E3050

E3050 — A pattern inside a variant's payload that is not a name or _, such as the 3 in Val(3) or the Inner::A(v) in Wrap(Inner::A(v)). The compiler does not test such a pattern when it chooses an arm, so the arm would be taken for any payload. Bind the payload to a name and test it in the arm, with an if or another match.

What the compiler reports

Error[E3050] at [[@LINE+1]]:5: a payload of `Val` can be matched only by a name or `_`
Error[E3050] at [[@LINE+1]]:5: a payload of `Wrap` can be matched only by a name or `_`
2 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
//
//
// Inside a variant's payload, a pattern can be only a name or `_`. A value, as in `Val(3)`, or
// another variant, as in `Wrap(Inner::A(v))`, is refused (E3050): the compiler does not test
// it, so `Val(3)` used to be chosen for `Val(7)` too. `Val(x)` and `Val(_)` are accepted.

enum Box2 {
  Val(i32),
  Empty,
}

enum Inner {
  A(i32),
  B,
}

enum Outer {
  Wrap(Inner),
  Nothing,
}

fn by_value(b : Box2) -> i32 {
  match b {
    Box2::Val(3) => {
      return 100;
    }
    Box2::Val(x) => {
      return x;
    }
    Box2::Empty => {
      return 0;
    }
  }
}

fn nested(o : Outer) -> i32 {
  match o {
    Outer::Wrap(Inner::A(v)) => {
      return v;
    }
    Outer::Wrap(_) => {
      return 1;
    }
    Outer::Nothing => {
      return 0;
    }
  }
}

fn main() -> i32 {
  return by_value(Box2::Val(7)) + nested(Outer::Nothing);
}

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

Related