Update: this is an old bug solved in 1.12
Here is some contrived but simple pattern matching example (demo):
fn main() {
let x = 'a';
match x {
'a'...'b' if false => {
println!("one");
},
'a' => {
println!("two");
},
'a'...'b' => {
println!("three");
},
_ => panic!("what?")
}
}
When I run it, I get three
as output. Why is this happening? Shouldn't the second branch match first?
: to fail or stop in a sudden or final way Contract negotiations have fallen through. Our vacation plans have fallen through.
A match expression branches on a pattern. The exact form of matching that occurs depends on the pattern. A match expression has a scrutinee expression, which is the value to compare to the patterns. The scrutinee expression and the patterns must have the same type.
: to fail to be noticed, assisted, or included with others Parents are concerned that children who have trouble in school will fall through the cracks in the school system. The program is meant to help workers who may have slipped through the cracks because of their age.
The expressions fall through the cracks and slip through the cracks came into use in the mid-twentieth century. The exact origin is unknown, but it reflects the idea that something that should have been contained or captured somehow seeped away, unnoticed.
Looking at the LLVM IR in Debug, it is already flawed, so this is definitely a bug in rustc
; we'll use the curated IR below to check what's going on.
So, %x
is assigned 'a' (97 in ASCII), and %10
is assigned the result of x >= 'a' and x <= 'b'
; if this is true, we go to match_case
, otherwise to compare_next
. match_case
redirect to cond
, which redirects to case_body2
which prints "three"
.
In theory, we would have wanted to go to case_body1
(printing "two"
), from cond7
, from match_case4
, from compare_next
. But compare_next
is only reached if x
is not in ['a', 'b']
according to the IR.
This clearly looks like a bug.
; Function Attrs: uwtable
define internal void @_ZN4main20h4f7b0d7962de19d8eaaE() unnamed_addr #0 {
entry-block:
%x = alloca i32
; [...]
store i32 97, i32* %x
%7 = load i32* %x, !range !0
%8 = icmp uge i32 %7, 97
%9 = icmp ule i32 %7, 98
%10 = and i1 %8, %9
br i1 %10, label %match_case, label %compare_next
case_body: ; preds = %next6, %next
; println!("one")
br label %case_body8
case_body1: ; preds = %cond7
; println!("two")
br label %case_body10
case_body2: ; preds = %cond
; println!("three")
br label %case_body15
case_body3: ; preds = %match_else
; panic!("what")
unreachable
match_else: ; preds = %compare_next5
br label %case_body3
match_case: ; preds = %entry-block
br i1 true, label %cond, label %next
compare_next: ; preds = %entry-block
%16 = icmp eq i32 %7, 97
br i1 %16, label %match_case4, label %compare_next5
next: ; preds = %match_case
br label %case_body
cond: ; preds = %match_case
br label %case_body2
match_case4: ; preds = %compare_next
br i1 true, label %cond7, label %next6
; [...]
cond7: ; preds = %match_case4
br label %case_body1
; [...]
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With