]>
Commit | Line | Data |
---|---|---|
416331ca XL |
1 | // run-pass |
2 | ||
0bf4aa26 XL |
3 | #![allow(non_camel_case_types)] |
4 | #![allow(stable_features)] | |
1a4d82fc JJ |
5 | // Issue 4691: Ensure that functional-struct-updates operates |
6 | // correctly and moves rather than copy when appropriate. | |
7 | ||
c295e0f8 | 8 | #![feature(core)] |
1a4d82fc | 9 | |
e9174d1e SL |
10 | struct ncint { v: isize } |
11 | fn ncint(v: isize) -> ncint { ncint { v: v } } | |
1a4d82fc | 12 | |
c34b1796 | 13 | struct NoFoo { copied: isize, nocopy: ncint, } |
1a4d82fc | 14 | impl NoFoo { |
c34b1796 | 15 | fn new(x:isize,y:isize) -> NoFoo { NoFoo { copied: x, nocopy: ncint(y) } } |
1a4d82fc JJ |
16 | } |
17 | ||
c34b1796 | 18 | struct MoveFoo { copied: isize, moved: Box<isize>, } |
1a4d82fc | 19 | impl MoveFoo { |
c295e0f8 | 20 | fn new(x:isize,y:isize) -> MoveFoo { MoveFoo { copied: x, moved: Box::new(y) } } |
1a4d82fc JJ |
21 | } |
22 | ||
23 | struct DropNoFoo { inner: NoFoo } | |
24 | impl DropNoFoo { | |
c34b1796 | 25 | fn new(x:isize,y:isize) -> DropNoFoo { DropNoFoo { inner: NoFoo::new(x,y) } } |
1a4d82fc JJ |
26 | } |
27 | impl Drop for DropNoFoo { fn drop(&mut self) { } } | |
28 | ||
29 | struct DropMoveFoo { inner: MoveFoo } | |
30 | impl DropMoveFoo { | |
c34b1796 | 31 | fn new(x:isize,y:isize) -> DropMoveFoo { DropMoveFoo { inner: MoveFoo::new(x,y) } } |
1a4d82fc JJ |
32 | } |
33 | impl Drop for DropMoveFoo { fn drop(&mut self) { } } | |
34 | ||
35 | ||
36 | fn test0() { | |
37 | // just copy implicitly copyable fields from `f`, no moves | |
38 | // (and thus it is okay that these are Drop; compare against | |
5869c6ff | 39 | // test ui/borrowck/borrowck-struct-update-with-dtor.rs). |
1a4d82fc JJ |
40 | |
41 | // Case 1: Nocopyable | |
42 | let f = DropNoFoo::new(1, 2); | |
43 | let b = DropNoFoo { inner: NoFoo { nocopy: ncint(3), ..f.inner }}; | |
44 | let c = DropNoFoo { inner: NoFoo { nocopy: ncint(4), ..f.inner }}; | |
45 | assert_eq!(f.inner.copied, 1); | |
46 | assert_eq!(f.inner.nocopy.v, 2); | |
47 | ||
48 | assert_eq!(b.inner.copied, 1); | |
49 | assert_eq!(b.inner.nocopy.v, 3); | |
50 | ||
51 | assert_eq!(c.inner.copied, 1); | |
52 | assert_eq!(c.inner.nocopy.v, 4); | |
53 | ||
54 | // Case 2: Owned | |
55 | let f = DropMoveFoo::new(5, 6); | |
c295e0f8 XL |
56 | let b = DropMoveFoo { inner: MoveFoo { moved: Box::new(7), ..f.inner }}; |
57 | let c = DropMoveFoo { inner: MoveFoo { moved: Box::new(8), ..f.inner }}; | |
1a4d82fc JJ |
58 | assert_eq!(f.inner.copied, 5); |
59 | assert_eq!(*f.inner.moved, 6); | |
60 | ||
61 | assert_eq!(b.inner.copied, 5); | |
62 | assert_eq!(*b.inner.moved, 7); | |
63 | ||
64 | assert_eq!(c.inner.copied, 5); | |
65 | assert_eq!(*c.inner.moved, 8); | |
66 | } | |
67 | ||
68 | fn test1() { | |
69 | // copying move-by-default fields from `f`, so it moves: | |
70 | let f = MoveFoo::new(11, 12); | |
71 | ||
c295e0f8 | 72 | let b = MoveFoo {moved: Box::new(13), ..f}; |
1a4d82fc JJ |
73 | let c = MoveFoo {copied: 14, ..f}; |
74 | assert_eq!(b.copied, 11); | |
75 | assert_eq!(*b.moved, 13); | |
76 | assert_eq!(c.copied, 14); | |
77 | assert_eq!(*c.moved, 12); | |
78 | } | |
79 | ||
80 | fn test2() { | |
81 | // move non-copyable field | |
82 | let f = NoFoo::new(21, 22); | |
83 | let b = NoFoo {nocopy: ncint(23), ..f}; | |
84 | let c = NoFoo {copied: 24, ..f}; | |
85 | assert_eq!(b.copied, 21); | |
86 | assert_eq!(b.nocopy.v, 23); | |
87 | assert_eq!(c.copied, 24); | |
88 | assert_eq!(c.nocopy.v, 22); | |
89 | } | |
90 | ||
91 | pub fn main() { | |
92 | test0(); | |
93 | test1(); | |
94 | test2(); | |
95 | } |