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