Skip to content

Commit d2b88b7

Browse files
committed
move_ref_pattern: test captures inside closure
1 parent bd318be commit d2b88b7

File tree

2 files changed

+526
-0
lines changed

2 files changed

+526
-0
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,122 @@
1+
#![feature(move_ref_pattern)]
2+
3+
fn main() {
4+
struct S; // Not `Copy`.
5+
6+
let mut tup0 = (S, S);
7+
let mut tup1 = (S, S, S);
8+
let tup2 = (S, S);
9+
let tup3 = (S, S, S);
10+
let tup4 = (S, S);
11+
let mut arr0 = [S, S, S];
12+
let mut arr1 = [S, S, S, S, S];
13+
let arr2 = [S, S, S];
14+
let arr3 = [S, S, S, S, S];
15+
16+
// The `mov` bindings require that we capture the scrutinees by-move.
17+
let mut closure = || {
18+
// Tuples...
19+
let (ref mut borrow, mov) = tup0;
20+
let (mov, _, ref mut borrow) = tup1;
21+
let (ref borrow, mov) = tup2;
22+
let (mov, _, ref borrow) = tup3;
23+
let (ref borrow, mov) = tup4;
24+
// Arrays...
25+
let [mov @ .., ref borrow] = arr0;
26+
let [_, ref mut borrow @ .., _, mov] = arr1;
27+
let [mov @ .., ref borrow] = arr2;
28+
let [_, ref borrow @ .., _, mov] = arr3;
29+
};
30+
31+
// Now we try to borrow and move the captures, which should result in errors...
32+
// ...for tuples:
33+
drop(&tup0); //~ ERROR borrow of moved value: `tup0`
34+
drop(&tup1); //~ ERROR borrow of moved value: `tup1`
35+
drop(&tup2); //~ ERROR borrow of moved value: `tup2`
36+
drop(&tup3); //~ ERROR borrow of moved value: `tup3`
37+
// Ostensibly this should compile.
38+
// However, because closures don't capture individual fields, which is changed in RFC 2229,
39+
// this won't compile because the entire product is moved into the closure.
40+
// The same applies to the array patterns below.
41+
drop(&tup4.0); //~ ERROR borrow of moved value: `tup4`
42+
// ...for arrays:
43+
drop(&arr0); //~ ERROR borrow of moved value: `arr0`
44+
let [_, mov1, mov2, mov3, _] = &arr1; //~ ERROR borrow of moved value: `arr1`
45+
drop(&arr2); //~ ERROR borrow of moved value: `arr2`
46+
let [_, mov1, mov2, mov3, _] = &arr3; //~ ERROR borrow of moved value: `arr3`
47+
48+
// Let's redo ^--- with a `match` + sum type:
49+
macro_rules! m {
50+
($p:pat = $s:expr) => {
51+
match $s {
52+
Some($p) => {}
53+
_ => {}
54+
}
55+
};
56+
}
57+
let mut tup0: Option<(S, S)> = None;
58+
let mut tup1: Option<(S, S, S)> = None;
59+
let tup2: Option<(S, S)> = None;
60+
let tup3: Option<(S, S, S)> = None;
61+
let tup4: Option<(S, S)> = None;
62+
let mut arr0: Option<[S; 3]> = None;
63+
let mut arr1: Option<[S; 5]> = None;
64+
let arr2: Option<[S; 3]> = None;
65+
let arr3: Option<[S; 5]> = None;
66+
let mut closure = || {
67+
m!((ref mut borrow, mov) = tup0);
68+
m!((mov, _, ref mut borrow) = tup1);
69+
m!((ref borrow, mov) = tup2);
70+
m!((mov, _, ref borrow) = tup3);
71+
m!((ref borrow, mov) = tup4);
72+
m!([mov @ .., ref borrow] = arr0);
73+
m!([_, ref mut borrow @ .., _, mov] = arr1);
74+
m!([mov @ .., ref borrow] = arr2);
75+
m!([_, ref borrow @ .., _, mov] = arr3);
76+
};
77+
drop(&tup0); //~ ERROR borrow of moved value: `tup0`
78+
drop(&tup1); //~ ERROR borrow of moved value: `tup1`
79+
drop(&tup2); //~ ERROR borrow of moved value: `tup2`
80+
drop(&tup3); //~ ERROR borrow of moved value: `tup3`
81+
m!((ref x, _) = &tup4); //~ ERROR borrow of moved value: `tup4`
82+
drop(&arr0); //~ ERROR borrow of moved value: `arr0`
83+
m!([_, mov1, mov2, mov3, _] = &arr1); //~ ERROR borrow of moved value: `arr1`
84+
drop(&arr2); //~ ERROR borrow of moved value: `arr2`
85+
m!([_, mov1, mov2, mov3, _] = &arr3); //~ ERROR borrow of moved value: `arr3`
86+
87+
// Let's redo ^--- with `if let` (which may diverge from `match` in the future):
88+
macro_rules! m {
89+
($p:pat = $s:expr) => {
90+
if let Some($p) = $s {}
91+
};
92+
}
93+
let mut tup0: Option<(S, S)> = None;
94+
let mut tup1: Option<(S, S, S)> = None;
95+
let tup2: Option<(S, S)> = None;
96+
let tup3: Option<(S, S, S)> = None;
97+
let tup4: Option<(S, S)> = None;
98+
let mut arr0: Option<[S; 3]> = None;
99+
let mut arr1: Option<[S; 5]> = None;
100+
let arr2: Option<[S; 3]> = None;
101+
let arr3: Option<[S; 5]> = None;
102+
let mut closure = || {
103+
m!((ref mut borrow, mov) = tup0);
104+
m!((mov, _, ref mut borrow) = tup1);
105+
m!((ref borrow, mov) = tup2);
106+
m!((mov, _, ref borrow) = tup3);
107+
m!((ref borrow, mov) = tup4);
108+
m!([mov @ .., ref borrow] = arr0);
109+
m!([_, ref mut borrow @ .., _, mov] = arr1);
110+
m!([mov @ .., ref borrow] = arr2);
111+
m!([_, ref borrow @ .., _, mov] = arr3);
112+
};
113+
drop(&tup0); //~ ERROR borrow of moved value: `tup0`
114+
drop(&tup1); //~ ERROR borrow of moved value: `tup1`
115+
drop(&tup2); //~ ERROR borrow of moved value: `tup2`
116+
drop(&tup3); //~ ERROR borrow of moved value: `tup3`
117+
m!((ref x, _) = &tup4); //~ ERROR borrow of moved value: `tup4`
118+
drop(&arr0); //~ ERROR borrow of moved value: `arr0`
119+
m!([_, mov1, mov2, mov3, _] = &arr1); //~ ERROR borrow of moved value: `arr1`
120+
drop(&arr2); //~ ERROR borrow of moved value: `arr2`
121+
m!([_, mov1, mov2, mov3, _] = &arr3); //~ ERROR borrow of moved value: `arr3`
122+
}

0 commit comments

Comments
 (0)