about summary refs log tree commit diff
path: root/src/comp/middle
diff options
context:
space:
mode:
authorMarijn Haverbeke <marijnh@gmail.com>2011-08-01 15:26:48 +0200
committerMarijn Haverbeke <marijnh@gmail.com>2011-08-01 17:52:43 +0200
commit92240eb25bdbe2a63864169d7d6a49b2fc6bed8e (patch)
treeb62264ecb7b3925f5057000eb888b3e855b6061e /src/comp/middle
parent985c32ef4c930cdfba23db2191014d772c354407 (diff)
downloadrust-92240eb25bdbe2a63864169d7d6a49b2fc6bed8e.tar.gz
rust-92240eb25bdbe2a63864169d7d6a49b2fc6bed8e.zip
Add check for irrefutable patterns in destructuring locals
Diffstat (limited to 'src/comp/middle')
-rw-r--r--src/comp/middle/check_alt.rs37
-rw-r--r--src/comp/middle/typeck.rs2
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);