1#![warn(rust_2018_idioms, single_use_lifetimes)]
2
3// Refs: https://doc.rust-lang.org/reference/destructors.html
4
5use std::{cell::Cell, pin::Pin, thread};
6
7use pin_project::pin_project;
8
9struct D<'a>(&'a Cell<usize>, usize);
10
11impl 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)]
21struct StructPinned<'a> {
22 #[pin]
23 f1: D<'a>,
24 #[pin]
25 f2: D<'a>,
26}
27
28#[pin_project(project_replace)]
29struct StructUnpinned<'a> {
30 f1: D<'a>,
31 f2: D<'a>,
32}
33
34#[pin_project(project_replace)]
35struct TuplePinned<'a>(#[pin] D<'a>, #[pin] D<'a>);
36
37#[pin_project(project_replace)]
38struct TupleUnpinned<'a>(D<'a>, D<'a>);
39
40#[pin_project(project_replace = EnumProj)]
41enum 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]
57fn 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]
71fn 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]
85fn 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]
99fn 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]
113fn 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]
138fn 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