Is this a bug in the matches! macro?

Hey there,

I don't understand this error, had a look a the issue but couldn't figure out anything from it. Is there a reason for it I'm not getting or is this just a bug with the macro ?

use std::ops::Range;

enum Foo {
    A(Range<usize>),
    B(Range<usize>)
}

fn main () {
    let foo = Foo::A(1..2);
    assert!(matches!(foo, Foo::A(1..2)));
}

The error:

error[E0658]: exclusive range pattern syntax is experimental
  --> src/main.rs:10:34
   |
10 |     assert!(matches!(foo, Foo::A(1..2)));
   |                                  ^^^^
   |
   = note: see issue #37854 <https://github.com/rust-lang/rust/issues/37854> for more information

error[E0308]: mismatched types
  --> src/main.rs:10:34
   |
10 |     assert!(matches!(foo, Foo::A(1..2)));
   |                      ---         ^  - this is of type `{integer}`
   |                      |           |
   |                      |           expected `Range<usize>`, found integer
   |                      this expression has type `Foo`
   |
   = note: expected struct `std::ops::Range<usize>`
                found type `{integer}`

error[E0308]: mismatched types
  --> src/main.rs:10:37
   |
10 |     assert!(matches!(foo, Foo::A(1..2)));
   |                      ---         -  ^ expected `Range<usize>`, found integer
   |                      |           |
   |                      |           this is of type `{integer}`
   |                      this expression has type `Foo`
   |
   = note: expected struct `std::ops::Range<usize>`
                found type `{integer}`

Oh ! I just realized what's going on ! Its pattern matching, obviously :man_facepalming:

fn main () {
    let foo = Foo::A(1..2);
    assert!(matches!(foo, Foo::A(..)));
}

start..end in a pattern means "the matched value is in the range [start, end)". It does not mean that "the value is an std::ops::Range { start, end }".

If you want to match a literal Range, you have to use its constructor, just like with any other UDT:

assert!(matches!(foo, Foo::A(Range { start: 1, end: 2 })));

Also, the .. syntax is nightly-only, as the compiler points it out, but that's beside the point here. You can always use start..=(end-1) instead, which is already stable.

1 Like