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 #[allow(dead_code)] // false positive that fixed in Rust 1.38
43 StructPinned {
44 #[pin]
45 f1: D<'a>,
46 #[pin]
47 f2: D<'a>,
48 },
49 #[allow(dead_code)] // false positive that fixed in Rust 1.38
50 StructUnpinned {
51 f1: D<'a>,
52 f2: D<'a>,
53 },
54 TuplePinned(#[pin] D<'a>, #[pin] D<'a>),
55 TupleUnpinned(D<'a>, D<'a>),
56 }
57
58 #[test]
struct_pinned()59 fn struct_pinned() {
60 {
61 let c = Cell::new(0);
62 let _x = StructPinned { f1: D(&c, 1), f2: D(&c, 2) };
63 }
64 {
65 let c = Cell::new(0);
66 let mut x = StructPinned { f1: D(&c, 1), f2: D(&c, 2) };
67 let y = Pin::new(&mut x);
68 let _z = y.project_replace(StructPinned { f1: D(&c, 3), f2: D(&c, 4) });
69 }
70 }
71
72 #[test]
struct_unpinned()73 fn struct_unpinned() {
74 {
75 let c = Cell::new(0);
76 let _x = StructUnpinned { f1: D(&c, 1), f2: D(&c, 2) };
77 }
78 {
79 let c = Cell::new(0);
80 let mut x = StructUnpinned { f1: D(&c, 1), f2: D(&c, 2) };
81 let y = Pin::new(&mut x);
82 let _z = y.project_replace(StructUnpinned { f1: D(&c, 3), f2: D(&c, 4) });
83 }
84 }
85
86 #[test]
tuple_pinned()87 fn tuple_pinned() {
88 {
89 let c = Cell::new(0);
90 let _x = TuplePinned(D(&c, 1), D(&c, 2));
91 }
92 {
93 let c = Cell::new(0);
94 let mut x = TuplePinned(D(&c, 1), D(&c, 2));
95 let y = Pin::new(&mut x);
96 let _z = y.project_replace(TuplePinned(D(&c, 3), D(&c, 4)));
97 }
98 }
99
100 #[test]
tuple_unpinned()101 fn tuple_unpinned() {
102 {
103 let c = Cell::new(0);
104 let _x = TupleUnpinned(D(&c, 1), D(&c, 2));
105 }
106 {
107 let c = Cell::new(0);
108 let mut x = TupleUnpinned(D(&c, 1), D(&c, 2));
109 let y = Pin::new(&mut x);
110 let _z = y.project_replace(TupleUnpinned(D(&c, 3), D(&c, 4)));
111 }
112 }
113
114 #[test]
enum_struct()115 fn enum_struct() {
116 {
117 let c = Cell::new(0);
118 let _x = Enum::StructPinned { f1: D(&c, 1), f2: D(&c, 2) };
119 }
120 {
121 let c = Cell::new(0);
122 let mut x = Enum::StructPinned { f1: D(&c, 1), f2: D(&c, 2) };
123 let y = Pin::new(&mut x);
124 let _z = y.project_replace(Enum::StructPinned { f1: D(&c, 3), f2: D(&c, 4) });
125 }
126
127 {
128 let c = Cell::new(0);
129 let _x = Enum::StructUnpinned { f1: D(&c, 1), f2: D(&c, 2) };
130 }
131 {
132 let c = Cell::new(0);
133 let mut x = Enum::StructUnpinned { f1: D(&c, 1), f2: D(&c, 2) };
134 let y = Pin::new(&mut x);
135 let _z = y.project_replace(Enum::StructUnpinned { f1: D(&c, 3), f2: D(&c, 4) });
136 }
137 }
138
139 #[test]
enum_tuple()140 fn enum_tuple() {
141 {
142 let c = Cell::new(0);
143 let _x = Enum::TuplePinned(D(&c, 1), D(&c, 2));
144 }
145 {
146 let c = Cell::new(0);
147 let mut x = Enum::TuplePinned(D(&c, 1), D(&c, 2));
148 let y = Pin::new(&mut x);
149 let _z = y.project_replace(Enum::TuplePinned(D(&c, 3), D(&c, 4)));
150 }
151
152 {
153 let c = Cell::new(0);
154 let _x = Enum::TupleUnpinned(D(&c, 1), D(&c, 2));
155 }
156 {
157 let c = Cell::new(0);
158 let mut x = Enum::TupleUnpinned(D(&c, 1), D(&c, 2));
159 let y = Pin::new(&mut x);
160 let _z = y.project_replace(Enum::TupleUnpinned(D(&c, 3), D(&c, 4)));
161 }
162 }
163