Skip to content

Commit 9d67df6

Browse files
committed
rustc: allow @ as-patterns to move when the sub-pattern contains no bindings.
A pattern like `foo @ Foo(Bar(*), _)` should be legal, even if `foo` moves, since the subpatterns are purely structural. Fixes rust-lang#3761.
1 parent e86d414 commit 9d67df6

File tree

3 files changed

+48
-1
lines changed

3 files changed

+48
-1
lines changed

src/librustc/middle/check_match.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -879,7 +879,9 @@ pub fn check_legality_of_move_bindings(cx: &MatchCheckCtxt,
879879

880880
let check_move: &fn(@pat, Option<@pat>) = |p, sub| {
881881
// check legality of moving out of the enum
882-
if sub.is_some() {
882+
883+
// x @ Foo(*) is legal, but x @ Foo(y) isn't.
884+
if sub.map_move_default(false, |p| pat_contains_bindings(def_map, p)) {
883885
tcx.sess.span_err(
884886
p.span,
885887
"cannot bind by-move with sub-bindings");

src/librustc/middle/pat_util.rs

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,3 +88,18 @@ pub fn pat_binding_ids(dm: resolve::DefMap, pat: @pat) -> ~[NodeId] {
8888
pat_bindings(dm, pat, |_bm, b_id, _sp, _pt| found.push(b_id) );
8989
return found;
9090
}
91+
92+
/// Checks if the pattern contains any patterns that bind something to
93+
/// an ident, e.g. `foo`, or `Foo(foo)` or `foo @ Bar(*)`.
94+
pub fn pat_contains_bindings(dm: resolve::DefMap, pat: @pat) -> bool {
95+
let mut contains_bindings = false;
96+
do walk_pat(pat) |p| {
97+
if pat_is_binding(dm, p) {
98+
contains_bindings = true;
99+
false // there's at least one binding, can short circuit now.
100+
} else {
101+
true
102+
}
103+
};
104+
contains_bindings
105+
}
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
// Issue #3761
12+
13+
struct Foo(~str);
14+
15+
enum Tree {
16+
Leaf(uint),
17+
Node(~Tree, ~Tree)
18+
}
19+
20+
fn main() {
21+
match Foo(~"hi") {
22+
_msg @ Foo(_) => {}
23+
}
24+
25+
match Node(~Node(~Leaf(1), ~Leaf(2)), ~Leaf(3)) {
26+
leaf @ Leaf(*) => { fail!() }
27+
two_subnodes @ Node(~Node(*), ~Node(*)) => { fail!() }
28+
other @ Node(_, _) => { /* ok */ }
29+
}
30+
}

0 commit comments

Comments
 (0)