blob: d6610993d3b9357633233ba2dac655cf8bd0e8f5 [file] [log] [blame]
Chih-Hung Hsieh6f3e9272020-05-13 16:08:03 -07001// Original code (./struct-default.rs):
2//
3// ```rust
4// #![allow(dead_code)]
5//
6// use pin_project::pin_project;
7//
8// #[pin_project]
9// struct Struct<T, U> {
10// #[pin]
11// pinned: T,
12// unpinned: U,
13// }
14//
15// fn main() {}
16// ```
17
Chih-Hung Hsieh127364b2020-10-26 16:54:29 -070018#![allow(dead_code, unused_imports, unused_parens, unknown_lints, renamed_and_removed_lints)]
19#![allow(clippy::needless_lifetimes)]
Chih-Hung Hsieh6f3e9272020-05-13 16:08:03 -070020
21use pin_project::pin_project;
22
Chih-Hung Hsieh127364b2020-10-26 16:54:29 -070023// #[pin_project]
Chih-Hung Hsieh6f3e9272020-05-13 16:08:03 -070024struct Struct<T, U> {
25 // #[pin]
26 pinned: T,
27 unpinned: U,
28}
29
Haibo Huangd58366d2020-07-10 20:23:30 -070030const _: () = {
Chih-Hung Hsieh127364b2020-10-26 16:54:29 -070031 struct __StructProjection<'pin, T, U>
32 where
33 Struct<T, U>: 'pin,
34 {
35 pinned: ::pin_project::__private::Pin<&'pin mut (T)>,
36 unpinned: &'pin mut (U),
37 }
38 struct __StructProjectionRef<'pin, T, U>
39 where
40 Struct<T, U>: 'pin,
41 {
42 pinned: ::pin_project::__private::Pin<&'pin (T)>,
43 unpinned: &'pin (U),
44 }
45
Chih-Hung Hsieh6f3e9272020-05-13 16:08:03 -070046 impl<T, U> Struct<T, U> {
47 fn project<'pin>(
Haibo Huangd58366d2020-07-10 20:23:30 -070048 self: ::pin_project::__private::Pin<&'pin mut Self>,
Chih-Hung Hsieh6f3e9272020-05-13 16:08:03 -070049 ) -> __StructProjection<'pin, T, U> {
50 unsafe {
51 let Self { pinned, unpinned } = self.get_unchecked_mut();
52 __StructProjection {
Haibo Huangd58366d2020-07-10 20:23:30 -070053 pinned: ::pin_project::__private::Pin::new_unchecked(pinned),
Chih-Hung Hsieh6f3e9272020-05-13 16:08:03 -070054 unpinned,
55 }
56 }
57 }
58 fn project_ref<'pin>(
Haibo Huangd58366d2020-07-10 20:23:30 -070059 self: ::pin_project::__private::Pin<&'pin Self>,
Chih-Hung Hsieh6f3e9272020-05-13 16:08:03 -070060 ) -> __StructProjectionRef<'pin, T, U> {
61 unsafe {
62 let Self { pinned, unpinned } = self.get_ref();
63 __StructProjectionRef {
Haibo Huangd58366d2020-07-10 20:23:30 -070064 pinned: ::pin_project::__private::Pin::new_unchecked(pinned),
Chih-Hung Hsieh6f3e9272020-05-13 16:08:03 -070065 unpinned,
66 }
67 }
68 }
69 }
70
Chih-Hung Hsieh127364b2020-10-26 16:54:29 -070071 // Ensure that it's impossible to use pin projections on a #[repr(packed)]
72 // struct.
73 //
Joel Galensonc95dc512021-05-19 16:12:52 -070074 // Taking a reference to a packed field is UB, and applying
75 // `#[forbid(unaligned_references)]` makes sure that doing this is a hard error.
Chih-Hung Hsieh127364b2020-10-26 16:54:29 -070076 //
77 // If the struct ends up having #[repr(packed)] applied somehow,
78 // this will generate an (unfriendly) error message. Under all reasonable
79 // circumstances, we'll detect the #[repr(packed)] attribute, and generate
80 // a much nicer error above.
81 //
82 // See https://github.com/taiki-e/pin-project/pull/34 for more details.
Joel Galensonc95dc512021-05-19 16:12:52 -070083 #[forbid(unaligned_references, safe_packed_borrows)]
Chih-Hung Hsieh127364b2020-10-26 16:54:29 -070084 fn __assert_not_repr_packed<T, U>(this: &Struct<T, U>) {
85 let _ = &this.pinned;
86 let _ = &this.unpinned;
87 }
88
Chih-Hung Hsieh6f3e9272020-05-13 16:08:03 -070089 // Automatically create the appropriate conditional `Unpin` implementation.
90 //
91 // Basically this is equivalent to the following code:
92 //
93 // ```rust
94 // impl<T, U> Unpin for Struct<T, U> where T: Unpin {}
95 // ```
96 //
97 // However, if struct is public and there is a private type field,
98 // this would cause an E0446 (private type in public interface).
99 //
100 // When RFC 2145 is implemented (rust-lang/rust#48054),
101 // this will become a lint, rather then a hard error.
102 //
Haibo Huangd58366d2020-07-10 20:23:30 -0700103 // As a workaround for this, we generate a new struct, containing all of
104 // the pinned fields from our #[pin_project] type. This struct is declared
105 // within a function, which makes it impossible to be named by user code.
Chih-Hung Hsieh6f3e9272020-05-13 16:08:03 -0700106 // This guarantees that it will use the default auto-trait impl for Unpin -
107 // that is, it will implement Unpin iff all of its fields implement Unpin.
108 // This type can be safely declared as 'public', satisfying the privacy
109 // checker without actually allowing user code to access it.
110 //
111 // This allows users to apply the #[pin_project] attribute to types
112 // regardless of the privacy of the types of their fields.
113 //
114 // See also https://github.com/taiki-e/pin-project/pull/53.
115 struct __Struct<'pin, T, U> {
Haibo Huangc9e44562020-07-27 09:15:10 -0700116 __pin_project_use_generics: ::pin_project::__private::AlwaysUnpin<
117 'pin,
118 (::pin_project::__private::PhantomData<T>, ::pin_project::__private::PhantomData<U>),
119 >,
Chih-Hung Hsieh6f3e9272020-05-13 16:08:03 -0700120 __field0: T,
121 }
Haibo Huangd58366d2020-07-10 20:23:30 -0700122 impl<'pin, T, U> ::pin_project::__private::Unpin for Struct<T, U> where
123 __Struct<'pin, T, U>: ::pin_project::__private::Unpin
Chih-Hung Hsieh6f3e9272020-05-13 16:08:03 -0700124 {
125 }
126 // A dummy impl of `UnsafeUnpin`, to ensure that the user cannot implement it.
127 //
128 // To ensure that users don't accidentally write a non-functional `UnsafeUnpin`
Haibo Huangd58366d2020-07-10 20:23:30 -0700129 // impls, we emit one ourselves. If the user ends up writing an `UnsafeUnpin`
130 // impl, they'll get a "conflicting implementations of trait" error when
131 // coherence checks are run.
Chih-Hung Hsieh127364b2020-10-26 16:54:29 -0700132 #[doc(hidden)]
133 unsafe impl<'pin, T, U> ::pin_project::UnsafeUnpin for Struct<T, U> where
134 __Struct<'pin, T, U>: ::pin_project::__private::Unpin
135 {
136 }
Chih-Hung Hsieh6f3e9272020-05-13 16:08:03 -0700137
138 // Ensure that struct does not implement `Drop`.
139 //
140 // If you attempt to provide an Drop impl, the blanket impl will
141 // then apply to your type, causing a compile-time error due to
142 // the conflict with the second impl.
143 trait StructMustNotImplDrop {}
Chih-Hung Hsieh127364b2020-10-26 16:54:29 -0700144 #[allow(clippy::drop_bounds, drop_bounds)]
Haibo Huangd58366d2020-07-10 20:23:30 -0700145 impl<T: ::pin_project::__private::Drop> StructMustNotImplDrop for T {}
Chih-Hung Hsieh6f3e9272020-05-13 16:08:03 -0700146 impl<T, U> StructMustNotImplDrop for Struct<T, U> {}
147 // A dummy impl of `PinnedDrop`, to ensure that users don't accidentally
148 // write a non-functional `PinnedDrop` impls.
Chih-Hung Hsieh127364b2020-10-26 16:54:29 -0700149 #[doc(hidden)]
Chih-Hung Hsieh6f3e9272020-05-13 16:08:03 -0700150 impl<T, U> ::pin_project::__private::PinnedDrop for Struct<T, U> {
Haibo Huangd58366d2020-07-10 20:23:30 -0700151 unsafe fn drop(self: ::pin_project::__private::Pin<&mut Self>) {}
Chih-Hung Hsieh6f3e9272020-05-13 16:08:03 -0700152 }
Chih-Hung Hsieh6f3e9272020-05-13 16:08:03 -0700153};
154
155fn main() {}