1 | #![warn (rust_2018_idioms, single_use_lifetimes)] |
2 | |
3 | // Refs: https://doc.rust-lang.org/reference/destructors.html |
4 | |
5 | use std::{cell::Cell, pin::Pin, thread}; |
6 | |
7 | use pin_project::pin_project ; |
8 | |
9 | struct D<'a>(&'a Cell<usize>, usize); |
10 | |
11 | impl Drop for D<'_> { |
12 | fn drop(&mut self) { |
13 | if !thread::panicking() { |
14 | let old = self.0.replace(self.1); |
15 | assert_eq!(old, self.1 - 1); |
16 | } |
17 | } |
18 | } |
19 | |
20 | #[pin_project (project_replace)] |
21 | struct StructPinned<'a> { |
22 | #[pin] |
23 | f1: D<'a>, |
24 | #[pin] |
25 | f2: D<'a>, |
26 | } |
27 | |
28 | #[pin_project (project_replace)] |
29 | struct StructUnpinned<'a> { |
30 | f1: D<'a>, |
31 | f2: D<'a>, |
32 | } |
33 | |
34 | #[pin_project (project_replace)] |
35 | struct TuplePinned<'a>(#[pin] D<'a>, #[pin] D<'a>); |
36 | |
37 | #[pin_project (project_replace)] |
38 | struct TupleUnpinned<'a>(D<'a>, D<'a>); |
39 | |
40 | #[pin_project (project_replace = EnumProj)] |
41 | enum Enum<'a> { |
42 | StructPinned { |
43 | #[pin] |
44 | f1: D<'a>, |
45 | #[pin] |
46 | f2: D<'a>, |
47 | }, |
48 | StructUnpinned { |
49 | f1: D<'a>, |
50 | f2: D<'a>, |
51 | }, |
52 | TuplePinned(#[pin] D<'a>, #[pin] D<'a>), |
53 | TupleUnpinned(D<'a>, D<'a>), |
54 | } |
55 | |
56 | #[test] |
57 | fn struct_pinned() { |
58 | { |
59 | let c = Cell::new(0); |
60 | let _x = StructPinned { f1: D(&c, 1), f2: D(&c, 2) }; |
61 | } |
62 | { |
63 | let c = Cell::new(0); |
64 | let mut x = StructPinned { f1: D(&c, 1), f2: D(&c, 2) }; |
65 | let y = Pin::new(&mut x); |
66 | let _z = y.project_replace(StructPinned { f1: D(&c, 3), f2: D(&c, 4) }); |
67 | } |
68 | } |
69 | |
70 | #[test] |
71 | fn struct_unpinned() { |
72 | { |
73 | let c = Cell::new(0); |
74 | let _x = StructUnpinned { f1: D(&c, 1), f2: D(&c, 2) }; |
75 | } |
76 | { |
77 | let c = Cell::new(0); |
78 | let mut x = StructUnpinned { f1: D(&c, 1), f2: D(&c, 2) }; |
79 | let y = Pin::new(&mut x); |
80 | let _z = y.project_replace(StructUnpinned { f1: D(&c, 3), f2: D(&c, 4) }); |
81 | } |
82 | } |
83 | |
84 | #[test] |
85 | fn tuple_pinned() { |
86 | { |
87 | let c = Cell::new(0); |
88 | let _x = TuplePinned(D(&c, 1), D(&c, 2)); |
89 | } |
90 | { |
91 | let c = Cell::new(0); |
92 | let mut x = TuplePinned(D(&c, 1), D(&c, 2)); |
93 | let y = Pin::new(&mut x); |
94 | let _z = y.project_replace(TuplePinned(D(&c, 3), D(&c, 4))); |
95 | } |
96 | } |
97 | |
98 | #[test] |
99 | fn tuple_unpinned() { |
100 | { |
101 | let c = Cell::new(0); |
102 | let _x = TupleUnpinned(D(&c, 1), D(&c, 2)); |
103 | } |
104 | { |
105 | let c = Cell::new(0); |
106 | let mut x = TupleUnpinned(D(&c, 1), D(&c, 2)); |
107 | let y = Pin::new(&mut x); |
108 | let _z = y.project_replace(TupleUnpinned(D(&c, 3), D(&c, 4))); |
109 | } |
110 | } |
111 | |
112 | #[test] |
113 | fn enum_struct() { |
114 | { |
115 | let c = Cell::new(0); |
116 | let _x = Enum::StructPinned { f1: D(&c, 1), f2: D(&c, 2) }; |
117 | } |
118 | { |
119 | let c = Cell::new(0); |
120 | let mut x = Enum::StructPinned { f1: D(&c, 1), f2: D(&c, 2) }; |
121 | let y = Pin::new(&mut x); |
122 | let _z = y.project_replace(Enum::StructPinned { f1: D(&c, 3), f2: D(&c, 4) }); |
123 | } |
124 | |
125 | { |
126 | let c = Cell::new(0); |
127 | let _x = Enum::StructUnpinned { f1: D(&c, 1), f2: D(&c, 2) }; |
128 | } |
129 | { |
130 | let c = Cell::new(0); |
131 | let mut x = Enum::StructUnpinned { f1: D(&c, 1), f2: D(&c, 2) }; |
132 | let y = Pin::new(&mut x); |
133 | let _z = y.project_replace(Enum::StructUnpinned { f1: D(&c, 3), f2: D(&c, 4) }); |
134 | } |
135 | } |
136 | |
137 | #[test] |
138 | fn enum_tuple() { |
139 | { |
140 | let c = Cell::new(0); |
141 | let _x = Enum::TuplePinned(D(&c, 1), D(&c, 2)); |
142 | } |
143 | { |
144 | let c = Cell::new(0); |
145 | let mut x = Enum::TuplePinned(D(&c, 1), D(&c, 2)); |
146 | let y = Pin::new(&mut x); |
147 | let _z = y.project_replace(Enum::TuplePinned(D(&c, 3), D(&c, 4))); |
148 | } |
149 | |
150 | { |
151 | let c = Cell::new(0); |
152 | let _x = Enum::TupleUnpinned(D(&c, 1), D(&c, 2)); |
153 | } |
154 | { |
155 | let c = Cell::new(0); |
156 | let mut x = Enum::TupleUnpinned(D(&c, 1), D(&c, 2)); |
157 | let y = Pin::new(&mut x); |
158 | let _z = y.project_replace(Enum::TupleUnpinned(D(&c, 3), D(&c, 4))); |
159 | } |
160 | } |
161 | |