graydon/rust — Issue #1170: Bogus "unreachable pattern" error with ranges
Author: elly
Created: 2011-11-11 03:37:21+00:00
State: open

This rust program:
[str-escape] ~/s/rust$ cat test.rs
use std;

import std::str;

fn escape_char(c: char) -> str {
alt c {
'"' { "\"" }
'\\' { "\\\\" }
'\n' { "\\n" }
'\t' { "\\t" }
'\r' { "\\r" }
'\x00' to '\x1f' { #fmt["\\x%02x", c as uint] }
v { str::from_char(c) }
}
}

fails to compile with this error:
test.rs:12:8: 12:24 error: unreachable pattern
test.rs:12 '\x00' to '\x1f' { #fmt["\\x%02x", c as uint] }
^~~~~~~~~~~~~~~~
error: aborting due to previous errors

Inspection suggests that the logic in pattern_supersedes() in /src/comp/middle/check_alt.rs is wrong:
alt a.node {
pat_wild. | pat_bind(_) { ret true; }
pat_lit(la) {
alt b.node {
pat_lit(lb) { ret util::common::lit_eq(la, lb); }
pat_range(beginb, endb) {
ret util::common::lit_type_eq(la, beginb) &&
util::common::lit_in_range(la, beginb, endb);
}

^ This returns true if a (a previous pattern) is contained in b (the current pattern) - i.e., this will match for alt x { 1 { ... } 1 to 10 { ... } }.