Я новичок в 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!(),
|
Да, но это сделает код менее читабельным, как это обойти?
Я не думаю, что код станет менее читабельным, если не будет предоставлять избыточную информацию, особенно если вы измените второй случай на x if x < 20
Я думаю, это сделает случаи более понятными, поскольку предыдущий случай уже обеспечивает нижнюю границу принятого диапазона.
Вы можете добавить _ => unreachable!()
, см. doc.rust-lang.org/std/macro.unreachable.html#examples
Просто используйте 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, это последний патч?
Этот синтаксис работает у меня с Rustc 1.76.0 (07dca489a 04.02.2024). Однако, если я использую ..
вместо ..=
, я получаю ту же ошибку, что и вы, поэтому я не использовал этот синтаксис.
Если пределы диапазона были константами, например ..=MY_CONST, это работало, но что, если следующая рука совпадения должна была быть MY_CONST + 1, я пробовал использовать круглые скобки, но они не анализировали их правильно. Попытался ли ты?
Оружия сопоставления @UmbertoFontanazza работают с шаблонами и константами, а не с произвольными выражениями. Так что ..=(MY_CONST + 1)
не получится. Однако вы можете сделать еще одну константу.
В целях проверки полноты компилятор всегда рассматривает охранники
if
как потенциально несовпадающие. Вы можете просто опустить защиту последней руки, если она всегда совпадает.