Add check for irrefutable patterns in destructuring locals

This commit is contained in:
Marijn Haverbeke 2011-08-01 15:26:48 +02:00
parent 985c32ef4c
commit 92240eb25b
2 changed files with 35 additions and 4 deletions

View File

@ -3,8 +3,9 @@ import syntax::visit;
fn check_crate(tcx: &ty::ctxt, crate: &@crate) {
let v =
@{visit_expr: bind check_expr(tcx, _, _, _)
with *visit::default_visitor[()]()};
@{visit_expr: bind check_expr(tcx, _, _, _),
visit_local: bind check_local(tcx, _, _, _)
with *visit::default_visitor[()]()};
visit::visit_crate(*crate, (), visit::mk_vt(v));
tcx.sess.abort_if_errors();
}
@ -92,6 +93,38 @@ fn pattern_supersedes(tcx: &ty::ctxt, a: &@pat, b: &@pat) -> bool {
}
}
fn check_local(tcx: &ty::ctxt, loc: &@local, s: &(), v: &visit::vt[()]) {
visit::visit_local(loc, s, v);
if is_refutable(tcx, loc.node.pat) {
tcx.sess.span_err(loc.node.pat.span,
"refutable pattern in local binding");
}
}
fn is_refutable(tcx: &ty::ctxt, pat: &@pat) -> bool {
alt pat.node {
pat_wild. | pat_bind(_) { ret false; }
pat_lit(_) { ret true; }
pat_box(sub) { ret is_refutable(tcx, sub); }
pat_rec(fields, _) {
for field: field_pat in fields {
if is_refutable(tcx, field.pat) { ret true; }
}
ret false;
}
pat_tag(_, args) {
let vdef = variant_def_ids(tcx.def_map.get(pat.id));
if std::ivec::len(ty::tag_variants(tcx, vdef.tg)) != 1u {
ret true;
}
for p: @pat in args {
if is_refutable(tcx, p) { ret true; }
}
ret false;
}
}
}
// Local Variables:
// mode: rust
// fill-column: 78;

View File

@ -1198,8 +1198,6 @@ fn gather_locals(ccx: &@crate_ctxt, f: &ast::_fn, id: &ast::node_id,
local_names: &hashmap[ast::node_id, ast::ident],
nvi: @mutable int, nid: ast::node_id, ident: &ast::ident,
ty_opt: option::t[ty::t]) {
// FIXME DESTR
if locals.contains_key(nid) { ret; }
let var_id = next_var_id(nvi);
locals.insert(nid, var_id);
local_names.insert(nid, ident);