about summary refs log tree commit diff
path: root/src/rustc
diff options
context:
space:
mode:
authorNiko Matsakis <niko@alum.mit.edu>2012-09-23 05:39:39 -0700
committerNiko Matsakis <niko@alum.mit.edu>2012-09-23 13:30:20 -0500
commit0a26edca75a53839d63c0227d62f863dfb717e1b (patch)
tree099d68f80f0f0d32b675e0da949b8406c86f9690 /src/rustc
parentba3eebd41db384c2a46535e8db8c7b2337d55f0b (diff)
downloadrust-0a26edca75a53839d63c0227d62f863dfb717e1b.tar.gz
rust-0a26edca75a53839d63c0227d62f863dfb717e1b.zip
Fix trans for region patterns (&P)
Diffstat (limited to 'src/rustc')
-rw-r--r--src/rustc/middle/trans/alt.rs82
1 files changed, 59 insertions, 23 deletions
diff --git a/src/rustc/middle/trans/alt.rs b/src/rustc/middle/trans/alt.rs
index c7abed19c59..07727113741 100644
--- a/src/rustc/middle/trans/alt.rs
+++ b/src/rustc/middle/trans/alt.rs
@@ -487,6 +487,31 @@ fn enter_uniq(bcx: block, dm: DefMap, m: &[@Match/&r],
     }
 }
 
+fn enter_region(bcx: block, dm: DefMap, m: &[@Match/&r],
+                col: uint, val: ValueRef)
+    -> ~[@Match/&r]
+{
+    debug!("enter_region(bcx=%s, m=%s, col=%u, val=%?)",
+           bcx.to_str(),
+           matches_to_str(bcx, m),
+           col,
+           bcx.val_str(val));
+    let _indenter = indenter();
+
+    let dummy = @{id: 0, node: ast::pat_wild, span: dummy_sp()};
+    do enter_match(bcx, dm, m, col, val) |p| {
+        match p.node {
+            ast::pat_region(sub) => {
+                Some(~[sub])
+            }
+            _ => {
+                assert_is_binding_or_wild(bcx, p);
+                Some(~[dummy])
+            }
+        }
+    }
+}
+
 fn get_options(ccx: @crate_ctxt, m: &[@Match], col: uint) -> ~[Opt] {
     fn add_to_set(tcx: ty::ctxt, set: &DVec<Opt>, val: Opt) {
         if set.any(|l| opt_eq(tcx, &l, &val)) {return;}
@@ -585,34 +610,35 @@ fn root_pats_as_necessary(bcx: block, m: &[@Match],
     }
 }
 
-fn any_box_pat(m: &[@Match], col: uint) -> bool {
-    for vec::each(m) |br| {
-        match br.pats[col].node {
-          ast::pat_box(_) => return true,
-          _ => ()
-        }
+// Macro for deciding whether any of the remaining matches fit a given kind of
+// pattern.  Note that, because the macro is well-typed, either ALL of the
+// matches should fit that sort of pattern or NONE (however, some of the
+// matches may be wildcards like _ or identifiers).
+macro_rules! any_pat (
+    ($m:expr, $pattern:pat) => {
+        vec::any($m, |br| {
+            match br.pats[col].node {
+                $pattern => true,
+                _ => false
+            }
+        })
     }
-    return false;
+)
+
+fn any_box_pat(m: &[@Match], col: uint) -> bool {
+    any_pat!(m, ast::pat_box(_))
 }
 
 fn any_uniq_pat(m: &[@Match], col: uint) -> bool {
-    for vec::each(m) |br| {
-        match br.pats[col].node {
-          ast::pat_uniq(_) => return true,
-          _ => ()
-        }
-    }
-    return false;
+    any_pat!(m, ast::pat_uniq(_))
+}
+
+fn any_region_pat(m: &[@Match], col: uint) -> bool {
+    any_pat!(m, ast::pat_region(_))
 }
 
 fn any_tup_pat(m: &[@Match], col: uint) -> bool {
-    for vec::each(m) |br| {
-        match br.pats[col].node {
-          ast::pat_tup(_) => return true,
-          _ => ()
-        }
-    }
-    return false;
+    any_pat!(m, ast::pat_tup(_))
 }
 
 type mk_fail = fn@() -> BasicBlockRef;
@@ -940,6 +966,13 @@ fn compile_submatch(bcx: block,
         return;
     }
 
+    if any_region_pat(m, col) {
+        let loaded_val = Load(bcx, val);
+        compile_submatch(bcx, enter_region(bcx, dm, m, col, val),
+                         vec::append(~[loaded_val], vals_left), chk);
+        return;
+    }
+
     // Decide what kind of branch we need
     let opts = get_options(ccx, m, col);
     let mut kind = no_branch;
@@ -1248,12 +1281,15 @@ fn bind_irrefutable_pat(bcx: block, pat: @ast::pat, val: ValueRef,
                 bcx = bind_irrefutable_pat(bcx, *elem, fldptr, make_copy);
             }
         }
-        ast::pat_box(inner) | ast::pat_uniq(inner) |
-        ast::pat_region(inner) => {
+        ast::pat_box(inner) | ast::pat_uniq(inner) => {
             let llbox = Load(bcx, val);
             let unboxed = GEPi(bcx, llbox, [0u, abi::box_field_body]);
             bcx = bind_irrefutable_pat(bcx, inner, unboxed, true);
         }
+        ast::pat_region(inner) => {
+            let loaded_val = Load(bcx, val);
+            bcx = bind_irrefutable_pat(bcx, inner, loaded_val, true);
+        }
         ast::pat_wild | ast::pat_lit(_) | ast::pat_range(_, _) => ()
     }
     return bcx;