1 // SPDX-License-Identifier: Apache-2.0 OR MIT
2
3 // Original code (./struct-default.rs):
4 //
5 // ```
6 // #![allow(dead_code)]
7 //
8 // use pin_project::pin_project;
9 //
10 // #[pin_project]
11 // struct Struct<T, U> {
12 // #[pin]
13 // pinned: T,
14 // unpinned: U,
15 // }
16 //
17 // fn main() {}
18 // ```
19
20 #![allow(
21 dead_code,
22 unused_imports,
23 unused_parens,
24 unknown_lints,
25 renamed_and_removed_lints,
26 clippy::needless_lifetimes,
27 clippy::undocumented_unsafe_blocks
28 )]
29
30 use pin_project::pin_project;
31
32 // #[pin_project]
33 struct Struct<T, U> {
34 // #[pin]
35 pinned: T,
36 unpinned: U,
37 }
38
39 const _: () = {
40 struct __StructProjection<'pin, T, U>
41 where
42 Struct<T, U>: 'pin,
43 {
44 pinned: ::pin_project::__private::Pin<&'pin mut (T)>,
45 unpinned: &'pin mut (U),
46 }
47 struct __StructProjectionRef<'pin, T, U>
48 where
49 Struct<T, U>: 'pin,
50 {
51 pinned: ::pin_project::__private::Pin<&'pin (T)>,
52 unpinned: &'pin (U),
53 }
54
55 impl<T, U> Struct<T, U> {
project<'pin>( self: ::pin_project::__private::Pin<&'pin mut Self>, ) -> __StructProjection<'pin, T, U>56 fn project<'pin>(
57 self: ::pin_project::__private::Pin<&'pin mut Self>,
58 ) -> __StructProjection<'pin, T, U> {
59 unsafe {
60 let Self { pinned, unpinned } = self.get_unchecked_mut();
61 __StructProjection {
62 pinned: ::pin_project::__private::Pin::new_unchecked(pinned),
63 unpinned,
64 }
65 }
66 }
project_ref<'pin>( self: ::pin_project::__private::Pin<&'pin Self>, ) -> __StructProjectionRef<'pin, T, U>67 fn project_ref<'pin>(
68 self: ::pin_project::__private::Pin<&'pin Self>,
69 ) -> __StructProjectionRef<'pin, T, U> {
70 unsafe {
71 let Self { pinned, unpinned } = self.get_ref();
72 __StructProjectionRef {
73 pinned: ::pin_project::__private::Pin::new_unchecked(pinned),
74 unpinned,
75 }
76 }
77 }
78 }
79
80 // Ensure that it's impossible to use pin projections on a #[repr(packed)]
81 // struct.
82 //
83 // Taking a reference to a packed field is UB, and applying
84 // `#[forbid(unaligned_references)]` makes sure that doing this is a hard error.
85 //
86 // If the struct ends up having #[repr(packed)] applied somehow,
87 // this will generate an (unfriendly) error message. Under all reasonable
88 // circumstances, we'll detect the #[repr(packed)] attribute, and generate
89 // a much nicer error above.
90 //
91 // See https://github.com/taiki-e/pin-project/pull/34 for more details.
92 #[forbid(unaligned_references, safe_packed_borrows)]
__assert_not_repr_packed<T, U>(this: &Struct<T, U>)93 fn __assert_not_repr_packed<T, U>(this: &Struct<T, U>) {
94 let _ = &this.pinned;
95 let _ = &this.unpinned;
96 }
97
98 // Automatically create the appropriate conditional `Unpin` implementation.
99 //
100 // Basically this is equivalent to the following code:
101 //
102 // ```
103 // impl<T, U> Unpin for Struct<T, U> where T: Unpin {}
104 // ```
105 //
106 // However, if struct is public and there is a private type field,
107 // this would cause an E0446 (private type in public interface).
108 //
109 // When RFC 2145 is implemented (rust-lang/rust#48054),
110 // this will become a lint, rather than a hard error.
111 //
112 // As a workaround for this, we generate a new struct, containing all of
113 // the pinned fields from our #[pin_project] type. This struct is declared
114 // within a function, which makes it impossible to be named by user code.
115 // This guarantees that it will use the default auto-trait impl for Unpin -
116 // that is, it will implement Unpin iff all of its fields implement Unpin.
117 // This type can be safely declared as 'public', satisfying the privacy
118 // checker without actually allowing user code to access it.
119 //
120 // This allows users to apply the #[pin_project] attribute to types
121 // regardless of the privacy of the types of their fields.
122 //
123 // See also https://github.com/taiki-e/pin-project/pull/53.
124 struct __Struct<'pin, T, U> {
125 __pin_project_use_generics: ::pin_project::__private::AlwaysUnpin<
126 'pin,
127 (::pin_project::__private::PhantomData<T>, ::pin_project::__private::PhantomData<U>),
128 >,
129 __field0: T,
130 }
131 impl<'pin, T, U> ::pin_project::__private::Unpin for Struct<T, U> where
132 ::pin_project::__private::PinnedFieldsOf<__Struct<'pin, T, U>>:
133 ::pin_project::__private::Unpin
134 {
135 }
136 // A dummy impl of `UnsafeUnpin`, to ensure that the user cannot implement it.
137 //
138 // To ensure that users don't accidentally write a non-functional `UnsafeUnpin`
139 // impls, we emit one ourselves. If the user ends up writing an `UnsafeUnpin`
140 // impl, they'll get a "conflicting implementations of trait" error when
141 // coherence checks are run.
142 #[doc(hidden)]
143 unsafe impl<'pin, T, U> ::pin_project::UnsafeUnpin for Struct<T, U> where
144 ::pin_project::__private::PinnedFieldsOf<__Struct<'pin, T, U>>:
145 ::pin_project::__private::Unpin
146 {
147 }
148
149 // Ensure that struct does not implement `Drop`.
150 //
151 // If you attempt to provide an Drop impl, the blanket impl will
152 // then apply to your type, causing a compile-time error due to
153 // the conflict with the second impl.
154 trait StructMustNotImplDrop {}
155 #[allow(clippy::drop_bounds, drop_bounds)]
156 impl<T: ::pin_project::__private::Drop> StructMustNotImplDrop for T {}
157 impl<T, U> StructMustNotImplDrop for Struct<T, U> {}
158 // A dummy impl of `PinnedDrop`, to ensure that users don't accidentally
159 // write a non-functional `PinnedDrop` impls.
160 #[doc(hidden)]
161 impl<T, U> ::pin_project::__private::PinnedDrop for Struct<T, U> {
drop(self: ::pin_project::__private::Pin<&mut Self>)162 unsafe fn drop(self: ::pin_project::__private::Pin<&mut Self>) {}
163 }
164 };
165
main()166 fn main() {}
167