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