1 #![warn(rust_2018_idioms, single_use_lifetimes)]
2 #![allow(dead_code)]
3 
4 #[macro_use]
5 mod auxiliary;
6 
7 use std::{
8     marker::{PhantomData, PhantomPinned},
9     panic,
10     pin::Pin,
11 };
12 
13 use pin_project::{pin_project, pinned_drop, UnsafeUnpin};
14 
15 #[test]
projection()16 fn projection() {
17     #[pin_project(
18         project = StructProj,
19         project_ref = StructProjRef,
20         project_replace = StructProjOwn,
21     )]
22     struct Struct<T, U> {
23         #[pin]
24         f1: T,
25         f2: U,
26     }
27 
28     let mut s = Struct { f1: 1, f2: 2 };
29     let mut s_orig = Pin::new(&mut s);
30     let s = s_orig.as_mut().project();
31 
32     let _: Pin<&mut i32> = s.f1;
33     assert_eq!(*s.f1, 1);
34     let _: &mut i32 = s.f2;
35     assert_eq!(*s.f2, 2);
36 
37     assert_eq!(s_orig.as_ref().f1, 1);
38     assert_eq!(s_orig.as_ref().f2, 2);
39 
40     let mut s = Struct { f1: 1, f2: 2 };
41     let mut s = Pin::new(&mut s);
42     {
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     }
60 
61     #[pin_project(project_replace)]
62     struct TupleStruct<T, U>(#[pin] T, U);
63 
64     let mut s = TupleStruct(1, 2);
65     let s = Pin::new(&mut s).project();
66 
67     let _: Pin<&mut i32> = s.0;
68     assert_eq!(*s.0, 1);
69     let _: &mut i32 = s.1;
70     assert_eq!(*s.1, 2);
71 
72     #[pin_project(project = EnumProj, project_ref = EnumProjRef, project_replace = EnumProjOwn)]
73     #[derive(Eq, PartialEq, Debug)]
74     enum Enum<A, B, C, D> {
75         Tuple(#[pin] A, B),
76         Struct {
77             #[pin]
78             f1: C,
79             f2: D,
80         },
81         Unit,
82     }
83 
84     let mut e = Enum::Tuple(1, 2);
85     let mut e = Pin::new(&mut e);
86 
87     match e.as_mut().project() {
88         EnumProj::Tuple(x, y) => {
89             let x: Pin<&mut i32> = x;
90             assert_eq!(*x, 1);
91             let y: &mut i32 = y;
92             assert_eq!(*y, 2);
93         }
94         EnumProj::Struct { f1, f2 } => {
95             let _: Pin<&mut i32> = f1;
96             let _: &mut i32 = f2;
97             unreachable!();
98         }
99         EnumProj::Unit => unreachable!(),
100     }
101 
102     assert_eq!(&*e, &Enum::Tuple(1, 2));
103 
104     let mut e = Enum::Struct { f1: 3, f2: 4 };
105     let mut e = Pin::new(&mut e);
106 
107     match e.as_mut().project() {
108         EnumProj::Tuple(x, y) => {
109             let _: Pin<&mut i32> = x;
110             let _: &mut i32 = y;
111             unreachable!();
112         }
113         EnumProj::Struct { f1, f2 } => {
114             let _: Pin<&mut i32> = f1;
115             assert_eq!(*f1, 3);
116             let _: &mut i32 = f2;
117             assert_eq!(*f2, 4);
118         }
119         EnumProj::Unit => unreachable!(),
120     }
121 
122     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);
127     }
128 }
129 
130 #[test]
enum_project_set()131 fn enum_project_set() {
132     #[pin_project(project = EnumProj, project_ref = EnumProjRef, project_replace = EnumProjOwn)]
133     #[derive(Eq, PartialEq, Debug)]
134     enum Enum {
135         V1(#[pin] u8),
136         V2(bool),
137     }
138 
139     let mut e = Enum::V1(25);
140     let mut e_orig = Pin::new(&mut e);
141     let e_proj = e_orig.as_mut().project();
142 
143     match e_proj {
144         EnumProj::V1(val) => {
145             let new_e = Enum::V2(val.as_ref().get_ref() == &25);
146             e_orig.set(new_e);
147         }
148         EnumProj::V2(_) => unreachable!(),
149     }
150 
151     assert_eq!(e, Enum::V2(true));
152 }
153 
154 #[test]
where_clause()155 fn where_clause() {
156     #[pin_project]
157     struct Struct<T>
158     where
159         T: Copy,
160     {
161         f: T,
162     }
163 
164     #[pin_project]
165     struct TupleStruct<T>(T)
166     where
167         T: Copy;
168 
169     #[pin_project(project = EnumProj, project_ref = EnumProjRef, project_replace = EnumProjOwn)]
170     enum Enum<T>
171     where
172         T: Copy,
173     {
174         V(T),
175     }
176 }
177 
178 #[test]
where_clause_and_associated_type_field()179 fn where_clause_and_associated_type_field() {
180     #[pin_project(project_replace)]
181     struct Struct1<I>
182     where
183         I: Iterator,
184     {
185         #[pin]
186         f1: I,
187         f2: I::Item,
188     }
189 
190     #[pin_project(project_replace)]
191     struct Struct2<I, J>
192     where
193         I: Iterator<Item = J>,
194     {
195         #[pin]
196         f1: I,
197         f2: J,
198     }
199 
200     #[pin_project(project_replace)]
201     struct Struct3<T>
202     where
203         T: 'static,
204     {
205         f: T,
206     }
207 
208     trait Static: 'static {}
209 
210     impl<T> Static for Struct3<T> {}
211 
212     #[pin_project(project_replace)]
213     struct TupleStruct<I>(#[pin] I, I::Item)
214     where
215         I: Iterator;
216 
217     #[pin_project(project = EnumProj, project_ref = EnumProjRef, project_replace = EnumProjOwn)]
218     enum Enum<I>
219     where
220         I: Iterator,
221     {
222         V1(#[pin] I),
223         V2(I::Item),
224     }
225 }
226 
227 #[test]
derive_copy()228 fn derive_copy() {
229     #[pin_project(project_replace)]
230     #[derive(Clone, Copy)]
231     struct Struct<T> {
232         f: T,
233     }
234 
235     fn is_copy<T: Copy>() {}
236 
237     is_copy::<Struct<u8>>();
238 }
239 
240 #[test]
move_out()241 fn move_out() {
242     struct NotCopy;
243 
244     #[pin_project(project_replace)]
245     struct Struct {
246         f: NotCopy,
247     }
248 
249     let x = Struct { f: NotCopy };
250     let _val: NotCopy = x.f;
251 
252     #[pin_project(project = EnumProj, project_ref = EnumProjRef, project_replace = EnumProjOwn)]
253     enum Enum {
254         V(NotCopy),
255     }
256 
257     let x = Enum::V(NotCopy);
258     #[allow(clippy::infallible_destructuring_match)]
259     let _val: NotCopy = match x {
260         Enum::V(val) => val,
261     };
262 }
263 
264 #[test]
trait_bounds_on_type_generics()265 fn trait_bounds_on_type_generics() {
266     #[pin_project(project_replace)]
267     pub struct Struct1<'a, T: ?Sized> {
268         f: &'a mut T,
269     }
270 
271     #[pin_project(project_replace)]
272     pub struct Struct2<'a, T: ::core::fmt::Debug> {
273         f: &'a mut T,
274     }
275 
276     #[pin_project(project_replace)]
277     pub struct Struct3<'a, T: core::fmt::Debug> {
278         f: &'a mut T,
279     }
280 
281     #[pin_project(project_replace)]
282     pub struct Struct4<'a, T: core::fmt::Debug + core::fmt::Display> {
283         f: &'a mut T,
284     }
285 
286     #[pin_project(project_replace)]
287     pub struct Struct5<'a, T: core::fmt::Debug + ?Sized> {
288         f: &'a mut T,
289     }
290 
291     #[pin_project(project_replace)]
292     pub struct Struct6<'a, T: core::fmt::Debug = [u8; 16]> {
293         f: &'a mut T,
294     }
295 
296     let _: Struct6<'_> = Struct6 { f: &mut [0_u8; 16] };
297 
298     #[pin_project(project_replace)]
299     pub struct Struct7<T: 'static> {
300         f: T,
301     }
302 
303     trait Static: 'static {}
304 
305     impl<T> Static for Struct7<T> {}
306 
307     #[pin_project(project_replace)]
308     pub struct Struct8<'a, 'b: 'a> {
309         f1: &'a u8,
310         f2: &'b u8,
311     }
312 
313     #[pin_project(project_replace)]
314     pub struct TupleStruct<'a, T: ?Sized>(&'a mut T);
315 
316     #[pin_project(project = EnumProj, project_ref = EnumProjRef, project_replace = EnumProjOwn)]
317     enum Enum<'a, T: ?Sized> {
318         V(&'a mut T),
319     }
320 }
321 
322 #[test]
overlapping_lifetime_names()323 fn overlapping_lifetime_names() {
324     #[pin_project(project_replace)]
325     pub struct Struct1<'pin, T> {
326         #[pin]
327         f: &'pin mut T,
328     }
329 
330     #[pin_project(project_replace)]
331     pub struct Struct2<'pin, 'pin_, 'pin__> {
332         #[pin]
333         f: &'pin &'pin_ &'pin__ (),
334     }
335 
336     pub trait Trait<'a> {}
337 
338     #[allow(single_use_lifetimes)] // https://github.com/rust-lang/rust/issues/55058
339     #[pin_project(project_replace)]
340     pub struct Hrtb<'pin___, T>
341     where
342         for<'pin> &'pin T: Unpin,
343         T: for<'pin> Trait<'pin>,
344         for<'pin, 'pin_, 'pin__> &'pin &'pin_ &'pin__ T: Unpin,
345     {
346         #[pin]
347         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 (),
373     }
374 }
375 
376 #[test]
combine()377 fn combine() {
378     #[pin_project(PinnedDrop, UnsafeUnpin)]
379     pub struct PinnedDropWithUnsafeUnpin<T> {
380         #[pin]
381         f: T,
382     }
383 
384     #[pinned_drop]
385     impl<T> PinnedDrop for PinnedDropWithUnsafeUnpin<T> {
386         fn drop(self: Pin<&mut Self>) {}
387     }
388 
389     unsafe impl<T: Unpin> UnsafeUnpin for PinnedDropWithUnsafeUnpin<T> {}
390 
391     #[pin_project(PinnedDrop, !Unpin)]
392     pub struct PinnedDropWithNotUnpin<T> {
393         #[pin]
394         f: T,
395     }
396 
397     #[pinned_drop]
398     impl<T> PinnedDrop for PinnedDropWithNotUnpin<T> {
399         fn drop(self: Pin<&mut Self>) {}
400     }
401 
402     #[pin_project(UnsafeUnpin, project_replace)]
403     pub struct UnsafeUnpinWithReplace<T> {
404         #[pin]
405         f: T,
406     }
407 
408     unsafe impl<T: Unpin> UnsafeUnpin for UnsafeUnpinWithReplace<T> {}
409 
410     #[pin_project(!Unpin, project_replace)]
411     pub struct NotUnpinWithReplace<T> {
412         #[pin]
413         f: T,
414     }
415 }
416 
417 #[test]
private_type_in_public_type()418 fn private_type_in_public_type() {
419     #[pin_project(project_replace)]
420     pub struct PublicStruct<T> {
421         #[pin]
422         inner: PrivateStruct<T>,
423     }
424 
425     struct PrivateStruct<T>(T);
426 }
427 
428 #[allow(clippy::needless_lifetimes)]
429 #[test]
lifetime_project()430 fn lifetime_project() {
431     #[pin_project(project_replace)]
432     struct Struct1<T, U> {
433         #[pin]
434         pinned: T,
435         unpinned: U,
436     }
437 
438     #[pin_project(project_replace)]
439     struct Struct2<'a, T, U> {
440         #[pin]
441         pinned: &'a T,
442         unpinned: U,
443     }
444 
445     #[pin_project(project = EnumProj, project_ref = EnumProjRef, project_replace = EnumProjOwn)]
446     enum Enum<T, U> {
447         V {
448             #[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         }
461         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         }
467     }
468 
469     impl<'b, T, U> Struct2<'b, T, U> {
470         fn get_pin_ref<'a>(self: Pin<&'a Self>) -> Pin<&'a &'b T> {
471             self.project_ref().pinned
472         }
473         fn get_pin_mut<'a>(self: Pin<&'a mut Self>) -> Pin<&'a mut &'b T> {
474             self.project().pinned
475         }
476         fn get_pin_ref_elided(self: Pin<&Self>) -> Pin<&&'b T> {
477             self.project_ref().pinned
478         }
479         fn get_pin_mut_elided(self: Pin<&mut Self>) -> Pin<&mut &'b T> {
480             self.project().pinned
481         }
482     }
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() {
487                 EnumProjRef::V { pinned, .. } => pinned,
488             }
489         }
490         fn get_pin_mut<'a>(self: Pin<&'a mut Self>) -> Pin<&'a mut T> {
491             match self.project() {
492                 EnumProj::V { pinned, .. } => pinned,
493             }
494         }
495         fn get_pin_ref_elided(self: Pin<&Self>) -> Pin<&T> {
496             match self.project_ref() {
497                 EnumProjRef::V { pinned, .. } => pinned,
498             }
499         }
500         fn get_pin_mut_elided(self: Pin<&mut Self>) -> Pin<&mut T> {
501             match self.project() {
502                 EnumProj::V { pinned, .. } => pinned,
503             }
504         }
505     }
506 }
507 
508 mod visibility {
509     use pin_project::pin_project;
510 
511     #[pin_project(project_replace)]
512     pub(crate) struct S {
513         pub f: u8,
514     }
515 }
516 
517 #[test]
visibility()518 fn visibility() {
519     let mut x = visibility::S { f: 0 };
520     let x = Pin::new(&mut x);
521     let y = x.as_ref().project_ref();
522     let _: &u8 = y.f;
523     let y = x.project();
524     let _: &mut u8 = y.f;
525 }
526 
527 #[test]
trivial_bounds()528 fn trivial_bounds() {
529     #[pin_project(project_replace)]
530     pub struct NoGenerics {
531         #[pin]
532         f: PhantomPinned,
533     }
534 
535     assert_not_unpin!(NoGenerics);
536 }
537 
538 #[test]
dst()539 fn dst() {
540     #[pin_project]
541     struct Struct1<T: ?Sized> {
542         f: T,
543     }
544 
545     let mut x = Struct1 { f: 0_u8 };
546     let x: Pin<&mut Struct1<dyn core::fmt::Debug>> = Pin::new(&mut x as _);
547     let _: &mut (dyn core::fmt::Debug) = x.project().f;
548 
549     #[pin_project]
550     struct Struct2<T: ?Sized> {
551         #[pin]
552         f: T,
553     }
554 
555     let mut x = Struct2 { f: 0_u8 };
556     let x: Pin<&mut Struct2<dyn core::fmt::Debug + Unpin>> = Pin::new(&mut x as _);
557     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     }
577 
578     #[pin_project(UnsafeUnpin)]
579     struct Struct5<T: ?Sized> {
580         f: T,
581     }
582 
583     #[pin_project(UnsafeUnpin)]
584     struct Struct6<T: ?Sized> {
585         #[pin]
586         f: T,
587     }
588 
589     #[pin_project(PinnedDrop)]
590     struct Struct7<T: ?Sized> {
591         f: T,
592     }
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]
602         f: T,
603     }
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> {
612         f: T,
613     }
614 
615     #[pin_project(!Unpin)]
616     struct Struct10<T: ?Sized> {
617         #[pin]
618         f: T,
619     }
620 
621     #[pin_project]
622     struct Struct11<'a, T: ?Sized, U: ?Sized> {
623         f1: &'a mut T,
624         f2: U,
625     }
626 
627     #[pin_project]
628     struct TupleStruct1<T: ?Sized>(T);
629 
630     #[pin_project]
631     struct TupleStruct2<T: ?Sized>(#[pin] T);
632 
633     #[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 
645     #[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);
672 
673     #[pin_project]
674     struct TupleStruct11<'a, T: ?Sized, U: ?Sized>(&'a mut T, U);
675 }
676 
677 #[test]
dyn_type()678 fn 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]
parse_self()715 fn parse_self() {
716     macro_rules! mac {
717         ($($tt:tt)*) => {
718             $($tt)*
719         };
720     }
721 
722     pub trait Trait {
723         type Assoc;
724     }
725 
726     #[allow(clippy::type_repetition_in_bounds)]
727     #[pin_project(project_replace)]
728     pub struct Generics<T: Trait<Assoc = Self>>
729     where
730         Self: Trait<Assoc = Self>,
731         <Self as Trait>::Assoc: Sized,
732         mac!(Self): Trait<Assoc = mac!(Self)>,
733     {
734         _f: T,
735     }
736 
737     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 
783     #[pin_project(project = EnumProj, project_ref = EnumProjRef, project_replace = EnumProjOwn)]
784     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;
812     }
813 }
814 
815 #[test]
816 fn no_infer_outlives() {
817     trait Trait<X> {
818         type Y;
819     }
820 
821     struct Struct1<A>(A);
822 
823     impl<X, T> Trait<X> for Struct1<T> {
824         type Y = Option<T>;
825     }
826 
827     #[pin_project(project_replace)]
828     struct Struct2<A, B> {
829         _f: <Struct1<A> as Trait<B>>::Y,
830     }
831 }
832 
833 // https://github.com/rust-lang/rust/issues/47949
834 // https://github.com/taiki-e/pin-project/pull/194#discussion_r419098111
835 #[allow(clippy::many_single_char_names)]
836 #[test]
837 fn project_replace_panic() {
838     #[pin_project(project_replace)]
839     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 {
850                 panic!();
851             }
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) });
860         // Previous `x.pinned` was dropped and panicked when `project_replace` is
861         // called, so this is unreachable.
862         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) });
876             // `_y` (previous `x.unpinned`) live to the end of this scope, so
877             // this is not unreachable.
878             // unreachable!();
879         }
880         unreachable!();
881     }));
882     assert!(res.is_err());
883     assert!(a);
884     assert!(b);
885     assert!(c);
886     assert!(d);
887 }
888