From 92240eb25bdbe2a63864169d7d6a49b2fc6bed8e Mon Sep 17 00:00:00 2001 From: Marijn Haverbeke Date: Mon, 1 Aug 2011 15:26:48 +0200 Subject: [PATCH] Add check for irrefutable patterns in destructuring locals --- src/comp/middle/check_alt.rs | 37 ++++++++++++++++++++++++++++++++++-- src/comp/middle/typeck.rs | 2 -- 2 files changed, 35 insertions(+), 4 deletions(-) diff --git a/src/comp/middle/check_alt.rs b/src/comp/middle/check_alt.rs index 5c9b9e9b048..c0053ecc56d 100644 --- a/src/comp/middle/check_alt.rs +++ b/src/comp/middle/check_alt.rs @@ -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; diff --git a/src/comp/middle/typeck.rs b/src/comp/middle/typeck.rs index 84482ce46cf..07dfedad6c0 100644 --- a/src/comp/middle/typeck.rs +++ b/src/comp/middle/typeck.rs @@ -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);