1 #![warn(rust_2018_idioms, single_use_lifetimes)]
2 #![allow(dead_code)]
3 
4 use pin_project::{pin_project, pinned_drop, UnsafeUnpin};
5 use std::{
6     marker::{PhantomData, PhantomPinned},
7     pin::Pin,
8 };
9 
10 #[test]
projection()11 fn projection() {
12     #[pin_project(
13         project = StructProj,
14         project_ref = StructProjRef,
15         project_replace = StructProjOwn,
16     )]
17     struct Struct<T, U> {
18         #[pin]
19         field1: T,
20         field2: U,
21     }
22 
23     let mut s = Struct { field1: 1, field2: 2 };
24     let mut s_orig = Pin::new(&mut s);
25     let s = s_orig.as_mut().project();
26 
27     let x: Pin<&mut i32> = s.field1;
28     assert_eq!(*x, 1);
29 
30     let y: &mut i32 = s.field2;
31     assert_eq!(*y, 2);
32 
33     assert_eq!(s_orig.as_ref().field1, 1);
34     assert_eq!(s_orig.as_ref().field2, 2);
35 
36     let mut s = Struct { field1: 1, field2: 2 };
37 
38     let StructProj { field1, field2 } = Pin::new(&mut s).project();
39     let _: Pin<&mut i32> = field1;
40     let _: &mut i32 = field2;
41 
42     let StructProjRef { field1, field2 } = Pin::new(&s).project_ref();
43     let _: Pin<&i32> = field1;
44     let _: &i32 = field2;
45 
46     let mut s = Pin::new(&mut s);
47     let StructProjOwn { field1, field2 } =
48         s.as_mut().project_replace(Struct { field1: 3, field2: 4 });
49     let _: PhantomData<i32> = field1;
50     let _: i32 = field2;
51     assert_eq!(field2, 2);
52     assert_eq!(s.field1, 3);
53     assert_eq!(s.field2, 4);
54 
55     #[pin_project(project_replace)]
56     struct TupleStruct<T, U>(#[pin] T, U);
57 
58     let mut s = TupleStruct(1, 2);
59     let s = Pin::new(&mut s).project();
60 
61     let x: Pin<&mut i32> = s.0;
62     assert_eq!(*x, 1);
63 
64     let y: &mut i32 = s.1;
65     assert_eq!(*y, 2);
66 
67     #[pin_project(project_replace, project = EnumProj)]
68     #[derive(Eq, PartialEq, Debug)]
69     enum Enum<A, B, C, D> {
70         Variant1(#[pin] A, B),
71         Variant2 {
72             #[pin]
73             field1: C,
74             field2: D,
75         },
76         None,
77     }
78 
79     let mut e = Enum::Variant1(1, 2);
80     let mut e_orig = Pin::new(&mut e);
81     let e = e_orig.as_mut().project();
82 
83     match e {
84         EnumProj::Variant1(x, y) => {
85             let x: Pin<&mut i32> = x;
86             assert_eq!(*x, 1);
87 
88             let y: &mut i32 = y;
89             assert_eq!(*y, 2);
90         }
91         EnumProj::Variant2 { field1, field2 } => {
92             let _x: Pin<&mut i32> = field1;
93             let _y: &mut i32 = field2;
94         }
95         EnumProj::None => {}
96     }
97 
98     assert_eq!(Pin::into_ref(e_orig).get_ref(), &Enum::Variant1(1, 2));
99 
100     let mut e = Enum::Variant2 { field1: 3, field2: 4 };
101     let mut e = Pin::new(&mut e).project();
102 
103     match &mut e {
104         EnumProj::Variant1(x, y) => {
105             let _x: &mut Pin<&mut i32> = x;
106             let _y: &mut &mut i32 = y;
107         }
108         EnumProj::Variant2 { field1, field2 } => {
109             let x: &mut Pin<&mut i32> = field1;
110             assert_eq!(**x, 3);
111 
112             let y: &mut &mut i32 = field2;
113             assert_eq!(**y, 4);
114         }
115         EnumProj::None => {}
116     }
117 
118     if let EnumProj::Variant2 { field1, field2 } = e {
119         let x: Pin<&mut i32> = field1;
120         assert_eq!(*x, 3);
121 
122         let y: &mut i32 = field2;
123         assert_eq!(*y, 4);
124     }
125 }
126 
127 #[test]
enum_project_set()128 fn enum_project_set() {
129     #[pin_project(project_replace, project = EnumProj)]
130     #[derive(Eq, PartialEq, Debug)]
131     enum Enum {
132         Variant1(#[pin] u8),
133         Variant2(bool),
134     }
135 
136     let mut e = Enum::Variant1(25);
137     let mut e_orig = Pin::new(&mut e);
138     let e_proj = e_orig.as_mut().project();
139 
140     match e_proj {
141         EnumProj::Variant1(val) => {
142             let new_e = Enum::Variant2(val.as_ref().get_ref() == &25);
143             e_orig.set(new_e);
144         }
145         _ => unreachable!(),
146     }
147 
148     assert_eq!(e, Enum::Variant2(true));
149 }
150 
151 #[test]
where_clause()152 fn where_clause() {
153     #[pin_project]
154     struct Struct<T>
155     where
156         T: Copy,
157     {
158         field: T,
159     }
160 
161     #[pin_project]
162     struct TupleStruct<T>(T)
163     where
164         T: Copy;
165 
166     #[pin_project]
167     enum EnumWhere<T>
168     where
169         T: Copy,
170     {
171         Variant(T),
172     }
173 }
174 
175 #[test]
where_clause_and_associated_type_field()176 fn where_clause_and_associated_type_field() {
177     #[pin_project(project_replace)]
178     struct Struct1<I>
179     where
180         I: Iterator,
181     {
182         #[pin]
183         field1: I,
184         field2: I::Item,
185     }
186 
187     #[pin_project(project_replace)]
188     struct Struct2<I, J>
189     where
190         I: Iterator<Item = J>,
191     {
192         #[pin]
193         field1: I,
194         field2: J,
195     }
196 
197     #[pin_project(project_replace)]
198     struct Struct3<T>
199     where
200         T: 'static,
201     {
202         field: T,
203     }
204 
205     trait Static: 'static {}
206 
207     impl<T> Static for Struct3<T> {}
208 
209     #[pin_project(project_replace)]
210     struct TupleStruct<I>(#[pin] I, I::Item)
211     where
212         I: Iterator;
213 
214     #[pin_project(project_replace)]
215     enum Enum<I>
216     where
217         I: Iterator,
218     {
219         Variant1(#[pin] I),
220         Variant2(I::Item),
221     }
222 }
223 
224 #[test]
derive_copy()225 fn derive_copy() {
226     #[pin_project(project_replace)]
227     #[derive(Clone, Copy)]
228     struct Struct<T> {
229         val: T,
230     }
231 
232     fn is_copy<T: Copy>() {}
233 
234     is_copy::<Struct<u8>>();
235 }
236 
237 #[test]
move_out()238 fn move_out() {
239     struct NotCopy;
240 
241     #[pin_project(project_replace)]
242     struct Struct {
243         val: NotCopy,
244     }
245 
246     let x = Struct { val: NotCopy };
247     let _val: NotCopy = x.val;
248 
249     #[pin_project(project_replace)]
250     enum Enum {
251         Variant(NotCopy),
252     }
253 
254     let x = Enum::Variant(NotCopy);
255     #[allow(clippy::infallible_destructuring_match)]
256     let _val: NotCopy = match x {
257         Enum::Variant(val) => val,
258     };
259 }
260 
261 #[test]
trait_bounds_on_type_generics()262 fn trait_bounds_on_type_generics() {
263     #[pin_project(project_replace)]
264     pub struct Struct1<'a, T: ?Sized> {
265         field: &'a mut T,
266     }
267 
268     #[pin_project(project_replace)]
269     pub struct Struct2<'a, T: ::core::fmt::Debug> {
270         field: &'a mut T,
271     }
272 
273     #[pin_project(project_replace)]
274     pub struct Struct3<'a, T: core::fmt::Debug> {
275         field: &'a mut T,
276     }
277 
278     #[pin_project(project_replace)]
279     pub struct Struct4<'a, T: core::fmt::Debug + core::fmt::Display> {
280         field: &'a mut T,
281     }
282 
283     #[pin_project(project_replace)]
284     pub struct Struct5<'a, T: core::fmt::Debug + ?Sized> {
285         field: &'a mut T,
286     }
287 
288     #[pin_project(project_replace)]
289     pub struct Struct6<'a, T: core::fmt::Debug = [u8; 16]> {
290         field: &'a mut T,
291     }
292 
293     let _: Struct6<'_> = Struct6 { field: &mut [0u8; 16] };
294 
295     #[pin_project(project_replace)]
296     pub struct Struct7<T: 'static> {
297         field: T,
298     }
299 
300     trait Static: 'static {}
301 
302     impl<T> Static for Struct7<T> {}
303 
304     #[pin_project(project_replace)]
305     pub struct Struct8<'a, 'b: 'a> {
306         field1: &'a u8,
307         field2: &'b u8,
308     }
309 
310     #[pin_project(project_replace)]
311     pub struct TupleStruct<'a, T: ?Sized>(&'a mut T);
312 
313     #[pin_project(project_replace)]
314     enum Enum<'a, T: ?Sized> {
315         Variant(&'a mut T),
316     }
317 }
318 
319 #[test]
overlapping_lifetime_names()320 fn overlapping_lifetime_names() {
321     #[pin_project(project_replace)]
322     pub struct Struct1<'pin, T> {
323         #[pin]
324         field: &'pin mut T,
325     }
326 
327     #[pin_project(project_replace)]
328     pub struct Struct2<'pin, 'pin_, 'pin__> {
329         #[pin]
330         field: &'pin &'pin_ &'pin__ (),
331     }
332 
333     pub trait A<'a> {}
334 
335     #[allow(single_use_lifetimes)] // https://github.com/rust-lang/rust/issues/55058
336     #[pin_project(project_replace)]
337     pub struct HRTB<'pin___, T>
338     where
339         for<'pin> &'pin T: Unpin,
340         T: for<'pin> A<'pin>,
341         for<'pin, 'pin_, 'pin__> &'pin &'pin_ &'pin__ T: Unpin,
342     {
343         #[pin]
344         field: &'pin___ mut T,
345     }
346 }
347 
348 #[test]
combine()349 fn combine() {
350     #[pin_project(PinnedDrop, UnsafeUnpin)]
351     pub struct PinnedDropWithUnsafeUnpin<T> {
352         #[pin]
353         field: T,
354     }
355 
356     #[pinned_drop]
357     impl<T> PinnedDrop for PinnedDropWithUnsafeUnpin<T> {
358         fn drop(self: Pin<&mut Self>) {}
359     }
360 
361     unsafe impl<T: Unpin> UnsafeUnpin for PinnedDropWithUnsafeUnpin<T> {}
362 
363     #[pin_project(PinnedDrop, !Unpin)]
364     pub struct PinnedDropWithNotUnpin<T> {
365         #[pin]
366         field: T,
367     }
368 
369     #[pinned_drop]
370     impl<T> PinnedDrop for PinnedDropWithNotUnpin<T> {
371         fn drop(self: Pin<&mut Self>) {}
372     }
373 
374     #[pin_project(UnsafeUnpin, project_replace)]
375     pub struct UnsafeUnpinWithReplace<T> {
376         #[pin]
377         field: T,
378     }
379 
380     unsafe impl<T: Unpin> UnsafeUnpin for UnsafeUnpinWithReplace<T> {}
381 
382     #[pin_project(!Unpin, project_replace)]
383     pub struct NotUnpinWithReplace<T> {
384         #[pin]
385         field: T,
386     }
387 }
388 
389 #[test]
private_type_in_public_type()390 fn private_type_in_public_type() {
391     #[pin_project(project_replace)]
392     pub struct PublicStruct<T> {
393         #[pin]
394         inner: PrivateStruct<T>,
395     }
396 
397     struct PrivateStruct<T>(T);
398 }
399 
400 #[test]
lifetime_project()401 fn lifetime_project() {
402     #[pin_project(project_replace)]
403     struct Struct1<T, U> {
404         #[pin]
405         pinned: T,
406         unpinned: U,
407     }
408 
409     #[pin_project(project_replace)]
410     struct Struct2<'a, T, U> {
411         #[pin]
412         pinned: &'a mut T,
413         unpinned: U,
414     }
415 
416     #[pin_project(project_replace, project = EnumProj, project_ref = EnumProjRef)]
417     enum Enum<T, U> {
418         Variant {
419             #[pin]
420             pinned: T,
421             unpinned: U,
422         },
423     }
424 
425     impl<T, U> Struct1<T, U> {
426         fn get_pin_ref<'a>(self: Pin<&'a Self>) -> Pin<&'a T> {
427             self.project_ref().pinned
428         }
429         fn get_pin_mut<'a>(self: Pin<&'a mut Self>) -> Pin<&'a mut T> {
430             self.project().pinned
431         }
432     }
433 
434     impl<'b, T, U> Struct2<'b, T, U> {
435         fn get_pin_ref<'a>(self: Pin<&'a Self>) -> Pin<&'a &'b mut T> {
436             self.project_ref().pinned
437         }
438         fn get_pin_mut<'a>(self: Pin<&'a mut Self>) -> Pin<&'a mut &'b mut T> {
439             self.project().pinned
440         }
441     }
442 
443     impl<T, U> Enum<T, U> {
444         fn get_pin_ref<'a>(self: Pin<&'a Self>) -> Pin<&'a T> {
445             match self.project_ref() {
446                 EnumProjRef::Variant { pinned, .. } => pinned,
447             }
448         }
449         fn get_pin_mut<'a>(self: Pin<&'a mut Self>) -> Pin<&'a mut T> {
450             match self.project() {
451                 EnumProj::Variant { pinned, .. } => pinned,
452             }
453         }
454     }
455 }
456 
457 #[rustversion::since(1.36)] // https://github.com/rust-lang/rust/pull/61207
458 #[test]
lifetime_project_elided()459 fn lifetime_project_elided() {
460     #[pin_project(project_replace)]
461     struct Struct1<T, U> {
462         #[pin]
463         pinned: T,
464         unpinned: U,
465     }
466 
467     #[pin_project(project_replace)]
468     struct Struct2<'a, T, U> {
469         #[pin]
470         pinned: &'a mut T,
471         unpinned: U,
472     }
473 
474     #[pin_project(project_replace, project = EnumProj, project_ref = EnumProjRef)]
475     enum Enum<T, U> {
476         Variant {
477             #[pin]
478             pinned: T,
479             unpinned: U,
480         },
481     }
482 
483     impl<T, U> Struct1<T, U> {
484         fn get_pin_ref(self: Pin<&Self>) -> Pin<&T> {
485             self.project_ref().pinned
486         }
487         fn get_pin_mut(self: Pin<&mut Self>) -> Pin<&mut T> {
488             self.project().pinned
489         }
490     }
491 
492     impl<'b, T, U> Struct2<'b, T, U> {
493         fn get_pin_ref(self: Pin<&Self>) -> Pin<&&'b mut T> {
494             self.project_ref().pinned
495         }
496         fn get_pin_mut(self: Pin<&mut Self>) -> Pin<&mut &'b mut T> {
497             self.project().pinned
498         }
499     }
500 
501     impl<T, U> Enum<T, U> {
502         fn get_pin_ref(self: Pin<&Self>) -> Pin<&T> {
503             match self.project_ref() {
504                 EnumProjRef::Variant { pinned, .. } => pinned,
505             }
506         }
507         fn get_pin_mut(self: Pin<&mut Self>) -> Pin<&mut T> {
508             match self.project() {
509                 EnumProj::Variant { pinned, .. } => pinned,
510             }
511         }
512     }
513 }
514 
515 mod visibility {
516     use pin_project::pin_project;
517 
518     #[pin_project(project_replace)]
519     pub(crate) struct A {
520         pub b: u8,
521     }
522 }
523 
524 #[test]
visibility()525 fn visibility() {
526     let mut x = visibility::A { b: 0 };
527     let x = Pin::new(&mut x);
528     let y = x.as_ref().project_ref();
529     let _: &u8 = y.b;
530     let y = x.project();
531     let _: &mut u8 = y.b;
532 }
533 
534 #[test]
trivial_bounds()535 fn trivial_bounds() {
536     #[pin_project(project_replace)]
537     pub struct NoGenerics {
538         #[pin]
539         field: PhantomPinned,
540     }
541 }
542 
543 #[test]
dst()544 fn dst() {
545     #[pin_project]
546     struct Struct1<T: ?Sized> {
547         x: T,
548     }
549 
550     let mut x = Struct1 { x: 0_u8 };
551     let x: Pin<&mut Struct1<dyn core::fmt::Debug>> = Pin::new(&mut x as _);
552     let _y: &mut (dyn core::fmt::Debug) = x.project().x;
553 
554     #[pin_project]
555     struct Struct2<T: ?Sized> {
556         #[pin]
557         x: T,
558     }
559 
560     let mut x = Struct2 { x: 0_u8 };
561     let x: Pin<&mut Struct2<dyn core::fmt::Debug + Unpin>> = Pin::new(&mut x as _);
562     let _y: Pin<&mut (dyn core::fmt::Debug + Unpin)> = x.project().x;
563 
564     #[pin_project(UnsafeUnpin)]
565     struct Struct5<T: ?Sized> {
566         x: T,
567     }
568 
569     #[pin_project(UnsafeUnpin)]
570     struct Struct6<T: ?Sized> {
571         #[pin]
572         x: T,
573     }
574 
575     #[pin_project(PinnedDrop)]
576     struct Struct7<T: ?Sized> {
577         x: T,
578     }
579 
580     #[pinned_drop]
581     impl<T: ?Sized> PinnedDrop for Struct7<T> {
582         fn drop(self: Pin<&mut Self>) {}
583     }
584 
585     #[pin_project(PinnedDrop)]
586     struct Struct8<T: ?Sized> {
587         #[pin]
588         x: T,
589     }
590 
591     #[pinned_drop]
592     impl<T: ?Sized> PinnedDrop for Struct8<T> {
593         fn drop(self: Pin<&mut Self>) {}
594     }
595 
596     #[pin_project(!Unpin)]
597     struct Struct9<T: ?Sized> {
598         x: T,
599     }
600 
601     #[pin_project(!Unpin)]
602     struct Struct10<T: ?Sized> {
603         #[pin]
604         x: T,
605     }
606 
607     #[pin_project]
608     struct TupleStruct1<T: ?Sized>(T);
609 
610     #[pin_project]
611     struct TupleStruct2<T: ?Sized>(#[pin] T);
612 
613     #[pin_project(UnsafeUnpin)]
614     struct TupleStruct5<T: ?Sized>(T);
615 
616     #[pin_project(UnsafeUnpin)]
617     struct TupleStruct6<T: ?Sized>(#[pin] T);
618 
619     #[pin_project(PinnedDrop)]
620     struct TupleStruct7<T: ?Sized>(T);
621 
622     #[pinned_drop]
623     impl<T: ?Sized> PinnedDrop for TupleStruct7<T> {
624         fn drop(self: Pin<&mut Self>) {}
625     }
626 
627     #[pin_project(PinnedDrop)]
628     struct TupleStruct8<T: ?Sized>(#[pin] T);
629 
630     #[pinned_drop]
631     impl<T: ?Sized> PinnedDrop for TupleStruct8<T> {
632         fn drop(self: Pin<&mut Self>) {}
633     }
634 
635     #[pin_project(!Unpin)]
636     struct TupleStruct9<T: ?Sized>(T);
637 
638     #[pin_project(!Unpin)]
639     struct TupleStruct10<T: ?Sized>(#[pin] T);
640 }
641 
642 #[allow(explicit_outlives_requirements)] // https://github.com/rust-lang/rust/issues/60993
643 #[test]
unsized_in_where_clause()644 fn unsized_in_where_clause() {
645     #[pin_project]
646     struct Struct3<T>
647     where
648         T: ?Sized,
649     {
650         x: T,
651     }
652 
653     #[pin_project]
654     struct Struct4<T>
655     where
656         T: ?Sized,
657     {
658         #[pin]
659         x: T,
660     }
661 
662     #[pin_project]
663     struct TupleStruct3<T>(T)
664     where
665         T: ?Sized;
666 
667     #[pin_project]
668     struct TupleStruct4<T>(#[pin] T)
669     where
670         T: ?Sized;
671 }
672 
673 #[test]
dyn_type()674 fn dyn_type() {
675     #[pin_project]
676     struct Struct1 {
677         f: dyn core::fmt::Debug,
678     }
679 
680     #[pin_project]
681     struct Struct2 {
682         #[pin]
683         f: dyn core::fmt::Debug,
684     }
685 
686     #[pin_project]
687     struct Struct3 {
688         f: dyn core::fmt::Debug + Send,
689     }
690 
691     #[pin_project]
692     struct Struct4 {
693         #[pin]
694         f: dyn core::fmt::Debug + Send,
695     }
696 
697     #[pin_project]
698     struct TupleStruct1(dyn core::fmt::Debug);
699 
700     #[pin_project]
701     struct TupleStruct2(#[pin] dyn core::fmt::Debug);
702 
703     #[pin_project]
704     struct TupleStruct3(dyn core::fmt::Debug + Send);
705 
706     #[pin_project]
707     struct TupleStruct4(#[pin] dyn core::fmt::Debug + Send);
708 }
709 
710 #[test]
parse_self()711 fn parse_self() {
712     macro_rules! mac {
713         ($($tt:tt)*) => {
714             $($tt)*
715         };
716     }
717 
718     pub trait Trait {
719         type Assoc;
720     }
721 
722     #[pin_project(project_replace)]
723     pub struct Generics<T: Trait<Assoc = Self>>
724     where
725         Self: Trait<Assoc = Self>,
726         <Self as Trait>::Assoc: Sized,
727         mac!(Self): Trait<Assoc = mac!(Self)>,
728     {
729         _f: T,
730     }
731 
732     impl<T: Trait<Assoc = Self>> Trait for Generics<T> {
733         type Assoc = Self;
734     }
735 
736     #[pin_project(project_replace)]
737     pub struct Struct {
738         _f1: Box<Self>,
739         _f2: Box<<Self as Trait>::Assoc>,
740         _f3: Box<mac!(Self)>,
741         _f4: [(); Self::ASSOC],
742         _f5: [(); Self::assoc()],
743         _f6: [(); mac!(Self::assoc())],
744     }
745 
746     impl Struct {
747         const ASSOC: usize = 1;
748         const fn assoc() -> usize {
749             0
750         }
751     }
752 
753     impl Trait for Struct {
754         type Assoc = Self;
755     }
756 
757     #[pin_project(project_replace)]
758     struct Tuple(
759         Box<Self>,
760         Box<<Self as Trait>::Assoc>,
761         Box<mac!(Self)>,
762         [(); Self::ASSOC],
763         [(); Self::assoc()],
764         [(); mac!(Self::assoc())],
765     );
766 
767     impl Tuple {
768         const ASSOC: usize = 1;
769         const fn assoc() -> usize {
770             0
771         }
772     }
773 
774     impl Trait for Tuple {
775         type Assoc = Self;
776     }
777 
778     #[pin_project(project_replace)]
779     enum Enum {
780         Struct {
781             _f1: Box<Self>,
782             _f2: Box<<Self as Trait>::Assoc>,
783             _f3: Box<mac!(Self)>,
784             _f4: [(); Self::ASSOC],
785             _f5: [(); Self::assoc()],
786             _f6: [(); mac!(Self::assoc())],
787         },
788         Tuple(
789             Box<Self>,
790             Box<<Self as Trait>::Assoc>,
791             Box<mac!(Self)>,
792             [(); Self::ASSOC],
793             [(); Self::assoc()],
794             [(); mac!(Self::assoc())],
795         ),
796     }
797 
798     impl Enum {
799         const ASSOC: usize = 1;
800         const fn assoc() -> usize {
801             0
802         }
803     }
804 
805     impl Trait for Enum {
806         type Assoc = Self;
807     }
808 }
809 
810 #[test]
811 fn no_infer_outlives() {
812     trait Bar<X> {
813         type Y;
814     }
815 
816     struct Example<A>(A);
817 
818     impl<X, T> Bar<X> for Example<T> {
819         type Y = Option<T>;
820     }
821 
822     #[pin_project(project_replace)]
823     struct Foo<A, B> {
824         _x: <Example<A> as Bar<B>>::Y,
825     }
826 }
827 
828 // https://github.com/rust-lang/rust/issues/47949
829 // https://github.com/taiki-e/pin-project/pull/194#discussion_r419098111
830 #[allow(clippy::many_single_char_names)]
831 #[test]
832 fn project_replace_panic() {
833     use std::panic;
834 
835     #[pin_project(project_replace)]
836     struct S<T, U> {
837         #[pin]
838         pinned: T,
839         unpinned: U,
840     }
841 
842     struct D<'a>(&'a mut bool, bool);
843     impl Drop for D<'_> {
844         fn drop(&mut self) {
845             *self.0 = true;
846             if self.1 {
847                 panic!()
848             }
849         }
850     }
851 
852     let (mut a, mut b, mut c, mut d) = (false, false, false, false);
853     let res = panic::catch_unwind(panic::AssertUnwindSafe(|| {
854         let mut x = S { pinned: D(&mut a, true), unpinned: D(&mut b, false) };
855         let _y = Pin::new(&mut x)
856             .project_replace(S { pinned: D(&mut c, false), unpinned: D(&mut d, false) });
857         // Previous `x.pinned` was dropped and panicked when `project_replace` is
858         // called, so this is unreachable.
859         unreachable!();
860     }));
861     assert!(res.is_err());
862     assert!(a);
863     assert!(b);
864     assert!(c);
865     assert!(d);
866 
867     let (mut a, mut b, mut c, mut d) = (false, false, false, false);
868     let res = panic::catch_unwind(panic::AssertUnwindSafe(|| {
869         let mut x = S { pinned: D(&mut a, false), unpinned: D(&mut b, true) };
870         {
871             let _y = Pin::new(&mut x)
872                 .project_replace(S { pinned: D(&mut c, false), unpinned: D(&mut d, false) });
873             // `_y` (previous `x.unpinned`) live to the end of this scope, so
874             // this is not unreachable.
875             // unreachable!();
876         }
877         unreachable!();
878     }));
879     assert!(res.is_err());
880     assert!(a);
881     assert!(b);
882     assert!(c);
883     assert!(d);
884 }
885