| fn main() { |
| struct S; // Not `Copy`. |
| |
| let mut tup0 = (S, S); |
| let mut tup1 = (S, S, S); |
| let tup2 = (S, S); |
| let tup3 = (S, S, S); |
| let tup4 = (S, S); |
| let mut arr0 = [S, S, S]; |
| let mut arr1 = [S, S, S, S, S]; |
| let arr2 = [S, S, S]; |
| let arr3 = [S, S, S, S, S]; |
| |
| // The `mov` bindings require that we capture the scrutinees by-move. |
| let mut closure = || { |
| // Tuples... |
| let (ref mut borrow, mov) = tup0; |
| let (mov, _, ref mut borrow) = tup1; |
| let (ref borrow, mov) = tup2; |
| let (mov, _, ref borrow) = tup3; |
| let (ref borrow, mov) = tup4; |
| // Arrays... |
| let [mov @ .., ref borrow] = arr0; |
| let [_, ref mut borrow @ .., _, mov] = arr1; |
| let [mov @ .., ref borrow] = arr2; |
| let [_, ref borrow @ .., _, mov] = arr3; |
| }; |
| |
| // Now we try to borrow and move the captures, which should result in errors... |
| // ...for tuples: |
| drop(&tup0); //~ ERROR borrow of moved value: `tup0` |
| drop(&tup1); //~ ERROR borrow of moved value: `tup1` |
| drop(&tup2); //~ ERROR borrow of moved value: `tup2` |
| drop(&tup3); //~ ERROR borrow of moved value: `tup3` |
| // Ostensibly this should compile. |
| // However, because closures don't capture individual fields, which is changed in RFC 2229, |
| // this won't compile because the entire product is moved into the closure. |
| // The same applies to the array patterns below. |
| drop(&tup4.0); //~ ERROR borrow of moved value: `tup4` |
| // ...for arrays: |
| drop(&arr0); //~ ERROR borrow of moved value: `arr0` |
| let [_, mov1, mov2, mov3, _] = &arr1; //~ ERROR borrow of moved value: `arr1` |
| drop(&arr2); //~ ERROR borrow of moved value: `arr2` |
| let [_, mov1, mov2, mov3, _] = &arr3; //~ ERROR borrow of moved value: `arr3` |
| |
| // Let's redo ^--- with a `match` + sum type: |
| macro_rules! m { |
| ($p:pat = $s:expr) => { |
| match $s { |
| Some($p) => {} |
| _ => {} |
| } |
| }; |
| } |
| let mut tup0: Option<(S, S)> = None; |
| let mut tup1: Option<(S, S, S)> = None; |
| let tup2: Option<(S, S)> = None; |
| let tup3: Option<(S, S, S)> = None; |
| let tup4: Option<(S, S)> = None; |
| let mut arr0: Option<[S; 3]> = None; |
| let mut arr1: Option<[S; 5]> = None; |
| let arr2: Option<[S; 3]> = None; |
| let arr3: Option<[S; 5]> = None; |
| let mut closure = || { |
| m!((ref mut borrow, mov) = tup0); |
| m!((mov, _, ref mut borrow) = tup1); |
| m!((ref borrow, mov) = tup2); |
| m!((mov, _, ref borrow) = tup3); |
| m!((ref borrow, mov) = tup4); |
| m!([mov @ .., ref borrow] = arr0); |
| m!([_, ref mut borrow @ .., _, mov] = arr1); |
| m!([mov @ .., ref borrow] = arr2); |
| m!([_, ref borrow @ .., _, mov] = arr3); |
| }; |
| drop(&tup0); //~ ERROR borrow of moved value: `tup0` |
| drop(&tup1); //~ ERROR borrow of moved value: `tup1` |
| drop(&tup2); //~ ERROR borrow of moved value: `tup2` |
| drop(&tup3); //~ ERROR borrow of moved value: `tup3` |
| m!((ref x, _) = &tup4); //~ ERROR borrow of moved value: `tup4` |
| drop(&arr0); //~ ERROR borrow of moved value: `arr0` |
| m!([_, mov1, mov2, mov3, _] = &arr1); //~ ERROR borrow of moved value: `arr1` |
| drop(&arr2); //~ ERROR borrow of moved value: `arr2` |
| m!([_, mov1, mov2, mov3, _] = &arr3); //~ ERROR borrow of moved value: `arr3` |
| |
| // Let's redo ^--- with `if let` (which may diverge from `match` in the future): |
| macro_rules! m { |
| ($p:pat = $s:expr) => { |
| if let Some($p) = $s {} |
| }; |
| } |
| let mut tup0: Option<(S, S)> = None; |
| let mut tup1: Option<(S, S, S)> = None; |
| let tup2: Option<(S, S)> = None; |
| let tup3: Option<(S, S, S)> = None; |
| let tup4: Option<(S, S)> = None; |
| let mut arr0: Option<[S; 3]> = None; |
| let mut arr1: Option<[S; 5]> = None; |
| let arr2: Option<[S; 3]> = None; |
| let arr3: Option<[S; 5]> = None; |
| let mut closure = || { |
| m!((ref mut borrow, mov) = tup0); |
| m!((mov, _, ref mut borrow) = tup1); |
| m!((ref borrow, mov) = tup2); |
| m!((mov, _, ref borrow) = tup3); |
| m!((ref borrow, mov) = tup4); |
| m!([mov @ .., ref borrow] = arr0); |
| m!([_, ref mut borrow @ .., _, mov] = arr1); |
| m!([mov @ .., ref borrow] = arr2); |
| m!([_, ref borrow @ .., _, mov] = arr3); |
| }; |
| drop(&tup0); //~ ERROR borrow of moved value: `tup0` |
| drop(&tup1); //~ ERROR borrow of moved value: `tup1` |
| drop(&tup2); //~ ERROR borrow of moved value: `tup2` |
| drop(&tup3); //~ ERROR borrow of moved value: `tup3` |
| m!((ref x, _) = &tup4); //~ ERROR borrow of moved value: `tup4` |
| drop(&arr0); //~ ERROR borrow of moved value: `arr0` |
| m!([_, mov1, mov2, mov3, _] = &arr1); //~ ERROR borrow of moved value: `arr1` |
| drop(&arr2); //~ ERROR borrow of moved value: `arr2` |
| m!([_, mov1, mov2, mov3, _] = &arr3); //~ ERROR borrow of moved value: `arr3` |
| } |