-
Notifications
You must be signed in to change notification settings - Fork 12.1k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add a pass that checks for unreachable alt arms
- Loading branch information
Showing
5 changed files
with
115 additions
and
2 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,102 @@ | ||
import syntax::ast::*; | ||
import syntax::visit; | ||
|
||
fn check_crate(&ty::ctxt tcx, &@crate crate) { | ||
auto v = @rec(visit_expr=bind check_expr(tcx, _, _, _) | ||
with *visit::default_visitor[()]()); | ||
visit::visit_crate(*crate, (), visit::mk_vt(v)); | ||
tcx.sess.abort_if_errors(); | ||
} | ||
|
||
fn check_expr(&ty::ctxt tcx, &@expr ex, &() s, &visit::vt[()] v) { | ||
visit::visit_expr(ex, s, v); | ||
alt ex.node { | ||
expr_alt(_, ?arms) { check_arms(tcx, arms); } | ||
_ {} | ||
} | ||
} | ||
|
||
fn check_arms(&ty::ctxt tcx, &arm[] arms) { | ||
auto i = 0; | ||
for (arm arm in arms) { | ||
for (@pat arm_pat in arm.pats) { | ||
auto reachable = true; | ||
auto j = 0; | ||
while j < i { | ||
for (@pat prev_pat in arms.(j).pats) { | ||
if pattern_supersedes(tcx, prev_pat, arm_pat) { | ||
reachable = false; | ||
} | ||
} | ||
j += 1; | ||
} | ||
if !reachable { | ||
tcx.sess.span_err(arm_pat.span, "unreachable pattern"); | ||
} | ||
} | ||
i += 1; | ||
} | ||
} | ||
|
||
fn pattern_supersedes(&ty::ctxt tcx, &@pat a, &@pat b) -> bool { | ||
fn patterns_supersede(&ty::ctxt tcx, &(@pat)[] as, &(@pat)[] bs) -> bool { | ||
auto i = 0; | ||
for (@pat a in as) { | ||
if !pattern_supersedes(tcx, a, bs.(i)) { ret false; } | ||
i += 1; | ||
} | ||
ret true; | ||
} | ||
fn field_patterns_supersede(&ty::ctxt tcx, &field_pat[] fas, | ||
&field_pat[] fbs) -> bool { | ||
auto wild = @rec(id=0, node=pat_wild, span=rec(lo=0u, hi=0u)); | ||
for (field_pat fa in fas) { | ||
auto pb = wild; | ||
for (field_pat fb in fbs) { | ||
if fa.ident == fb.ident { pb = fb.pat; } | ||
} | ||
if !pattern_supersedes(tcx, fa.pat, pb) { ret false; } | ||
} | ||
ret true; | ||
} | ||
|
||
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); } | ||
_ { ret false; } | ||
} | ||
} | ||
pat_tag(?va, ?suba) { | ||
alt b.node { | ||
pat_tag(?vb, ?subb) { | ||
ret tcx.def_map.get(a.id) == tcx.def_map.get(b.id) && | ||
patterns_supersede(tcx, suba, subb); | ||
} | ||
_ { ret false; } | ||
} | ||
} | ||
pat_rec(?suba, _) { | ||
alt b.node { | ||
pat_rec(?subb, _) { ret field_patterns_supersede(tcx, suba, subb); } | ||
_ { ret false; } | ||
} | ||
} | ||
pat_box(?suba) { | ||
alt b.node { | ||
pat_box(?subb) { ret pattern_supersedes(tcx, suba, subb); } | ||
_ { ret pattern_supersedes(tcx, suba, b); } | ||
} | ||
} | ||
} | ||
} | ||
|
||
// Local Variables: | ||
// mode: rust | ||
// fill-column: 78; | ||
// indent-tabs-mode: nil | ||
// c-basic-offset: 4 | ||
// buffer-file-coding-system: utf-8-unix | ||
// compile-command: "make -k -C $RBUILD 2>&1 | sed -e 's/\\/x\\//x:\\//g'"; | ||
// End: |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -25,6 +25,7 @@ mod middle { | |
mod ast_map; | ||
mod resolve; | ||
mod typeck; | ||
mod check_alt; | ||
mod alias; | ||
mod freevars; | ||
|
||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
// error-pattern:unreachable pattern | ||
|
||
tag foo { a(@foo, int); b(uint); } | ||
|
||
fn main() { | ||
alt b(1u) { | ||
b(_) | a(@_, 1) {} | ||
a(_, 1) {} | ||
} | ||
} |