Почему этот шаблон совпадения недоступен при использовании нелитеральных шаблонов?

Следующий код (детская площадка)

let max_column = 7;
edge = match current_column {
    0 => Edge::Left,
    max_column => Edge::Right,
    _ => Edge::NotAnEdge
};

выдает следующее предупреждение:

warning: unreachable pattern
  --> src/main.rs:10:9
   |
9  |         max_column => Edge::Right,
   |         ---------- matches any value
10 |         _ => Edge::NotAnEdge
   |         ^ unreachable pattern
   |
   = note: #[warn(unreachable_patterns)] on by default

Замена переменной max_column на литерал работает нормально:

let max_column = 7;
edge = match current_column {
    0 => Edge::Left,
    7 => Edge::Right,
    _ => Edge::NotAnEdge
};

Почему _ недоступен в первом примере, когда его можно достичь для любых значений, где current_column != max_column?

Ответ 1

Язык программирования Rust объясняет, как обрабатывается выражение match, выделение мое:

Когда выполняется выражение match, оно сравнивает результирующее значение с шаблоном каждого плеча, по порядку.

В вашем примере max_column - это имя переменной, с которой нужно связать, не константу или внешнюю переменную. Когда компилятор достигает max_column, любые оставшиеся значения будут назначены для этой совпадающей ветки, что сделает последующие ветки недоступными.

В вашем случае вам нужен охранник матча:

let current_column = 1;
let max_column = 7;
edge = match current_column {
    0                    => Edge::Left,
    a if a == max_column => Edge::Right,
    _                    => Edge::NotAnEdge
};

Обратите внимание, что в первом приближении a и _ - это одно и то же! В обоих случаях сопоставляемая переменная будет привязана к имени (a или _ соответственно), но любой идентификатор с префиксом _ специально предназначен для использования в качестве заполнителя неиспользуемой переменной.

Блюсс уточняет и исправляет это приближение:

_ является отдельным частным случаем, это вовсе не привязка переменной, но ее отсутствие! Сопоставление с _x перемещает значение в _x, _ ничего подобного не делает. (Разница заметна.)