Неполное совпадение (фактически исчерпывающее)

Я новичок в Rust, и мне нравится идея иметь такую ​​конструкцию, как match, при которой проверяется полнота того, что я пишу, но у меня возникают проблемы с компилятором при выполнении очень простых вещей, которые на самом деле правильны, например, следующих.

Как мне поступить в этой ситуации? (В этом случае код поясняет себя)

fn main() {
    let my_int = -29;
    match my_int {
        x if x < 10            => {println!("Foo")},
        x if x >= 10 && x < 20 => {println!("Bar")},
        x if x >= 20           => {println!("Baz")},
    }
}

Компилятор говорит:

error[E0004]: non-exhaustive patterns: `_` not covered
 --> src/main.rs:3:11
  |
3 |     match my_int {
  |           ^^^^^^ pattern `_` not covered
  |
  = note: the matched value is of type `i32`
  = note: match arms with guards don't count towards exhaustivity
help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
  |
6 ~         x if x >= 20 => {println!("Baz")},
7 ~         _ => todo!(),
  |

В целях проверки полноты компилятор всегда рассматривает охранники if как потенциально несовпадающие. Вы можете просто опустить защиту последней руки, если она всегда совпадает.

Sven Marnach 24.03.2024 18:05

Да, но это сделает код менее читабельным, как это обойти?

Umberto Fontanazza 24.03.2024 18:07

Я не думаю, что код станет менее читабельным, если не будет предоставлять избыточную информацию, особенно если вы измените второй случай на x if x < 20 Я думаю, это сделает случаи более понятными, поскольку предыдущий случай уже обеспечивает нижнюю границу принятого диапазона.

Masklinn 24.03.2024 18:09

Вы можете добавить _ => unreachable!(), см. doc.rust-lang.org/std/macro.unreachable.html#examples

mkrieger1 24.03.2024 18:13
Почему Python в конце концов умрет
Почему Python в конце концов умрет
Последние 20 лет были действительно хорошими для Python. Он прошел путь от "просто языка сценариев" до основного языка, используемого для написания...
0
4
115
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Просто используйте x или _ для последней записи. Альтернативно, закодируйте свои диапазоны в перечисление.

В Rust нет (на данный момент?) типов диапазонов или уточнений типов, поэтому, поскольку ошибка компилятора сообщает вам, что компилятор в настоящее время не может вычислить полноту соответствия на основе защитных мер, охватывающих весь домен, любой защищенный шаблон будет неполным по определению.

Ответ принят как подходящий

Это связано с тем, что использование условия не ограничивает полноту типов. Но вы можете написать так:

fn main() {
    let my_int = -29;
    match my_int {
        ..=9    => {println!("Foo")},
        10..=19 => {println!("Bar")},
        20..    => {println!("Baz")},
    }
}

Если вы хотите использовать x, вы можете сделать это следующим образом:

fn main() {
    let my_int = -29;
    match my_int {
        x @ ..=9    => {println!("Foo: {x}")},
        x @ 10..=19 => {println!("Bar: {x}")},
        x @ 20..    => {println!("Baz: {x}")},
    }
}

ошибка [E0658]: синтаксис шаблона эксклюзивного диапазона является экспериментальным. Я использую Rustc версии 1.76.0, это последний патч?

Umberto Fontanazza 24.03.2024 18:14

Этот синтаксис работает у меня с Rustc 1.76.0 (07dca489a 04.02.2024). Однако, если я использую .. вместо ..=, я получаю ту же ошибку, что и вы, поэтому я не использовал этот синтаксис.

bk2204 24.03.2024 18:17

Если пределы диапазона были константами, например ..=MY_CONST, это работало, но что, если следующая рука совпадения должна была быть MY_CONST + 1, я пробовал использовать круглые скобки, но они не анализировали их правильно. Попытался ли ты?

Umberto Fontanazza 24.03.2024 18:41

Оружия сопоставления @UmbertoFontanazza работают с шаблонами и константами, а не с произвольными выражениями. Так что ..=(MY_CONST + 1) не получится. Однако вы можете сделать еще одну константу.

kmdreko 24.03.2024 18:51

Другие вопросы по теме