]> git.lizzy.rs Git - rust.git/commitdiff
Pointers to bound variables are stored after all patterns are matched.
authorDmitry Ermolov <epdmitry@yandex.ru>
Wed, 14 Aug 2013 21:28:49 +0000 (01:28 +0400)
committerDmitry Ermolov <epdmitry@yandex.ru>
Thu, 15 Aug 2013 22:07:21 +0000 (02:07 +0400)
Pointers to bound variables shouldn't be stored before checking pattern,
otherwise piped patterns can conflict with each other (issue #6338).

Closes #6338.

src/librustc/middle/trans/_match.rs
src/test/run-pass/match-pipe-binding.rs

index 1089fc5574487e2c21315355724c0640fa4e6d66..1eeafeacc6f05a75b395d59360ec0c572d0e94c4 100644 (file)
@@ -399,10 +399,17 @@ struct ArmData<'self> {
     bindings_map: @BindingsMap
 }
 
+/**
+ * Info about Match.
+ * If all `pats` are matched then arm `data` will be executed.
+ * As we proceed `bound_ptrs` are filled with pointers to values to be bound,
+ * these pointers are stored in llmatch variables just before executing `data` arm.
+ */
 #[deriving(Clone)]
 struct Match<'self> {
     pats: ~[@ast::pat],
-    data: ArmData<'self>
+    data: ArmData<'self>,
+    bound_ptrs: ~[(ident, ValueRef)]
 }
 
 impl<'self> Repr for Match<'self> {
@@ -447,14 +454,13 @@ fn expand_nested_bindings<'r>(bcx: @mut Block,
                                 br.pats.slice(col + 1u,
                                            br.pats.len())));
 
-                let binding_info =
-                    br.data.bindings_map.get(&path_to_ident(path));
-
-                Store(bcx, val, binding_info.llmatch);
-                Match {
+                let mut res = Match {
                     pats: pats,
-                    data: br.data.clone()
-                }
+                    data: br.data.clone(),
+                    bound_ptrs: br.bound_ptrs.clone()
+                };
+                res.bound_ptrs.push((path_to_ident(path), val));
+                res
             }
             _ => (*br).clone(),
         }
@@ -496,13 +502,11 @@ fn enter_match<'r>(bcx: @mut Block,
                         br.pats.slice(col + 1u, br.pats.len()));
 
                 let this = br.pats[col];
+                let mut bound_ptrs = br.bound_ptrs.clone();
                 match this.node {
                     ast::pat_ident(_, ref path, None) => {
                         if pat_is_binding(dm, this) {
-                            let binding_info =
-                                br.data.bindings_map.get(
-                                    &path_to_ident(path));
-                            Store(bcx, val, binding_info.llmatch);
+                            bound_ptrs.push((path_to_ident(path), val));
                         }
                     }
                     _ => {}
@@ -510,7 +514,8 @@ fn enter_match<'r>(bcx: @mut Block,
 
                 result.push(Match {
                     pats: pats,
-                    data: br.data.clone()
+                    data: br.data.clone(),
+                    bound_ptrs: bound_ptrs
                 });
             }
             None => ()
@@ -1414,6 +1419,10 @@ fn compile_submatch(bcx: @mut Block,
     }
     if m[0].pats.len() == 0u {
         let data = &m[0].data;
+        for &(ref ident, ref value_ptr) in m[0].bound_ptrs.iter() {
+            let llmatch = data.bindings_map.get(ident).llmatch;
+            Store(bcx, *value_ptr, llmatch);
+        }
         match data.arm.guard {
             Some(guard_expr) => {
                 bcx = compile_guard(bcx,
@@ -1839,6 +1848,7 @@ fn trans_match_inner(scope_cx: @mut Block,
             matches.push(Match {
                 pats: ~[*p],
                 data: arm_data.clone(),
+                bound_ptrs: ~[],
             });
         }
     }
index 02dd10b35c9a703be6d335987e81ba3553b6e157..b4933773c03e25b41bb8acdd4ff08b5f1ff6c304 100644 (file)
@@ -8,8 +8,6 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-// xfail-test
-
 fn test1() {
     // from issue 6338
     match ((1, ~"a"), (2, ~"b")) {