From 6d95765cd2a897f5145014d39de87c465395272d Mon Sep 17 00:00:00 2001 From: Dmitry Ermolov Date: Sun, 11 Aug 2013 02:26:40 +0400 Subject: [PATCH 1/3] Cleanup: remove useless parameter --- src/librustc/middle/trans/_match.rs | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/src/librustc/middle/trans/_match.rs b/src/librustc/middle/trans/_match.rs index bb1e3fa1718dc..1089fc5574487 100644 --- a/src/librustc/middle/trans/_match.rs +++ b/src/librustc/middle/trans/_match.rs @@ -1294,7 +1294,6 @@ fn store_non_ref_bindings(bcx: @mut Block, fn insert_lllocals(bcx: @mut Block, bindings_map: &BindingsMap, - binding_mode: IrrefutablePatternBindingMode, add_cleans: bool) -> @mut Block { /*! * For each binding in `data.bindings_map`, adds an appropriate entry into @@ -1302,10 +1301,7 @@ fn insert_lllocals(bcx: @mut Block, * the bindings. */ - let llmap = match binding_mode { - BindLocal => bcx.fcx.lllocals, - BindArgument => bcx.fcx.llargs - }; + let llmap = bcx.fcx.lllocals; for (&ident, &binding_info) in bindings_map.iter() { let llval = match binding_info.trmode { @@ -1358,7 +1354,7 @@ fn compile_guard(bcx: @mut Block, bcx = store_non_ref_bindings(bcx, data.bindings_map, Some(&mut temp_cleanups)); - bcx = insert_lllocals(bcx, data.bindings_map, BindLocal, false); + bcx = insert_lllocals(bcx, data.bindings_map, false); let val = unpack_result!(bcx, { do with_scope_result(bcx, guard_expr.info(), @@ -1875,7 +1871,7 @@ fn trans_match_inner(scope_cx: @mut Block, } // insert bindings into the lllocals map and add cleanups - bcx = insert_lllocals(bcx, arm_data.bindings_map, BindLocal, true); + bcx = insert_lllocals(bcx, arm_data.bindings_map, true); bcx = controlflow::trans_block(bcx, &arm_data.arm.body, dest); bcx = trans_block_cleanups(bcx, block_cleanups(arm_data.bodycx)); From 6365c4ac5f81210ee6921484736b398244646381 Mon Sep 17 00:00:00 2001 From: Dmitry Ermolov Date: Fri, 16 Aug 2013 00:56:04 +0400 Subject: [PATCH 2/3] Test for issue #6338. --- src/test/run-pass/match-pipe-binding.rs | 70 +++++++++++++++++++++++++ 1 file changed, 70 insertions(+) create mode 100644 src/test/run-pass/match-pipe-binding.rs diff --git a/src/test/run-pass/match-pipe-binding.rs b/src/test/run-pass/match-pipe-binding.rs new file mode 100644 index 0000000000000..02dd10b35c9a7 --- /dev/null +++ b/src/test/run-pass/match-pipe-binding.rs @@ -0,0 +1,70 @@ +// Copyright 2013 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// 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")) { + ((1, a), (2, b)) | ((2, b), (1, a)) => { + assert_eq!(a, ~"a"); + assert_eq!(b, ~"b"); + }, + _ => fail!(), + } +} + +fn test2() { + match (1, 2, 3) { + (1, a, b) | (2, b, a) => { + assert_eq!(a, 2); + assert_eq!(b, 3); + }, + _ => fail!(), + } +} + +fn test3() { + match (1, 2, 3) { + (1, ref a, ref b) | (2, ref b, ref a) => { + assert_eq!(*a, 2); + assert_eq!(*b, 3); + }, + _ => fail!(), + } +} + +fn test4() { + match (1, 2, 3) { + (1, a, b) | (2, b, a) if a == 2 => { + assert_eq!(a, 2); + assert_eq!(b, 3); + }, + _ => fail!(), + } +} + +fn test5() { + match (1, 2, 3) { + (1, ref a, ref b) | (2, ref b, ref a) if *a == 2 => { + assert_eq!(*a, 2); + assert_eq!(*b, 3); + }, + _ => fail!(), + } +} + +fn main() { + test1(); + test2(); + test3(); + test4(); + test5(); +} From f4b88547ad8233c69f024b67e0a6bbd98b28c6e1 Mon Sep 17 00:00:00 2001 From: Dmitry Ermolov Date: Thu, 15 Aug 2013 01:28:49 +0400 Subject: [PATCH 3/3] Pointers to bound variables are stored after all patterns are matched. 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 | 36 ++++++++++++++++--------- src/test/run-pass/match-pipe-binding.rs | 2 -- 2 files changed, 23 insertions(+), 15 deletions(-) diff --git a/src/librustc/middle/trans/_match.rs b/src/librustc/middle/trans/_match.rs index 1089fc5574487..1eeafeacc6f05 100644 --- a/src/librustc/middle/trans/_match.rs +++ b/src/librustc/middle/trans/_match.rs @@ -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: ~[], }); } } diff --git a/src/test/run-pass/match-pipe-binding.rs b/src/test/run-pass/match-pipe-binding.rs index 02dd10b35c9a7..b4933773c03e2 100644 --- a/src/test/run-pass/match-pipe-binding.rs +++ b/src/test/run-pass/match-pipe-binding.rs @@ -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")) {