Right hand side of range in parenthesis is unaccepted?

#1

I have a minimal example:

fn main() {
    let foo = 32;
    match foo {
        0..(255) => {},
        _ => {}
    }
}

Playground
I feel as if this should be accepted (it is not, look at the playground link), as I have done this before with similar cases; I have a rhs of a range that is more complicated than an identifier, and needs to be an expression, so I use parenthesis around it.
On the other hand, this works just fine with for loops

fn main() {
    for _ in 0..(255) {}
}

Playground
Why is the above in the match statement not accepted?

#2

Why would you want parentheses? I don’t think more complicated expressions are legal in a match arm. I think you’re limited to literals.

See https://doc.rust-lang.org/reference/expressions/match-expr.html

And https://doc.rust-lang.org/reference/patterns.html#range-patterns

1 Like
#3

I’m on mobile so sorry for the low quality post.
I actually have a constant RHS, u8::max_value() as u64 to be exact. This should be okay in the eyes of the compiler as it still is a constant.

#4

The RangePattern's syntax is

     RangePatternBound ..= RangePatternBound
   | RangePatternBound ... RangePatternBound

And RangePatternBound is

     CHAR_LITERAL
   | BYTE_LITERAL
   | -? INTEGER_LITERAL
   | -? FLOAT_LITERAL
   | PathInExpression
   | QualifiedPathInExpression

So, it looks to me like only literals are allowed on either side of the ..= or ....

There’s PathInExpression and QualifiedPathInExpression, but no GroupedExpression. I think that explains why no parentheses.

1 Like
#5

I imagine this will be legal as Rust’s const support improves. In theory u8::max_value() is a const expression so the compiler should be able to deal with it, but maybe the parser/language syntax hasn’t caught up yet?

#6

The fundamental problem is that patterns are not expressions. Patterns are semantically the inverse of expressions: instead of constructing values, they deconstruct them. If function call-looking things were allowed, I’d expect them to be “pattern functions”.

On a semi-related note: I’ve thought before that it would be nice to have a general-purpose const { ... } construct that forces constant evaluation of an expression. If we had that, it would be unambigous to allow that in patterns as a “compute this, then match against it” construct.

4 Likes
#7

Yep, I think you are stuck with

pub
enum ToU8Error {
    Truncated(pub T),
    Negative,
}

fn try_to_u8 (foo: i32) -> Result<u8, ToU8Error<u8>>
{
    const MAXU8: i32 = core::u8::MAX as i32;
    match foo {
        n if {0 <= n && n <= MAXU8} => Ok(n as u8),
        n if {n < 0} => Err(ToU8Error::Negative),
        _ => Err(ToU8Error::Truncated(foo as u8)),
    }
}

for the general case, but for const expressions you can avoid needing parenthesis by definin the constant in advance:

fn main ()
{
    let foo = 32;
    const U8MAX: u64 = u8::max_value() as u64;
    match foo {
        0 ..= U8MAX => {},
        _ => {}
    }
}
1 Like
#8

See Quick Thought: const{} blocks in IRLO.

1 Like