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.
This commit is contained in:
Dmitry Ermolov 2013-08-15 01:28:49 +04:00
parent 6365c4ac5f
commit f4b88547ad
2 changed files with 23 additions and 15 deletions

View 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: ~[],
});
}
}

View 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")) {