blob: aa08056e81d332efc1817b0113e0879af1f92267 [file] [log] [blame]
Chih-Hung Hsieh6f3e9272020-05-13 16:08:03 -07001#![warn(rust_2018_idioms, single_use_lifetimes)]
2#![allow(dead_code)]
3
Chih-Hung Hsieh127364b2020-10-26 16:54:29 -07004#[macro_use]
5mod auxiliary;
6
Haibo Huangd58366d2020-07-10 20:23:30 -07007use std::{
Chih-Hung Hsieh6f3e9272020-05-13 16:08:03 -07008 marker::{PhantomData, PhantomPinned},
Chih-Hung Hsieh127364b2020-10-26 16:54:29 -07009 panic,
Chih-Hung Hsieh6f3e9272020-05-13 16:08:03 -070010 pin::Pin,
11};
Chih-Hung Hsieh6f3e9272020-05-13 16:08:03 -070012
Haibo Huangc1311072021-02-09 17:42:22 -080013use pin_project::{pin_project, pinned_drop, UnsafeUnpin};
14
Chih-Hung Hsieh6f3e9272020-05-13 16:08:03 -070015#[test]
16fn projection() {
Haibo Huang2960bb32020-05-18 15:51:06 -070017 #[pin_project(
Haibo Huang2960bb32020-05-18 15:51:06 -070018 project = StructProj,
19 project_ref = StructProjRef,
20 project_replace = StructProjOwn,
21 )]
Chih-Hung Hsieh6f3e9272020-05-13 16:08:03 -070022 struct Struct<T, U> {
23 #[pin]
Chih-Hung Hsieh127364b2020-10-26 16:54:29 -070024 f1: T,
25 f2: U,
Chih-Hung Hsieh6f3e9272020-05-13 16:08:03 -070026 }
27
Chih-Hung Hsieh127364b2020-10-26 16:54:29 -070028 let mut s = Struct { f1: 1, f2: 2 };
Chih-Hung Hsieh6f3e9272020-05-13 16:08:03 -070029 let mut s_orig = Pin::new(&mut s);
30 let s = s_orig.as_mut().project();
31
Haibo Huang6c94c6b2020-11-18 15:37:31 -080032 let _: Pin<&mut i32> = s.f1;
33 assert_eq!(*s.f1, 1);
34 let _: &mut i32 = s.f2;
35 assert_eq!(*s.f2, 2);
Chih-Hung Hsieh6f3e9272020-05-13 16:08:03 -070036
Chih-Hung Hsieh127364b2020-10-26 16:54:29 -070037 assert_eq!(s_orig.as_ref().f1, 1);
38 assert_eq!(s_orig.as_ref().f2, 2);
Chih-Hung Hsieh6f3e9272020-05-13 16:08:03 -070039
Chih-Hung Hsieh127364b2020-10-26 16:54:29 -070040 let mut s = Struct { f1: 1, f2: 2 };
Chih-Hung Hsieh6f3e9272020-05-13 16:08:03 -070041 let mut s = Pin::new(&mut s);
Haibo Huang6c94c6b2020-11-18 15:37:31 -080042 {
43 let StructProj { f1, f2 } = s.as_mut().project();
44 let _: Pin<&mut i32> = f1;
45 let _: &mut i32 = f2;
46 }
47 {
48 let StructProjRef { f1, f2 } = s.as_ref().project_ref();
49 let _: Pin<&i32> = f1;
50 let _: &i32 = f2;
51 }
52 {
53 let StructProjOwn { f1, f2 } = s.as_mut().project_replace(Struct { f1: 3, f2: 4 });
54 let _: PhantomData<i32> = f1;
55 let _: i32 = f2;
56 assert_eq!(f2, 2);
57 assert_eq!(s.f1, 3);
58 assert_eq!(s.f2, 4);
59 }
Chih-Hung Hsieh6f3e9272020-05-13 16:08:03 -070060
Haibo Huangd58366d2020-07-10 20:23:30 -070061 #[pin_project(project_replace)]
Chih-Hung Hsieh6f3e9272020-05-13 16:08:03 -070062 struct TupleStruct<T, U>(#[pin] T, U);
63
64 let mut s = TupleStruct(1, 2);
65 let s = Pin::new(&mut s).project();
66
Haibo Huang6c94c6b2020-11-18 15:37:31 -080067 let _: Pin<&mut i32> = s.0;
68 assert_eq!(*s.0, 1);
69 let _: &mut i32 = s.1;
70 assert_eq!(*s.1, 2);
Chih-Hung Hsieh6f3e9272020-05-13 16:08:03 -070071
Chih-Hung Hsieh127364b2020-10-26 16:54:29 -070072 #[pin_project(project = EnumProj, project_ref = EnumProjRef, project_replace = EnumProjOwn)]
Chih-Hung Hsieh6f3e9272020-05-13 16:08:03 -070073 #[derive(Eq, PartialEq, Debug)]
74 enum Enum<A, B, C, D> {
Chih-Hung Hsieh127364b2020-10-26 16:54:29 -070075 Tuple(#[pin] A, B),
76 Struct {
Chih-Hung Hsieh6f3e9272020-05-13 16:08:03 -070077 #[pin]
Chih-Hung Hsieh127364b2020-10-26 16:54:29 -070078 f1: C,
79 f2: D,
Chih-Hung Hsieh6f3e9272020-05-13 16:08:03 -070080 },
Chih-Hung Hsieh127364b2020-10-26 16:54:29 -070081 Unit,
Chih-Hung Hsieh6f3e9272020-05-13 16:08:03 -070082 }
83
Chih-Hung Hsieh127364b2020-10-26 16:54:29 -070084 let mut e = Enum::Tuple(1, 2);
Haibo Huang6c94c6b2020-11-18 15:37:31 -080085 let mut e = Pin::new(&mut e);
Chih-Hung Hsieh6f3e9272020-05-13 16:08:03 -070086
Haibo Huang6c94c6b2020-11-18 15:37:31 -080087 match e.as_mut().project() {
Chih-Hung Hsieh127364b2020-10-26 16:54:29 -070088 EnumProj::Tuple(x, y) => {
Chih-Hung Hsieh6f3e9272020-05-13 16:08:03 -070089 let x: Pin<&mut i32> = x;
90 assert_eq!(*x, 1);
Chih-Hung Hsieh6f3e9272020-05-13 16:08:03 -070091 let y: &mut i32 = y;
92 assert_eq!(*y, 2);
93 }
Chih-Hung Hsieh127364b2020-10-26 16:54:29 -070094 EnumProj::Struct { f1, f2 } => {
95 let _: Pin<&mut i32> = f1;
96 let _: &mut i32 = f2;
Joel Galensonc1569cc2021-08-09 10:36:36 -070097 unreachable!();
Chih-Hung Hsieh6f3e9272020-05-13 16:08:03 -070098 }
Haibo Huang6c94c6b2020-11-18 15:37:31 -080099 EnumProj::Unit => unreachable!(),
Chih-Hung Hsieh6f3e9272020-05-13 16:08:03 -0700100 }
101
Haibo Huang6c94c6b2020-11-18 15:37:31 -0800102 assert_eq!(&*e, &Enum::Tuple(1, 2));
Chih-Hung Hsieh6f3e9272020-05-13 16:08:03 -0700103
Chih-Hung Hsieh127364b2020-10-26 16:54:29 -0700104 let mut e = Enum::Struct { f1: 3, f2: 4 };
Haibo Huang6c94c6b2020-11-18 15:37:31 -0800105 let mut e = Pin::new(&mut e);
Chih-Hung Hsieh6f3e9272020-05-13 16:08:03 -0700106
Haibo Huang6c94c6b2020-11-18 15:37:31 -0800107 match e.as_mut().project() {
Chih-Hung Hsieh127364b2020-10-26 16:54:29 -0700108 EnumProj::Tuple(x, y) => {
Haibo Huang6c94c6b2020-11-18 15:37:31 -0800109 let _: Pin<&mut i32> = x;
110 let _: &mut i32 = y;
Joel Galensonc1569cc2021-08-09 10:36:36 -0700111 unreachable!();
Chih-Hung Hsieh6f3e9272020-05-13 16:08:03 -0700112 }
Chih-Hung Hsieh127364b2020-10-26 16:54:29 -0700113 EnumProj::Struct { f1, f2 } => {
Haibo Huang6c94c6b2020-11-18 15:37:31 -0800114 let _: Pin<&mut i32> = f1;
115 assert_eq!(*f1, 3);
116 let _: &mut i32 = f2;
117 assert_eq!(*f2, 4);
Chih-Hung Hsieh6f3e9272020-05-13 16:08:03 -0700118 }
Haibo Huang6c94c6b2020-11-18 15:37:31 -0800119 EnumProj::Unit => unreachable!(),
Chih-Hung Hsieh6f3e9272020-05-13 16:08:03 -0700120 }
121
Haibo Huang6c94c6b2020-11-18 15:37:31 -0800122 if let EnumProj::Struct { f1, f2 } = e.as_mut().project() {
123 let _: Pin<&mut i32> = f1;
124 assert_eq!(*f1, 3);
125 let _: &mut i32 = f2;
126 assert_eq!(*f2, 4);
Chih-Hung Hsieh6f3e9272020-05-13 16:08:03 -0700127 }
128}
129
130#[test]
131fn enum_project_set() {
Chih-Hung Hsieh127364b2020-10-26 16:54:29 -0700132 #[pin_project(project = EnumProj, project_ref = EnumProjRef, project_replace = EnumProjOwn)]
Chih-Hung Hsieh6f3e9272020-05-13 16:08:03 -0700133 #[derive(Eq, PartialEq, Debug)]
134 enum Enum {
Chih-Hung Hsieh127364b2020-10-26 16:54:29 -0700135 V1(#[pin] u8),
136 V2(bool),
Chih-Hung Hsieh6f3e9272020-05-13 16:08:03 -0700137 }
138
Chih-Hung Hsieh127364b2020-10-26 16:54:29 -0700139 let mut e = Enum::V1(25);
Chih-Hung Hsieh6f3e9272020-05-13 16:08:03 -0700140 let mut e_orig = Pin::new(&mut e);
141 let e_proj = e_orig.as_mut().project();
142
143 match e_proj {
Chih-Hung Hsieh127364b2020-10-26 16:54:29 -0700144 EnumProj::V1(val) => {
145 let new_e = Enum::V2(val.as_ref().get_ref() == &25);
Chih-Hung Hsieh6f3e9272020-05-13 16:08:03 -0700146 e_orig.set(new_e);
147 }
Haibo Huang6c94c6b2020-11-18 15:37:31 -0800148 EnumProj::V2(_) => unreachable!(),
Chih-Hung Hsieh6f3e9272020-05-13 16:08:03 -0700149 }
150
Chih-Hung Hsieh127364b2020-10-26 16:54:29 -0700151 assert_eq!(e, Enum::V2(true));
Chih-Hung Hsieh6f3e9272020-05-13 16:08:03 -0700152}
153
154#[test]
155fn where_clause() {
156 #[pin_project]
157 struct Struct<T>
158 where
159 T: Copy,
160 {
Chih-Hung Hsieh127364b2020-10-26 16:54:29 -0700161 f: T,
Chih-Hung Hsieh6f3e9272020-05-13 16:08:03 -0700162 }
163
164 #[pin_project]
165 struct TupleStruct<T>(T)
166 where
167 T: Copy;
168
Chih-Hung Hsieh127364b2020-10-26 16:54:29 -0700169 #[pin_project(project = EnumProj, project_ref = EnumProjRef, project_replace = EnumProjOwn)]
170 enum Enum<T>
Chih-Hung Hsieh6f3e9272020-05-13 16:08:03 -0700171 where
172 T: Copy,
173 {
Chih-Hung Hsieh127364b2020-10-26 16:54:29 -0700174 V(T),
Chih-Hung Hsieh6f3e9272020-05-13 16:08:03 -0700175 }
176}
177
178#[test]
179fn where_clause_and_associated_type_field() {
Haibo Huangd58366d2020-07-10 20:23:30 -0700180 #[pin_project(project_replace)]
Chih-Hung Hsieh6f3e9272020-05-13 16:08:03 -0700181 struct Struct1<I>
182 where
183 I: Iterator,
184 {
185 #[pin]
Chih-Hung Hsieh127364b2020-10-26 16:54:29 -0700186 f1: I,
187 f2: I::Item,
Chih-Hung Hsieh6f3e9272020-05-13 16:08:03 -0700188 }
189
Haibo Huangd58366d2020-07-10 20:23:30 -0700190 #[pin_project(project_replace)]
Chih-Hung Hsieh6f3e9272020-05-13 16:08:03 -0700191 struct Struct2<I, J>
192 where
193 I: Iterator<Item = J>,
194 {
195 #[pin]
Chih-Hung Hsieh127364b2020-10-26 16:54:29 -0700196 f1: I,
197 f2: J,
Chih-Hung Hsieh6f3e9272020-05-13 16:08:03 -0700198 }
199
Haibo Huangd58366d2020-07-10 20:23:30 -0700200 #[pin_project(project_replace)]
Chih-Hung Hsieh6f3e9272020-05-13 16:08:03 -0700201 struct Struct3<T>
202 where
203 T: 'static,
204 {
Chih-Hung Hsieh127364b2020-10-26 16:54:29 -0700205 f: T,
Chih-Hung Hsieh6f3e9272020-05-13 16:08:03 -0700206 }
207
208 trait Static: 'static {}
209
210 impl<T> Static for Struct3<T> {}
211
Haibo Huangd58366d2020-07-10 20:23:30 -0700212 #[pin_project(project_replace)]
Chih-Hung Hsieh6f3e9272020-05-13 16:08:03 -0700213 struct TupleStruct<I>(#[pin] I, I::Item)
214 where
215 I: Iterator;
216
Chih-Hung Hsieh127364b2020-10-26 16:54:29 -0700217 #[pin_project(project = EnumProj, project_ref = EnumProjRef, project_replace = EnumProjOwn)]
Chih-Hung Hsieh6f3e9272020-05-13 16:08:03 -0700218 enum Enum<I>
219 where
220 I: Iterator,
221 {
Chih-Hung Hsieh127364b2020-10-26 16:54:29 -0700222 V1(#[pin] I),
223 V2(I::Item),
Chih-Hung Hsieh6f3e9272020-05-13 16:08:03 -0700224 }
225}
226
227#[test]
228fn derive_copy() {
Haibo Huangd58366d2020-07-10 20:23:30 -0700229 #[pin_project(project_replace)]
Chih-Hung Hsieh6f3e9272020-05-13 16:08:03 -0700230 #[derive(Clone, Copy)]
231 struct Struct<T> {
Chih-Hung Hsieh127364b2020-10-26 16:54:29 -0700232 f: T,
Chih-Hung Hsieh6f3e9272020-05-13 16:08:03 -0700233 }
234
235 fn is_copy<T: Copy>() {}
236
237 is_copy::<Struct<u8>>();
238}
239
240#[test]
241fn move_out() {
242 struct NotCopy;
243
Haibo Huangd58366d2020-07-10 20:23:30 -0700244 #[pin_project(project_replace)]
Chih-Hung Hsieh6f3e9272020-05-13 16:08:03 -0700245 struct Struct {
Chih-Hung Hsieh127364b2020-10-26 16:54:29 -0700246 f: NotCopy,
Chih-Hung Hsieh6f3e9272020-05-13 16:08:03 -0700247 }
248
Chih-Hung Hsieh127364b2020-10-26 16:54:29 -0700249 let x = Struct { f: NotCopy };
250 let _val: NotCopy = x.f;
Chih-Hung Hsieh6f3e9272020-05-13 16:08:03 -0700251
Chih-Hung Hsieh127364b2020-10-26 16:54:29 -0700252 #[pin_project(project = EnumProj, project_ref = EnumProjRef, project_replace = EnumProjOwn)]
Chih-Hung Hsieh6f3e9272020-05-13 16:08:03 -0700253 enum Enum {
Chih-Hung Hsieh127364b2020-10-26 16:54:29 -0700254 V(NotCopy),
Chih-Hung Hsieh6f3e9272020-05-13 16:08:03 -0700255 }
256
Chih-Hung Hsieh127364b2020-10-26 16:54:29 -0700257 let x = Enum::V(NotCopy);
Chih-Hung Hsieh6f3e9272020-05-13 16:08:03 -0700258 #[allow(clippy::infallible_destructuring_match)]
259 let _val: NotCopy = match x {
Chih-Hung Hsieh127364b2020-10-26 16:54:29 -0700260 Enum::V(val) => val,
Chih-Hung Hsieh6f3e9272020-05-13 16:08:03 -0700261 };
262}
263
264#[test]
265fn trait_bounds_on_type_generics() {
Haibo Huangd58366d2020-07-10 20:23:30 -0700266 #[pin_project(project_replace)]
Chih-Hung Hsieh6f3e9272020-05-13 16:08:03 -0700267 pub struct Struct1<'a, T: ?Sized> {
Chih-Hung Hsieh127364b2020-10-26 16:54:29 -0700268 f: &'a mut T,
Chih-Hung Hsieh6f3e9272020-05-13 16:08:03 -0700269 }
270
Haibo Huangd58366d2020-07-10 20:23:30 -0700271 #[pin_project(project_replace)]
Chih-Hung Hsieh6f3e9272020-05-13 16:08:03 -0700272 pub struct Struct2<'a, T: ::core::fmt::Debug> {
Chih-Hung Hsieh127364b2020-10-26 16:54:29 -0700273 f: &'a mut T,
Chih-Hung Hsieh6f3e9272020-05-13 16:08:03 -0700274 }
275
Haibo Huangd58366d2020-07-10 20:23:30 -0700276 #[pin_project(project_replace)]
Chih-Hung Hsieh6f3e9272020-05-13 16:08:03 -0700277 pub struct Struct3<'a, T: core::fmt::Debug> {
Chih-Hung Hsieh127364b2020-10-26 16:54:29 -0700278 f: &'a mut T,
Chih-Hung Hsieh6f3e9272020-05-13 16:08:03 -0700279 }
280
Haibo Huangd58366d2020-07-10 20:23:30 -0700281 #[pin_project(project_replace)]
Chih-Hung Hsieh6f3e9272020-05-13 16:08:03 -0700282 pub struct Struct4<'a, T: core::fmt::Debug + core::fmt::Display> {
Chih-Hung Hsieh127364b2020-10-26 16:54:29 -0700283 f: &'a mut T,
Chih-Hung Hsieh6f3e9272020-05-13 16:08:03 -0700284 }
285
Haibo Huangd58366d2020-07-10 20:23:30 -0700286 #[pin_project(project_replace)]
Chih-Hung Hsieh6f3e9272020-05-13 16:08:03 -0700287 pub struct Struct5<'a, T: core::fmt::Debug + ?Sized> {
Chih-Hung Hsieh127364b2020-10-26 16:54:29 -0700288 f: &'a mut T,
Chih-Hung Hsieh6f3e9272020-05-13 16:08:03 -0700289 }
290
Haibo Huangd58366d2020-07-10 20:23:30 -0700291 #[pin_project(project_replace)]
Chih-Hung Hsieh6f3e9272020-05-13 16:08:03 -0700292 pub struct Struct6<'a, T: core::fmt::Debug = [u8; 16]> {
Chih-Hung Hsieh127364b2020-10-26 16:54:29 -0700293 f: &'a mut T,
Chih-Hung Hsieh6f3e9272020-05-13 16:08:03 -0700294 }
295
Haibo Huang6c94c6b2020-11-18 15:37:31 -0800296 let _: Struct6<'_> = Struct6 { f: &mut [0_u8; 16] };
Chih-Hung Hsieh6f3e9272020-05-13 16:08:03 -0700297
Haibo Huangd58366d2020-07-10 20:23:30 -0700298 #[pin_project(project_replace)]
Chih-Hung Hsieh6f3e9272020-05-13 16:08:03 -0700299 pub struct Struct7<T: 'static> {
Chih-Hung Hsieh127364b2020-10-26 16:54:29 -0700300 f: T,
Chih-Hung Hsieh6f3e9272020-05-13 16:08:03 -0700301 }
302
303 trait Static: 'static {}
304
305 impl<T> Static for Struct7<T> {}
306
Haibo Huangd58366d2020-07-10 20:23:30 -0700307 #[pin_project(project_replace)]
Chih-Hung Hsieh6f3e9272020-05-13 16:08:03 -0700308 pub struct Struct8<'a, 'b: 'a> {
Chih-Hung Hsieh127364b2020-10-26 16:54:29 -0700309 f1: &'a u8,
310 f2: &'b u8,
Chih-Hung Hsieh6f3e9272020-05-13 16:08:03 -0700311 }
312
Haibo Huangd58366d2020-07-10 20:23:30 -0700313 #[pin_project(project_replace)]
Chih-Hung Hsieh6f3e9272020-05-13 16:08:03 -0700314 pub struct TupleStruct<'a, T: ?Sized>(&'a mut T);
315
Chih-Hung Hsieh127364b2020-10-26 16:54:29 -0700316 #[pin_project(project = EnumProj, project_ref = EnumProjRef, project_replace = EnumProjOwn)]
Chih-Hung Hsieh6f3e9272020-05-13 16:08:03 -0700317 enum Enum<'a, T: ?Sized> {
Chih-Hung Hsieh127364b2020-10-26 16:54:29 -0700318 V(&'a mut T),
Chih-Hung Hsieh6f3e9272020-05-13 16:08:03 -0700319 }
320}
321
322#[test]
323fn overlapping_lifetime_names() {
Haibo Huangd58366d2020-07-10 20:23:30 -0700324 #[pin_project(project_replace)]
Chih-Hung Hsieh6f3e9272020-05-13 16:08:03 -0700325 pub struct Struct1<'pin, T> {
326 #[pin]
Chih-Hung Hsieh127364b2020-10-26 16:54:29 -0700327 f: &'pin mut T,
Chih-Hung Hsieh6f3e9272020-05-13 16:08:03 -0700328 }
329
Haibo Huangd58366d2020-07-10 20:23:30 -0700330 #[pin_project(project_replace)]
Chih-Hung Hsieh6f3e9272020-05-13 16:08:03 -0700331 pub struct Struct2<'pin, 'pin_, 'pin__> {
332 #[pin]
Chih-Hung Hsieh127364b2020-10-26 16:54:29 -0700333 f: &'pin &'pin_ &'pin__ (),
Chih-Hung Hsieh6f3e9272020-05-13 16:08:03 -0700334 }
335
Chih-Hung Hsieh127364b2020-10-26 16:54:29 -0700336 pub trait Trait<'a> {}
Chih-Hung Hsieh6f3e9272020-05-13 16:08:03 -0700337
338 #[allow(single_use_lifetimes)] // https://github.com/rust-lang/rust/issues/55058
Haibo Huangd58366d2020-07-10 20:23:30 -0700339 #[pin_project(project_replace)]
Haibo Huangc1311072021-02-09 17:42:22 -0800340 pub struct Hrtb<'pin___, T>
Chih-Hung Hsieh6f3e9272020-05-13 16:08:03 -0700341 where
342 for<'pin> &'pin T: Unpin,
Chih-Hung Hsieh127364b2020-10-26 16:54:29 -0700343 T: for<'pin> Trait<'pin>,
Chih-Hung Hsieh6f3e9272020-05-13 16:08:03 -0700344 for<'pin, 'pin_, 'pin__> &'pin &'pin_ &'pin__ T: Unpin,
345 {
346 #[pin]
Chih-Hung Hsieh127364b2020-10-26 16:54:29 -0700347 f: &'pin___ mut T,
348 }
349
350 #[pin_project(PinnedDrop)]
351 pub struct PinnedDropStruct<'pin> {
352 #[pin]
353 f: &'pin (),
354 }
355
356 #[pinned_drop]
357 impl PinnedDrop for PinnedDropStruct<'_> {
358 fn drop(self: Pin<&mut Self>) {}
359 }
360
361 #[pin_project(UnsafeUnpin)]
362 pub struct UnsafeUnpinStruct<'pin> {
363 #[pin]
364 f: &'pin (),
365 }
366
367 unsafe impl UnsafeUnpin for UnsafeUnpinStruct<'_> {}
368
369 #[pin_project(!Unpin)]
370 pub struct NotUnpinStruct<'pin> {
371 #[pin]
372 f: &'pin (),
Chih-Hung Hsieh6f3e9272020-05-13 16:08:03 -0700373 }
374}
375
376#[test]
377fn combine() {
378 #[pin_project(PinnedDrop, UnsafeUnpin)]
Haibo Huangd58366d2020-07-10 20:23:30 -0700379 pub struct PinnedDropWithUnsafeUnpin<T> {
Chih-Hung Hsieh6f3e9272020-05-13 16:08:03 -0700380 #[pin]
Chih-Hung Hsieh127364b2020-10-26 16:54:29 -0700381 f: T,
Chih-Hung Hsieh6f3e9272020-05-13 16:08:03 -0700382 }
383
384 #[pinned_drop]
Haibo Huangd58366d2020-07-10 20:23:30 -0700385 impl<T> PinnedDrop for PinnedDropWithUnsafeUnpin<T> {
Chih-Hung Hsieh6f3e9272020-05-13 16:08:03 -0700386 fn drop(self: Pin<&mut Self>) {}
387 }
388
Haibo Huangd58366d2020-07-10 20:23:30 -0700389 unsafe impl<T: Unpin> UnsafeUnpin for PinnedDropWithUnsafeUnpin<T> {}
Chih-Hung Hsieh6f3e9272020-05-13 16:08:03 -0700390
391 #[pin_project(PinnedDrop, !Unpin)]
Haibo Huangd58366d2020-07-10 20:23:30 -0700392 pub struct PinnedDropWithNotUnpin<T> {
Chih-Hung Hsieh6f3e9272020-05-13 16:08:03 -0700393 #[pin]
Chih-Hung Hsieh127364b2020-10-26 16:54:29 -0700394 f: T,
Chih-Hung Hsieh6f3e9272020-05-13 16:08:03 -0700395 }
396
397 #[pinned_drop]
Haibo Huangd58366d2020-07-10 20:23:30 -0700398 impl<T> PinnedDrop for PinnedDropWithNotUnpin<T> {
Chih-Hung Hsieh6f3e9272020-05-13 16:08:03 -0700399 fn drop(self: Pin<&mut Self>) {}
400 }
401
Haibo Huangd58366d2020-07-10 20:23:30 -0700402 #[pin_project(UnsafeUnpin, project_replace)]
403 pub struct UnsafeUnpinWithReplace<T> {
404 #[pin]
Chih-Hung Hsieh127364b2020-10-26 16:54:29 -0700405 f: T,
Haibo Huangd58366d2020-07-10 20:23:30 -0700406 }
407
408 unsafe impl<T: Unpin> UnsafeUnpin for UnsafeUnpinWithReplace<T> {}
409
410 #[pin_project(!Unpin, project_replace)]
411 pub struct NotUnpinWithReplace<T> {
Chih-Hung Hsieh6f3e9272020-05-13 16:08:03 -0700412 #[pin]
Chih-Hung Hsieh127364b2020-10-26 16:54:29 -0700413 f: T,
Chih-Hung Hsieh6f3e9272020-05-13 16:08:03 -0700414 }
415}
416
417#[test]
418fn private_type_in_public_type() {
Haibo Huangd58366d2020-07-10 20:23:30 -0700419 #[pin_project(project_replace)]
Chih-Hung Hsieh6f3e9272020-05-13 16:08:03 -0700420 pub struct PublicStruct<T> {
421 #[pin]
422 inner: PrivateStruct<T>,
423 }
424
425 struct PrivateStruct<T>(T);
426}
427
Chih-Hung Hsieh127364b2020-10-26 16:54:29 -0700428#[allow(clippy::needless_lifetimes)]
Chih-Hung Hsieh6f3e9272020-05-13 16:08:03 -0700429#[test]
430fn lifetime_project() {
Haibo Huangd58366d2020-07-10 20:23:30 -0700431 #[pin_project(project_replace)]
Chih-Hung Hsieh6f3e9272020-05-13 16:08:03 -0700432 struct Struct1<T, U> {
433 #[pin]
434 pinned: T,
435 unpinned: U,
436 }
437
Haibo Huangd58366d2020-07-10 20:23:30 -0700438 #[pin_project(project_replace)]
Chih-Hung Hsieh6f3e9272020-05-13 16:08:03 -0700439 struct Struct2<'a, T, U> {
440 #[pin]
Haibo Huang6c94c6b2020-11-18 15:37:31 -0800441 pinned: &'a T,
Chih-Hung Hsieh6f3e9272020-05-13 16:08:03 -0700442 unpinned: U,
443 }
444
Chih-Hung Hsieh127364b2020-10-26 16:54:29 -0700445 #[pin_project(project = EnumProj, project_ref = EnumProjRef, project_replace = EnumProjOwn)]
Chih-Hung Hsieh6f3e9272020-05-13 16:08:03 -0700446 enum Enum<T, U> {
Chih-Hung Hsieh127364b2020-10-26 16:54:29 -0700447 V {
Chih-Hung Hsieh6f3e9272020-05-13 16:08:03 -0700448 #[pin]
449 pinned: T,
450 unpinned: U,
451 },
452 }
453
454 impl<T, U> Struct1<T, U> {
455 fn get_pin_ref<'a>(self: Pin<&'a Self>) -> Pin<&'a T> {
456 self.project_ref().pinned
457 }
458 fn get_pin_mut<'a>(self: Pin<&'a mut Self>) -> Pin<&'a mut T> {
459 self.project().pinned
460 }
Chih-Hung Hsieh127364b2020-10-26 16:54:29 -0700461 fn get_pin_ref_elided(self: Pin<&Self>) -> Pin<&T> {
462 self.project_ref().pinned
463 }
464 fn get_pin_mut_elided(self: Pin<&mut Self>) -> Pin<&mut T> {
465 self.project().pinned
466 }
Chih-Hung Hsieh6f3e9272020-05-13 16:08:03 -0700467 }
468
469 impl<'b, T, U> Struct2<'b, T, U> {
Haibo Huang6c94c6b2020-11-18 15:37:31 -0800470 fn get_pin_ref<'a>(self: Pin<&'a Self>) -> Pin<&'a &'b T> {
Chih-Hung Hsieh6f3e9272020-05-13 16:08:03 -0700471 self.project_ref().pinned
472 }
Haibo Huang6c94c6b2020-11-18 15:37:31 -0800473 fn get_pin_mut<'a>(self: Pin<&'a mut Self>) -> Pin<&'a mut &'b T> {
Chih-Hung Hsieh6f3e9272020-05-13 16:08:03 -0700474 self.project().pinned
475 }
Haibo Huang6c94c6b2020-11-18 15:37:31 -0800476 fn get_pin_ref_elided(self: Pin<&Self>) -> Pin<&&'b T> {
Chih-Hung Hsieh127364b2020-10-26 16:54:29 -0700477 self.project_ref().pinned
478 }
Haibo Huang6c94c6b2020-11-18 15:37:31 -0800479 fn get_pin_mut_elided(self: Pin<&mut Self>) -> Pin<&mut &'b T> {
Chih-Hung Hsieh127364b2020-10-26 16:54:29 -0700480 self.project().pinned
481 }
Chih-Hung Hsieh6f3e9272020-05-13 16:08:03 -0700482 }
483
484 impl<T, U> Enum<T, U> {
485 fn get_pin_ref<'a>(self: Pin<&'a Self>) -> Pin<&'a T> {
486 match self.project_ref() {
Chih-Hung Hsieh127364b2020-10-26 16:54:29 -0700487 EnumProjRef::V { pinned, .. } => pinned,
Chih-Hung Hsieh6f3e9272020-05-13 16:08:03 -0700488 }
489 }
490 fn get_pin_mut<'a>(self: Pin<&'a mut Self>) -> Pin<&'a mut T> {
491 match self.project() {
Chih-Hung Hsieh127364b2020-10-26 16:54:29 -0700492 EnumProj::V { pinned, .. } => pinned,
Chih-Hung Hsieh6f3e9272020-05-13 16:08:03 -0700493 }
494 }
Chih-Hung Hsieh127364b2020-10-26 16:54:29 -0700495 fn get_pin_ref_elided(self: Pin<&Self>) -> Pin<&T> {
Chih-Hung Hsieh6f3e9272020-05-13 16:08:03 -0700496 match self.project_ref() {
Chih-Hung Hsieh127364b2020-10-26 16:54:29 -0700497 EnumProjRef::V { pinned, .. } => pinned,
Chih-Hung Hsieh6f3e9272020-05-13 16:08:03 -0700498 }
499 }
Chih-Hung Hsieh127364b2020-10-26 16:54:29 -0700500 fn get_pin_mut_elided(self: Pin<&mut Self>) -> Pin<&mut T> {
Chih-Hung Hsieh6f3e9272020-05-13 16:08:03 -0700501 match self.project() {
Chih-Hung Hsieh127364b2020-10-26 16:54:29 -0700502 EnumProj::V { pinned, .. } => pinned,
Chih-Hung Hsieh6f3e9272020-05-13 16:08:03 -0700503 }
504 }
505 }
506}
507
508mod visibility {
509 use pin_project::pin_project;
510
Haibo Huangd58366d2020-07-10 20:23:30 -0700511 #[pin_project(project_replace)]
Chih-Hung Hsieh127364b2020-10-26 16:54:29 -0700512 pub(crate) struct S {
513 pub f: u8,
Chih-Hung Hsieh6f3e9272020-05-13 16:08:03 -0700514 }
515}
516
517#[test]
518fn visibility() {
Chih-Hung Hsieh127364b2020-10-26 16:54:29 -0700519 let mut x = visibility::S { f: 0 };
Chih-Hung Hsieh6f3e9272020-05-13 16:08:03 -0700520 let x = Pin::new(&mut x);
521 let y = x.as_ref().project_ref();
Chih-Hung Hsieh127364b2020-10-26 16:54:29 -0700522 let _: &u8 = y.f;
Chih-Hung Hsieh6f3e9272020-05-13 16:08:03 -0700523 let y = x.project();
Chih-Hung Hsieh127364b2020-10-26 16:54:29 -0700524 let _: &mut u8 = y.f;
Chih-Hung Hsieh6f3e9272020-05-13 16:08:03 -0700525}
526
527#[test]
528fn trivial_bounds() {
Haibo Huangd58366d2020-07-10 20:23:30 -0700529 #[pin_project(project_replace)]
Chih-Hung Hsieh6f3e9272020-05-13 16:08:03 -0700530 pub struct NoGenerics {
531 #[pin]
Chih-Hung Hsieh127364b2020-10-26 16:54:29 -0700532 f: PhantomPinned,
Chih-Hung Hsieh6f3e9272020-05-13 16:08:03 -0700533 }
Chih-Hung Hsieh127364b2020-10-26 16:54:29 -0700534
535 assert_not_unpin!(NoGenerics);
Chih-Hung Hsieh6f3e9272020-05-13 16:08:03 -0700536}
537
538#[test]
539fn dst() {
540 #[pin_project]
541 struct Struct1<T: ?Sized> {
Chih-Hung Hsieh127364b2020-10-26 16:54:29 -0700542 f: T,
Chih-Hung Hsieh6f3e9272020-05-13 16:08:03 -0700543 }
544
Chih-Hung Hsieh127364b2020-10-26 16:54:29 -0700545 let mut x = Struct1 { f: 0_u8 };
Chih-Hung Hsieh6f3e9272020-05-13 16:08:03 -0700546 let x: Pin<&mut Struct1<dyn core::fmt::Debug>> = Pin::new(&mut x as _);
Chih-Hung Hsieh127364b2020-10-26 16:54:29 -0700547 let _: &mut (dyn core::fmt::Debug) = x.project().f;
Chih-Hung Hsieh6f3e9272020-05-13 16:08:03 -0700548
549 #[pin_project]
550 struct Struct2<T: ?Sized> {
551 #[pin]
Chih-Hung Hsieh127364b2020-10-26 16:54:29 -0700552 f: T,
Chih-Hung Hsieh6f3e9272020-05-13 16:08:03 -0700553 }
554
Chih-Hung Hsieh127364b2020-10-26 16:54:29 -0700555 let mut x = Struct2 { f: 0_u8 };
Chih-Hung Hsieh6f3e9272020-05-13 16:08:03 -0700556 let x: Pin<&mut Struct2<dyn core::fmt::Debug + Unpin>> = Pin::new(&mut x as _);
Chih-Hung Hsieh127364b2020-10-26 16:54:29 -0700557 let _: Pin<&mut (dyn core::fmt::Debug + Unpin)> = x.project().f;
558
559 #[allow(explicit_outlives_requirements)] // https://github.com/rust-lang/rust/issues/60993
560 #[pin_project]
561 struct Struct3<T>
562 where
563 T: ?Sized,
564 {
565 f: T,
566 }
567
568 #[allow(explicit_outlives_requirements)] // https://github.com/rust-lang/rust/issues/60993
569 #[pin_project]
570 struct Struct4<T>
571 where
572 T: ?Sized,
573 {
574 #[pin]
575 f: T,
576 }
Chih-Hung Hsieh6f3e9272020-05-13 16:08:03 -0700577
578 #[pin_project(UnsafeUnpin)]
579 struct Struct5<T: ?Sized> {
Chih-Hung Hsieh127364b2020-10-26 16:54:29 -0700580 f: T,
Chih-Hung Hsieh6f3e9272020-05-13 16:08:03 -0700581 }
582
583 #[pin_project(UnsafeUnpin)]
584 struct Struct6<T: ?Sized> {
585 #[pin]
Chih-Hung Hsieh127364b2020-10-26 16:54:29 -0700586 f: T,
Chih-Hung Hsieh6f3e9272020-05-13 16:08:03 -0700587 }
588
589 #[pin_project(PinnedDrop)]
590 struct Struct7<T: ?Sized> {
Chih-Hung Hsieh127364b2020-10-26 16:54:29 -0700591 f: T,
Chih-Hung Hsieh6f3e9272020-05-13 16:08:03 -0700592 }
593
594 #[pinned_drop]
595 impl<T: ?Sized> PinnedDrop for Struct7<T> {
596 fn drop(self: Pin<&mut Self>) {}
597 }
598
599 #[pin_project(PinnedDrop)]
600 struct Struct8<T: ?Sized> {
601 #[pin]
Chih-Hung Hsieh127364b2020-10-26 16:54:29 -0700602 f: T,
Chih-Hung Hsieh6f3e9272020-05-13 16:08:03 -0700603 }
604
605 #[pinned_drop]
606 impl<T: ?Sized> PinnedDrop for Struct8<T> {
607 fn drop(self: Pin<&mut Self>) {}
608 }
609
610 #[pin_project(!Unpin)]
611 struct Struct9<T: ?Sized> {
Chih-Hung Hsieh127364b2020-10-26 16:54:29 -0700612 f: T,
Chih-Hung Hsieh6f3e9272020-05-13 16:08:03 -0700613 }
614
615 #[pin_project(!Unpin)]
616 struct Struct10<T: ?Sized> {
617 #[pin]
Chih-Hung Hsieh127364b2020-10-26 16:54:29 -0700618 f: T,
619 }
620
621 #[pin_project]
622 struct Struct11<'a, T: ?Sized, U: ?Sized> {
623 f1: &'a mut T,
624 f2: U,
Chih-Hung Hsieh6f3e9272020-05-13 16:08:03 -0700625 }
626
627 #[pin_project]
628 struct TupleStruct1<T: ?Sized>(T);
629
630 #[pin_project]
631 struct TupleStruct2<T: ?Sized>(#[pin] T);
632
Chih-Hung Hsieh127364b2020-10-26 16:54:29 -0700633 #[allow(explicit_outlives_requirements)] // https://github.com/rust-lang/rust/issues/60993
634 #[pin_project]
635 struct TupleStruct3<T>(T)
636 where
637 T: ?Sized;
638
639 #[allow(explicit_outlives_requirements)] // https://github.com/rust-lang/rust/issues/60993
640 #[pin_project]
641 struct TupleStruct4<T>(#[pin] T)
642 where
643 T: ?Sized;
644
Chih-Hung Hsieh6f3e9272020-05-13 16:08:03 -0700645 #[pin_project(UnsafeUnpin)]
646 struct TupleStruct5<T: ?Sized>(T);
647
648 #[pin_project(UnsafeUnpin)]
649 struct TupleStruct6<T: ?Sized>(#[pin] T);
650
651 #[pin_project(PinnedDrop)]
652 struct TupleStruct7<T: ?Sized>(T);
653
654 #[pinned_drop]
655 impl<T: ?Sized> PinnedDrop for TupleStruct7<T> {
656 fn drop(self: Pin<&mut Self>) {}
657 }
658
659 #[pin_project(PinnedDrop)]
660 struct TupleStruct8<T: ?Sized>(#[pin] T);
661
662 #[pinned_drop]
663 impl<T: ?Sized> PinnedDrop for TupleStruct8<T> {
664 fn drop(self: Pin<&mut Self>) {}
665 }
666
667 #[pin_project(!Unpin)]
668 struct TupleStruct9<T: ?Sized>(T);
669
670 #[pin_project(!Unpin)]
671 struct TupleStruct10<T: ?Sized>(#[pin] T);
Chih-Hung Hsieh6f3e9272020-05-13 16:08:03 -0700672
673 #[pin_project]
Chih-Hung Hsieh127364b2020-10-26 16:54:29 -0700674 struct TupleStruct11<'a, T: ?Sized, U: ?Sized>(&'a mut T, U);
Chih-Hung Hsieh6f3e9272020-05-13 16:08:03 -0700675}
676
677#[test]
678fn dyn_type() {
679 #[pin_project]
680 struct Struct1 {
681 f: dyn core::fmt::Debug,
682 }
683
684 #[pin_project]
685 struct Struct2 {
686 #[pin]
687 f: dyn core::fmt::Debug,
688 }
689
690 #[pin_project]
691 struct Struct3 {
692 f: dyn core::fmt::Debug + Send,
693 }
694
695 #[pin_project]
696 struct Struct4 {
697 #[pin]
698 f: dyn core::fmt::Debug + Send,
699 }
700
701 #[pin_project]
702 struct TupleStruct1(dyn core::fmt::Debug);
703
704 #[pin_project]
705 struct TupleStruct2(#[pin] dyn core::fmt::Debug);
706
707 #[pin_project]
708 struct TupleStruct3(dyn core::fmt::Debug + Send);
709
710 #[pin_project]
711 struct TupleStruct4(#[pin] dyn core::fmt::Debug + Send);
712}
713
714#[test]
Haibo Huangd58366d2020-07-10 20:23:30 -0700715fn parse_self() {
716 macro_rules! mac {
717 ($($tt:tt)*) => {
718 $($tt)*
719 };
Chih-Hung Hsieh6f3e9272020-05-13 16:08:03 -0700720 }
721
Haibo Huangd58366d2020-07-10 20:23:30 -0700722 pub trait Trait {
Chih-Hung Hsieh6f3e9272020-05-13 16:08:03 -0700723 type Assoc;
724 }
725
Joel Galensonc1569cc2021-08-09 10:36:36 -0700726 #[allow(clippy::type_repetition_in_bounds)]
Haibo Huangd58366d2020-07-10 20:23:30 -0700727 #[pin_project(project_replace)]
728 pub struct Generics<T: Trait<Assoc = Self>>
Chih-Hung Hsieh6f3e9272020-05-13 16:08:03 -0700729 where
Haibo Huangd58366d2020-07-10 20:23:30 -0700730 Self: Trait<Assoc = Self>,
731 <Self as Trait>::Assoc: Sized,
732 mac!(Self): Trait<Assoc = mac!(Self)>,
Chih-Hung Hsieh6f3e9272020-05-13 16:08:03 -0700733 {
Haibo Huangd58366d2020-07-10 20:23:30 -0700734 _f: T,
Chih-Hung Hsieh6f3e9272020-05-13 16:08:03 -0700735 }
736
Haibo Huangd58366d2020-07-10 20:23:30 -0700737 impl<T: Trait<Assoc = Self>> Trait for Generics<T> {
738 type Assoc = Self;
739 }
740
741 #[pin_project(project_replace)]
742 pub struct Struct {
743 _f1: Box<Self>,
744 _f2: Box<<Self as Trait>::Assoc>,
745 _f3: Box<mac!(Self)>,
746 _f4: [(); Self::ASSOC],
747 _f5: [(); Self::assoc()],
748 _f6: [(); mac!(Self::assoc())],
749 }
750
751 impl Struct {
752 const ASSOC: usize = 1;
753 const fn assoc() -> usize {
754 0
755 }
756 }
757
758 impl Trait for Struct {
759 type Assoc = Self;
760 }
761
762 #[pin_project(project_replace)]
763 struct Tuple(
764 Box<Self>,
765 Box<<Self as Trait>::Assoc>,
766 Box<mac!(Self)>,
767 [(); Self::ASSOC],
768 [(); Self::assoc()],
769 [(); mac!(Self::assoc())],
770 );
771
772 impl Tuple {
773 const ASSOC: usize = 1;
774 const fn assoc() -> usize {
775 0
776 }
777 }
778
779 impl Trait for Tuple {
780 type Assoc = Self;
781 }
782
Chih-Hung Hsieh127364b2020-10-26 16:54:29 -0700783 #[pin_project(project = EnumProj, project_ref = EnumProjRef, project_replace = EnumProjOwn)]
Haibo Huangd58366d2020-07-10 20:23:30 -0700784 enum Enum {
785 Struct {
786 _f1: Box<Self>,
787 _f2: Box<<Self as Trait>::Assoc>,
788 _f3: Box<mac!(Self)>,
789 _f4: [(); Self::ASSOC],
790 _f5: [(); Self::assoc()],
791 _f6: [(); mac!(Self::assoc())],
792 },
793 Tuple(
794 Box<Self>,
795 Box<<Self as Trait>::Assoc>,
796 Box<mac!(Self)>,
797 [(); Self::ASSOC],
798 [(); Self::assoc()],
799 [(); mac!(Self::assoc())],
800 ),
801 }
802
803 impl Enum {
804 const ASSOC: usize = 1;
805 const fn assoc() -> usize {
806 0
807 }
808 }
809
810 impl Trait for Enum {
811 type Assoc = Self;
Chih-Hung Hsieh6f3e9272020-05-13 16:08:03 -0700812 }
813}
814
815#[test]
816fn no_infer_outlives() {
Chih-Hung Hsieh127364b2020-10-26 16:54:29 -0700817 trait Trait<X> {
Chih-Hung Hsieh6f3e9272020-05-13 16:08:03 -0700818 type Y;
819 }
820
Chih-Hung Hsieh127364b2020-10-26 16:54:29 -0700821 struct Struct1<A>(A);
Chih-Hung Hsieh6f3e9272020-05-13 16:08:03 -0700822
Chih-Hung Hsieh127364b2020-10-26 16:54:29 -0700823 impl<X, T> Trait<X> for Struct1<T> {
Chih-Hung Hsieh6f3e9272020-05-13 16:08:03 -0700824 type Y = Option<T>;
825 }
826
Haibo Huangd58366d2020-07-10 20:23:30 -0700827 #[pin_project(project_replace)]
Chih-Hung Hsieh127364b2020-10-26 16:54:29 -0700828 struct Struct2<A, B> {
829 _f: <Struct1<A> as Trait<B>>::Y,
Chih-Hung Hsieh6f3e9272020-05-13 16:08:03 -0700830 }
831}
832
833// https://github.com/rust-lang/rust/issues/47949
834// https://github.com/taiki-e/pin-project/pull/194#discussion_r419098111
Haibo Huangd58366d2020-07-10 20:23:30 -0700835#[allow(clippy::many_single_char_names)]
Chih-Hung Hsieh6f3e9272020-05-13 16:08:03 -0700836#[test]
837fn project_replace_panic() {
Haibo Huangd58366d2020-07-10 20:23:30 -0700838 #[pin_project(project_replace)]
Chih-Hung Hsieh6f3e9272020-05-13 16:08:03 -0700839 struct S<T, U> {
840 #[pin]
841 pinned: T,
842 unpinned: U,
843 }
844
845 struct D<'a>(&'a mut bool, bool);
846 impl Drop for D<'_> {
847 fn drop(&mut self) {
848 *self.0 = true;
849 if self.1 {
Joel Galensonc1569cc2021-08-09 10:36:36 -0700850 panic!();
Chih-Hung Hsieh6f3e9272020-05-13 16:08:03 -0700851 }
852 }
853 }
854
855 let (mut a, mut b, mut c, mut d) = (false, false, false, false);
856 let res = panic::catch_unwind(panic::AssertUnwindSafe(|| {
857 let mut x = S { pinned: D(&mut a, true), unpinned: D(&mut b, false) };
858 let _y = Pin::new(&mut x)
859 .project_replace(S { pinned: D(&mut c, false), unpinned: D(&mut d, false) });
Haibo Huangd58366d2020-07-10 20:23:30 -0700860 // Previous `x.pinned` was dropped and panicked when `project_replace` is
861 // called, so this is unreachable.
Chih-Hung Hsieh6f3e9272020-05-13 16:08:03 -0700862 unreachable!();
863 }));
864 assert!(res.is_err());
865 assert!(a);
866 assert!(b);
867 assert!(c);
868 assert!(d);
869
870 let (mut a, mut b, mut c, mut d) = (false, false, false, false);
871 let res = panic::catch_unwind(panic::AssertUnwindSafe(|| {
872 let mut x = S { pinned: D(&mut a, false), unpinned: D(&mut b, true) };
873 {
874 let _y = Pin::new(&mut x)
875 .project_replace(S { pinned: D(&mut c, false), unpinned: D(&mut d, false) });
Haibo Huangd58366d2020-07-10 20:23:30 -0700876 // `_y` (previous `x.unpinned`) live to the end of this scope, so
877 // this is not unreachable.
Chih-Hung Hsieh6f3e9272020-05-13 16:08:03 -0700878 // unreachable!();
879 }
880 unreachable!();
881 }));
882 assert!(res.is_err());
883 assert!(a);
884 assert!(b);
885 assert!(c);
886 assert!(d);
887}