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<'_> {
drop(&mut self)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]
struct_pinned()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]
struct_unpinned()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]
tuple_pinned()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]
tuple_unpinned()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]
enum_struct()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]
enum_tuple()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