| //@ edition:2015..2021 | |
| 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` | |
| } |