匹配表达落下?

时间:2015-06-12 17:24:07

标签: pattern-matching rust

更新:这是1.12

中的旧错误solved

这是一些人为但简单的模式匹配示例(demo)

fn main() {
    let x = 'a';

    match x {
            'a'...'b' if false => {
                println!("one");
            },

            'a' => {
                println!("two");
            },

            'a'...'b' => {
                println!("three");
            },

            _ => panic!("what?")
    }
}

当我运行它时,我得到three作为输出。为什么会这样?第二个分支不应该先匹配吗?

1 个答案:

答案 0 :(得分:4)

查看Debug中的LLVM IR,它已经存在缺陷,所以这绝对是rustc中的一个错误。我们将使用下面的策划红外线来检查发生了什么。

因此,%x被指定为'a'(ASCII为97),%10被赋予x >= 'a' and x <= 'b'的结果;如果是这样,我们转到match_case,否则转到compare_nextmatch_case重定向到cond,重定向到case_body2打印"three"

从理论上讲,我们原本希望从case_body1"two"cond7转到match_case4(打印compare_next)。但compare_next只有在x根据IR不在['a', 'b']时才会到达。

这显然看起来像个错误。

; 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

; [...]
}