匹配表达式未能匹配成功?

11

жӣҙж–°пјҡиҝҷжҳҜдёҖдёӘж—§зҡ„жјҸжҙһпјҢе·ІеңЁ1.12дёӯи§ЈеҶі


иҝҷйҮҢжңүдёҖдёӘдәәдёәеҲ¶йҖ зҡ„дҪҶз®ҖеҚ•зҡ„жЁЎејҸеҢ№й…ҚзӨәдҫӢпјҲжј”зӨәпјүпјҡ

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

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

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

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

            _ => panic!("what?")
    }
}
当我运行它时,输出结果是three。为什么会这样?第二个分支不应该先匹配吗?

哦,看起来像是个bug。如果你注释掉任意一个带有...的匹配分支,它都会匹配到"two",即使你在"two"之后注释掉了该匹配分支。这只是纯粹的猜测,我想知道是否存在某些不正确的优化,将两个范围合并在一起,并使它们首先触发。如果你将第一个范围更改为'a'...'c',那么"two"也会匹配上... - Shepmaster
我打开了一个错误报告 - rvidal
1个回答

4
在 Debug 模式下查看 LLVM IR,它已经存在缺陷,因此这肯定是 rustc 的一个 bug;我们将使用下面的精选 IR 来检查发生了什么。
因此,%x 被赋值为 'a'(在 ASCII 中是97),%10 被赋值为 x >= 'a' and x <= 'b' 的结果;如果为真,则跳转到 match_case,否则跳转到 compare_nextmatch_case 重定向到 cond,然后重定向到 case_body2,并打印出 "three"
理论上,我们本应从 compare_next 中从 match_case4cond7 跳转到 case_body1(打印 "two")。但是根据 IR,只有当 x 不在 ['a', 'b'] 中时才会到达 compare_next
这显然是一个 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

; [...]
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接