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 #3761.
This commit is contained in:
parent
ac49e65611
commit
58021be454
2 changed files with 18 additions and 1 deletions
|
@ -879,7 +879,9 @@ pub fn check_legality_of_move_bindings(cx: &MatchCheckCtxt,
|
||||||
|
|
||||||
let check_move: &fn(@pat, Option<@pat>) = |p, sub| {
|
let check_move: &fn(@pat, Option<@pat>) = |p, sub| {
|
||||||
// check legality of moving out of the enum
|
// check legality of moving out of the enum
|
||||||
if sub.is_some() {
|
|
||||||
|
// x @ Foo(*) is legal, but x @ Foo(y) isn't.
|
||||||
|
if sub.map_move_default(false, |p| pat_contains_bindings(def_map, p)) {
|
||||||
tcx.sess.span_err(
|
tcx.sess.span_err(
|
||||||
p.span,
|
p.span,
|
||||||
"cannot bind by-move with sub-bindings");
|
"cannot bind by-move with sub-bindings");
|
||||||
|
|
|
@ -88,3 +88,18 @@ pub fn pat_binding_ids(dm: resolve::DefMap, pat: @pat) -> ~[NodeId] {
|
||||||
pat_bindings(dm, pat, |_bm, b_id, _sp, _pt| found.push(b_id) );
|
pat_bindings(dm, pat, |_bm, b_id, _sp, _pt| found.push(b_id) );
|
||||||
return found;
|
return found;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Checks if the pattern contains any patterns that bind something to
|
||||||
|
/// an ident, e.g. `foo`, or `Foo(foo)` or `foo @ Bar(*)`.
|
||||||
|
pub fn pat_contains_bindings(dm: resolve::DefMap, pat: @pat) -> bool {
|
||||||
|
let mut contains_bindings = false;
|
||||||
|
do walk_pat(pat) |p| {
|
||||||
|
if pat_is_binding(dm, p) {
|
||||||
|
contains_bindings = true;
|
||||||
|
false // there's at least one binding, can short circuit now.
|
||||||
|
} else {
|
||||||
|
true
|
||||||
|
}
|
||||||
|
};
|
||||||
|
contains_bindings
|
||||||
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue