aboutsummaryrefslogtreecommitdiff
path: root/examples
diff options
context:
space:
mode:
authorChih-Hung Hsieh <chh@google.com>2020-05-13 16:08:03 -0700
committerChih-Hung Hsieh <chh@google.com>2020-05-13 16:08:03 -0700
commit6f3e9271b123f94f158b1f000c996a558351320f (patch)
treec0d427205c0f0002d86155721cc4f8de67c4fbe5 /examples
parent2e1ed433d835e9f8409237243b8c03b0be6a1310 (diff)
downloadpin-project-6f3e9271b123f94f158b1f000c996a558351320f.tar.gz
Import 'pin-project' package version 0.4.16
* Add OWNERS and Android.bp Bug: 156165390 Test: make Change-Id: I8ace68f978b2725ad91e0f64282003fa453674ca
Diffstat (limited to 'examples')
-rw-r--r--examples/README.md35
-rw-r--r--examples/enum-default-expanded.rs109
-rw-r--r--examples/enum-default.rs13
-rw-r--r--examples/not_unpin-expanded.rs125
-rw-r--r--examples/not_unpin.rs17
-rw-r--r--examples/pinned_drop-expanded.rs154
-rw-r--r--examples/pinned_drop.rs22
-rw-r--r--examples/project_replace-expanded.rs158
-rw-r--r--examples/project_replace.rs14
-rw-r--r--examples/struct-default-expanded.rs157
-rw-r--r--examples/struct-default.rs14
-rw-r--r--examples/unsafe_unpin-expanded.rs111
-rw-r--r--examples/unsafe_unpin.rs16
13 files changed, 945 insertions, 0 deletions
diff --git a/examples/README.md b/examples/README.md
new file mode 100644
index 0000000..94f49b5
--- /dev/null
+++ b/examples/README.md
@@ -0,0 +1,35 @@
+# Examples and generated code of each feature of pin-project
+
+### Basic usage of `#[pin_project]` on structs
+
+ * [example](struct-default.rs)
+ * [generated code](struct-default-expanded.rs)
+
+### Basic usage of `#[pin_project]` on enums
+
+ * [example](enum-default.rs)
+ * [generated code](enum-default-expanded.rs)
+
+### Manual implementation of `Unpin` by `UnsafeUnpin`
+
+ * [example](unsafe_unpin.rs)
+ * [generated code](unsafe_unpin-expanded.rs)
+ * [`UnsafeUnpin` documentation](https://docs.rs/pin-project/0.4/pin_project/trait.UnsafeUnpin.html)
+
+### Manual implementation of `Drop` by `#[pinned_drop]`
+
+ * [example](pinned_drop.rs)
+ * [generated code](pinned_drop-expanded.rs)
+ * [`#[pinned_drop]` documentation](https://docs.rs/pin-project/0.4/pin_project/attr.pinned_drop.html)
+
+### `project_replace()` method
+
+ * [example](project_replace.rs)
+ * [generated code](project_replace-expanded.rs)
+ * [`project_replace()` documentation](https://docs.rs/pin-project/0.4/pin_project/attr.pin_project.html#project_replace)
+
+### Ensure `!Unpin` by `#[pin_project(!Unpin)]`
+
+ * [example](not_unpin.rs)
+ * [generated code](not_unpin-expanded.rs)
+ * [`!Unpin` documentation](https://docs.rs/pin-project/0.4/pin_project/attr.pin_project.html#unpin)
diff --git a/examples/enum-default-expanded.rs b/examples/enum-default-expanded.rs
new file mode 100644
index 0000000..036c01f
--- /dev/null
+++ b/examples/enum-default-expanded.rs
@@ -0,0 +1,109 @@
+// Original code (./enum-default.rs):
+//
+// ```rust
+// #![allow(dead_code)]
+//
+// use pin_project::pin_project;
+//
+// #[pin_project]
+// enum Enum<T, U> {
+// Pinned(#[pin] T),
+// Unpinned(U),
+// }
+//
+// fn main() {}
+// ```
+
+#![allow(dead_code, unused_imports, unused_parens)]
+#![allow(clippy::no_effect, clippy::just_underscores_and_digits)]
+
+use pin_project::pin_project;
+
+enum Enum<T, U> {
+ Pinned(/* #[pin] */ T),
+ Unpinned(U),
+}
+
+#[doc(hidden)]
+#[allow(clippy::mut_mut)] // This lint warns `&mut &mut <ty>`.
+#[allow(dead_code)] // This lint warns unused fields/variants.
+#[allow(single_use_lifetimes)]
+enum __EnumProjection<'pin, T, U>
+where
+ Enum<T, U>: 'pin,
+{
+ Pinned(::pin_project::__reexport::pin::Pin<&'pin mut (T)>),
+ Unpinned(&'pin mut (U)),
+}
+#[doc(hidden)]
+#[allow(dead_code)] // This lint warns unused fields/variants.
+#[allow(single_use_lifetimes)]
+enum __EnumProjectionRef<'pin, T, U>
+where
+ Enum<T, U>: 'pin,
+{
+ Pinned(::pin_project::__reexport::pin::Pin<&'pin (T)>),
+ Unpinned(&'pin (U)),
+}
+
+#[doc(hidden)]
+#[allow(non_upper_case_globals)]
+#[allow(single_use_lifetimes)]
+const __SCOPE_Enum: () = {
+ impl<T, U> Enum<T, U> {
+ fn project<'pin>(
+ self: ::pin_project::__reexport::pin::Pin<&'pin mut Self>,
+ ) -> __EnumProjection<'pin, T, U> {
+ unsafe {
+ match self.get_unchecked_mut() {
+ Enum::Pinned(_0) => __EnumProjection::Pinned(
+ ::pin_project::__reexport::pin::Pin::new_unchecked(_0),
+ ),
+ Enum::Unpinned(_0) => __EnumProjection::Unpinned(_0),
+ }
+ }
+ }
+ fn project_ref<'pin>(
+ self: ::pin_project::__reexport::pin::Pin<&'pin Self>,
+ ) -> __EnumProjectionRef<'pin, T, U> {
+ unsafe {
+ match self.get_ref() {
+ Enum::Pinned(_0) => __EnumProjectionRef::Pinned(
+ ::pin_project::__reexport::pin::Pin::new_unchecked(_0),
+ ),
+ Enum::Unpinned(_0) => __EnumProjectionRef::Unpinned(_0),
+ }
+ }
+ }
+ }
+
+ // Automatically create the appropriate conditional `Unpin` implementation.
+ //
+ // See ./struct-default-expanded.rs and https://github.com/taiki-e/pin-project/pull/53.
+ // for details.
+ struct __Enum<'pin, T, U> {
+ __pin_project_use_generics: ::pin_project::__private::AlwaysUnpin<'pin, (T, U)>,
+ __field0: T,
+ }
+ impl<'pin, T, U> ::pin_project::__reexport::marker::Unpin for Enum<T, U> where
+ __Enum<'pin, T, U>: ::pin_project::__reexport::marker::Unpin
+ {
+ }
+ unsafe impl<T, U> ::pin_project::UnsafeUnpin for Enum<T, U> {}
+
+ // Ensure that enum does not implement `Drop`.
+ //
+ // See ./struct-default-expanded.rs for details.
+ trait EnumMustNotImplDrop {}
+ #[allow(clippy::drop_bounds)]
+ impl<T: ::pin_project::__reexport::ops::Drop> EnumMustNotImplDrop for T {}
+ impl<T, U> EnumMustNotImplDrop for Enum<T, U> {}
+ impl<T, U> ::pin_project::__private::PinnedDrop for Enum<T, U> {
+ unsafe fn drop(self: ::pin_project::__reexport::pin::Pin<&mut Self>) {}
+ }
+
+ // We don't need to check for `#[repr(packed)]`,
+ // since it does not apply to enums.
+};
+
+fn main() {}
diff --git a/examples/enum-default.rs b/examples/enum-default.rs
new file mode 100644
index 0000000..ab5a4bc
--- /dev/null
+++ b/examples/enum-default.rs
@@ -0,0 +1,13 @@
+// See ./enum-default-expanded.rs for generated code.
+
+#![allow(dead_code)]
+
+use pin_project::pin_project;
+
+#[pin_project]
+enum Enum<T, U> {
+ Pinned(#[pin] T),
+ Unpinned(U),
+}
+
+fn main() {}
diff --git a/examples/not_unpin-expanded.rs b/examples/not_unpin-expanded.rs
new file mode 100644
index 0000000..45f1321
--- /dev/null
+++ b/examples/not_unpin-expanded.rs
@@ -0,0 +1,125 @@
+// Original code (./not_unpin.rs):
+//
+// ```rust
+// #![allow(dead_code)]
+//
+// use pin_project::pin_project;
+//
+// #[pin_project(!Unpin)]
+// pub struct Struct<T, U> {
+// #[pin]
+// pinned: T,
+// unpinned: U,
+// }
+//
+// fn main() {
+// fn _is_unpin<T: Unpin>() {}
+// // _is_unpin::<Struct<(), ()>>(); //~ ERROR `std::marker::PhantomPinned` cannot be unpinned
+// }
+// ```
+
+#![allow(dead_code, unused_imports, unused_parens)]
+#![allow(clippy::no_effect)]
+
+use pin_project::pin_project;
+
+pub struct Struct<T, U> {
+ // #[pin]
+ pinned: T,
+ unpinned: U,
+}
+
+#[doc(hidden)]
+#[allow(clippy::mut_mut)] // This lint warns `&mut &mut <ty>`.
+#[allow(dead_code)] // This lint warns unused fields/variants.
+#[allow(single_use_lifetimes)]
+pub(crate) struct __StructProjection<'pin, T, U>
+where
+ Struct<T, U>: 'pin,
+{
+ pinned: ::pin_project::__reexport::pin::Pin<&'pin mut (T)>,
+ unpinned: &'pin mut (U),
+}
+#[doc(hidden)]
+#[allow(dead_code)] // This lint warns unused fields/variants.
+#[allow(single_use_lifetimes)]
+pub(crate) struct __StructProjectionRef<'pin, T, U>
+where
+ Struct<T, U>: 'pin,
+{
+ pinned: ::pin_project::__reexport::pin::Pin<&'pin (T)>,
+ unpinned: &'pin (U),
+}
+
+#[doc(hidden)]
+#[allow(non_upper_case_globals)]
+#[allow(single_use_lifetimes)]
+const __SCOPE_Struct: () = {
+ impl<T, U> Struct<T, U> {
+ pub(crate) fn project<'pin>(
+ self: ::pin_project::__reexport::pin::Pin<&'pin mut Self>,
+ ) -> __StructProjection<'pin, T, U> {
+ unsafe {
+ let Self { pinned, unpinned } = self.get_unchecked_mut();
+ __StructProjection {
+ pinned: ::pin_project::__reexport::pin::Pin::new_unchecked(pinned),
+ unpinned,
+ }
+ }
+ }
+ pub(crate) fn project_ref<'pin>(
+ self: ::pin_project::__reexport::pin::Pin<&'pin Self>,
+ ) -> __StructProjectionRef<'pin, T, U> {
+ unsafe {
+ let Self { pinned, unpinned } = self.get_ref();
+ __StructProjectionRef {
+ pinned: ::pin_project::__reexport::pin::Pin::new_unchecked(pinned),
+ unpinned,
+ }
+ }
+ }
+ }
+
+ // Create `Unpin` impl that has trivial `Unpin` bounds.
+ //
+ // See https://github.com/taiki-e/pin-project/issues/102#issuecomment-540472282
+ // for details.
+ impl<'pin, T, U> ::pin_project::__reexport::marker::Unpin for Struct<T, U> where
+ ::pin_project::__private::Wrapper<'pin, ::pin_project::__reexport::marker::PhantomPinned>:
+ ::pin_project::__reexport::marker::Unpin
+ {
+ }
+ // A dummy impl of `UnsafeUnpin`, to ensure that the user cannot implement it.
+ //
+ // To ensure that users don't accidentally write a non-functional `UnsafeUnpin`
+ // impls, we emit one ourselves. If the user ends up writing a `UnsafeUnpin` impl,
+ // they'll get a "conflicting implementations of trait" error when coherence
+ // checks are run.
+ unsafe impl<T, U> ::pin_project::UnsafeUnpin for Struct<T, U> {}
+
+ // Ensure that struct does not implement `Drop`.
+ //
+ // See ./struct-default-expanded.rs for details.
+ trait StructMustNotImplDrop {}
+ #[allow(clippy::drop_bounds)]
+ impl<T: ::pin_project::__reexport::ops::Drop> StructMustNotImplDrop for T {}
+ impl<T, U> StructMustNotImplDrop for Struct<T, U> {}
+ impl<T, U> ::pin_project::__private::PinnedDrop for Struct<T, U> {
+ unsafe fn drop(self: ::pin_project::__reexport::pin::Pin<&mut Self>) {}
+ }
+
+ // Ensure that it's impossible to use pin projections on a #[repr(packed)] struct.
+ //
+ // See ./struct-default-expanded.rs and https://github.com/taiki-e/pin-project/pull/34
+ // for details.
+ #[deny(safe_packed_borrows)]
+ fn __assert_not_repr_packed<T, U>(val: &Struct<T, U>) {
+ &val.pinned;
+ &val.unpinned;
+ }
+};
+
+fn main() {
+ fn _is_unpin<T: Unpin>() {}
+ // _is_unpin::<Struct<(), ()>>(); //~ ERROR `std::marker::PhantomPinned` cannot be unpinned
+}
diff --git a/examples/not_unpin.rs b/examples/not_unpin.rs
new file mode 100644
index 0000000..2ad72a8
--- /dev/null
+++ b/examples/not_unpin.rs
@@ -0,0 +1,17 @@
+// See ./not_unpin-expanded.rs for generated code.
+
+#![allow(dead_code)]
+
+use pin_project::pin_project;
+
+#[pin_project(!Unpin)]
+pub struct Struct<T, U> {
+ #[pin]
+ pinned: T,
+ unpinned: U,
+}
+
+fn main() {
+ fn _is_unpin<T: Unpin>() {}
+ // _is_unpin::<Struct<(), ()>>(); //~ ERROR `std::marker::PhantomPinned` cannot be unpinned
+}
diff --git a/examples/pinned_drop-expanded.rs b/examples/pinned_drop-expanded.rs
new file mode 100644
index 0000000..15dde89
--- /dev/null
+++ b/examples/pinned_drop-expanded.rs
@@ -0,0 +1,154 @@
+// Original code (./pinned_drop.rs):
+//
+// ```rust
+// #![allow(dead_code)]
+//
+// use pin_project::{pin_project, pinned_drop};
+// use std::pin::Pin;
+//
+// #[pin_project(PinnedDrop)]
+// pub struct Struct<'a, T> {
+// was_dropped: &'a mut bool,
+// #[pin]
+// field: T,
+// }
+//
+// #[pinned_drop]
+// fn drop_Struct<T>(mut this: Pin<&mut Struct<'_, T>>) {
+// **this.project().was_dropped = true;
+// }
+//
+// fn main() {}
+// ```
+
+#![allow(dead_code, unused_imports, unused_parens)]
+#![allow(clippy::no_effect)]
+
+use pin_project::{pin_project, pinned_drop};
+use std::pin::Pin;
+
+pub struct Struct<'a, T> {
+ was_dropped: &'a mut bool,
+ // #[pin]
+ field: T,
+}
+
+#[doc(hidden)]
+#[allow(clippy::mut_mut)] // This lint warns `&mut &mut <ty>`.
+#[allow(dead_code)] // This lint warns unused fields/variants.
+#[allow(single_use_lifetimes)]
+pub(crate) struct __StructProjection<'pin, 'a, T>
+where
+ Struct<'a, T>: 'pin,
+{
+ was_dropped: &'pin mut (&'a mut bool),
+ field: ::pin_project::__reexport::pin::Pin<&'pin mut (T)>,
+}
+#[doc(hidden)]
+#[allow(dead_code)] // This lint warns unused fields/variants.
+#[allow(single_use_lifetimes)]
+pub(crate) struct __StructProjectionRef<'pin, 'a, T>
+where
+ Struct<'a, T>: 'pin,
+{
+ was_dropped: &'pin (&'a mut bool),
+ field: ::pin_project::__reexport::pin::Pin<&'pin (T)>,
+}
+
+#[doc(hidden)]
+#[allow(non_upper_case_globals)]
+#[allow(single_use_lifetimes)]
+const __SCOPE_Struct: () = {
+ impl<'a, T> Struct<'a, T> {
+ pub(crate) fn project<'pin>(
+ self: ::pin_project::__reexport::pin::Pin<&'pin mut Self>,
+ ) -> __StructProjection<'pin, 'a, T> {
+ unsafe {
+ let Self { was_dropped, field } = self.get_unchecked_mut();
+ __StructProjection {
+ was_dropped,
+ field: ::pin_project::__reexport::pin::Pin::new_unchecked(field),
+ }
+ }
+ }
+ pub(crate) fn project_ref<'pin>(
+ self: ::pin_project::__reexport::pin::Pin<&'pin Self>,
+ ) -> __StructProjectionRef<'pin, 'a, T> {
+ unsafe {
+ let Self { was_dropped, field } = self.get_ref();
+ __StructProjectionRef {
+ was_dropped,
+ field: ::pin_project::__reexport::pin::Pin::new_unchecked(field),
+ }
+ }
+ }
+ }
+
+ impl<'a, T> ::pin_project::__reexport::ops::Drop for Struct<'a, T> {
+ fn drop(&mut self) {
+ // Safety - we're in 'drop', so we know that 'self' will
+ // never move again.
+ let pinned_self = unsafe { ::pin_project::__reexport::pin::Pin::new_unchecked(self) };
+ // We call `pinned_drop` only once. Since `PinnedDrop::drop`
+ // is an unsafe method and a private API, it is never called again in safe
+ // code *unless the user uses a maliciously crafted macro*.
+ unsafe {
+ ::pin_project::__private::PinnedDrop::drop(pinned_self);
+ }
+ }
+ }
+
+ // Automatically create the appropriate conditional `Unpin` implementation.
+ //
+ // See ./struct-default-expanded.rs and https://github.com/taiki-e/pin-project/pull/53.
+ // for details.
+ pub struct __Struct<'pin, 'a, T> {
+ __pin_project_use_generics: ::pin_project::__private::AlwaysUnpin<'pin, (T)>,
+ __field0: T,
+ __lifetime0: &'a (),
+ }
+ impl<'pin, 'a, T> ::pin_project::__reexport::marker::Unpin for Struct<'a, T> where
+ __Struct<'pin, 'a, T>: ::pin_project::__reexport::marker::Unpin
+ {
+ }
+ unsafe impl<'a, T> ::pin_project::UnsafeUnpin for Struct<'a, T> {}
+
+ // Ensure that it's impossible to use pin projections on a #[repr(packed)] struct.
+ //
+ // See ./struct-default-expanded.rs and https://github.com/taiki-e/pin-project/pull/34
+ // for details.
+ #[deny(safe_packed_borrows)]
+ fn __assert_not_repr_packed<'a, T>(val: &Struct<'a, T>) {
+ &val.was_dropped;
+ &val.field;
+ }
+};
+
+// Implementing `PinnedDrop::drop` is safe, but calling it is not safe.
+// This is because destructors can be called multiple times in safe code and
+// [double dropping is unsound](https://github.com/rust-lang/rust/pull/62360).
+//
+// Ideally, it would be desirable to be able to forbid manual calls in
+// the same way as `Drop::drop`, but the library cannot do it. So, by using
+// macros and replacing them with private traits, we prevent users from
+// calling `PinnedDrop::drop`.
+//
+// Users can implement [`Drop`] safely using `#[pinned_drop]` and can drop a
+// type that implements `PinnedDrop` using the [`drop`] function safely.
+// **Do not call or implement this trait directly.**
+impl<T> ::pin_project::__private::PinnedDrop for Struct<'_, T> {
+ // Since calling it twice on the same object would be UB,
+ // this method is unsafe.
+ unsafe fn drop(self: Pin<&mut Self>) {
+ #[allow(clippy::needless_pass_by_value)]
+ fn __drop_inner<T>(__self: Pin<&mut Struct<'_, T>>) {
+ // A dummy `__drop_inner` function to prevent users call outer `__drop_inner`.
+ fn __drop_inner() {}
+
+ **__self.project().was_dropped = true;
+ }
+ __drop_inner(self);
+ }
+}
+
+fn main() {}
diff --git a/examples/pinned_drop.rs b/examples/pinned_drop.rs
new file mode 100644
index 0000000..4dfd228
--- /dev/null
+++ b/examples/pinned_drop.rs
@@ -0,0 +1,22 @@
+// See ./pinned_drop-expanded.rs for generated code.
+
+#![allow(dead_code)]
+
+use pin_project::{pin_project, pinned_drop};
+use std::pin::Pin;
+
+#[pin_project(PinnedDrop)]
+pub struct Struct<'a, T> {
+ was_dropped: &'a mut bool,
+ #[pin]
+ field: T,
+}
+
+#[pinned_drop]
+impl<T> PinnedDrop for Struct<'_, T> {
+ fn drop(self: Pin<&mut Self>) {
+ **self.project().was_dropped = true;
+ }
+}
+
+fn main() {}
diff --git a/examples/project_replace-expanded.rs b/examples/project_replace-expanded.rs
new file mode 100644
index 0000000..ec9f00e
--- /dev/null
+++ b/examples/project_replace-expanded.rs
@@ -0,0 +1,158 @@
+// Original code (./struct-default.rs):
+//
+// ```rust
+// #![allow(dead_code)]
+//
+// use pin_project::pin_project;
+//
+// #[pin_project(Replace)]
+// struct Struct<T, U> {
+// #[pin]
+// pinned: T,
+// unpinned: U,
+// }
+//
+// fn main() {}
+// ```
+
+#![allow(dead_code, unused_imports, unused_parens)]
+#![allow(clippy::no_effect)]
+
+use pin_project::pin_project;
+
+struct Struct<T, U> {
+ // #[pin]
+ pinned: T,
+ unpinned: U,
+}
+
+#[doc(hidden)]
+#[allow(clippy::mut_mut)] // This lint warns `&mut &mut <ty>`.
+#[allow(dead_code)] // This lint warns unused fields/variants.
+#[allow(single_use_lifetimes)]
+struct __StructProjection<'pin, T, U>
+where
+ Struct<T, U>: 'pin,
+{
+ pinned: ::pin_project::__reexport::pin::Pin<&'pin mut (T)>,
+ unpinned: &'pin mut (U),
+}
+#[doc(hidden)]
+#[allow(dead_code)] // This lint warns unused fields/variants.
+#[allow(single_use_lifetimes)]
+struct __StructProjectionRef<'pin, T, U>
+where
+ Struct<T, U>: 'pin,
+{
+ pinned: ::pin_project::__reexport::pin::Pin<&'pin (T)>,
+ unpinned: &'pin (U),
+}
+
+#[doc(hidden)]
+#[allow(dead_code)] // This lint warns unused fields/variants.
+#[allow(single_use_lifetimes)]
+struct __StructProjectionOwned<T, U> {
+ pinned: ::pin_project::__reexport::marker::PhantomData<T>,
+ unpinned: U,
+}
+
+#[doc(hidden)]
+#[allow(non_upper_case_globals)]
+#[allow(single_use_lifetimes)]
+const __SCOPE_Struct: () = {
+ impl<T, U> Struct<T, U> {
+ fn project<'pin>(
+ self: ::pin_project::__reexport::pin::Pin<&'pin mut Self>,
+ ) -> __StructProjection<'pin, T, U> {
+ unsafe {
+ let Self { pinned, unpinned } = self.get_unchecked_mut();
+ __StructProjection {
+ pinned: ::pin_project::__reexport::pin::Pin::new_unchecked(pinned),
+ unpinned,
+ }
+ }
+ }
+ fn project_ref<'pin>(
+ self: ::pin_project::__reexport::pin::Pin<&'pin Self>,
+ ) -> __StructProjectionRef<'pin, T, U> {
+ unsafe {
+ let Self { pinned, unpinned } = self.get_ref();
+ __StructProjectionRef {
+ pinned: ::pin_project::__reexport::pin::Pin::new_unchecked(pinned),
+ unpinned,
+ }
+ }
+ }
+ fn project_replace(
+ self: ::pin_project::__reexport::pin::Pin<&mut Self>,
+ __replacement: Self,
+ ) -> __StructProjectionOwned<T, U> {
+ unsafe {
+ let __self_ptr: *mut Self = self.get_unchecked_mut();
+ let Self { pinned, unpinned } = &mut *__self_ptr;
+
+ // First, extract all the unpinned fields
+ let __result = __StructProjectionOwned {
+ pinned: ::pin_project::__reexport::marker::PhantomData,
+ unpinned: ::pin_project::__reexport::ptr::read(unpinned),
+ };
+
+ // Destructors will run in reverse order, so next create a guard to overwrite
+ // `self` with the replacement value without calling destructors.
+ let __guard = ::pin_project::__private::UnsafeOverwriteGuard {
+ target: __self_ptr,
+ value: ::pin_project::__reexport::mem::ManuallyDrop::new(__replacement),
+ };
+
+ // Now create guards to drop all the pinned fields
+ //
+ // Due to a compiler bug (https://github.com/rust-lang/rust/issues/47949)
+ // this must be in its own scope, or else `__result` will not be dropped
+ // if any of the destructors panic.
+ {
+ let __guard = ::pin_project::__private::UnsafeDropInPlaceGuard(pinned);
+ }
+
+ // Finally, return the result
+ __result
+ }
+ }
+ }
+
+ // Automatically create the appropriate conditional `Unpin` implementation.
+ //
+ // See ./struct-default-expanded.rs and https://github.com/taiki-e/pin-project/pull/53.
+ // for details.
+ struct __Struct<'pin, T, U> {
+ __pin_project_use_generics: ::pin_project::__private::AlwaysUnpin<'pin, (T, U)>,
+ __field0: T,
+ }
+ impl<'pin, T, U> ::pin_project::__reexport::marker::Unpin for Struct<T, U> where
+ __Struct<'pin, T, U>: ::pin_project::__reexport::marker::Unpin
+ {
+ }
+ unsafe impl<T, U> ::pin_project::UnsafeUnpin for Struct<T, U> {}
+
+ // Ensure that struct does not implement `Drop`.
+ //
+ // See ./struct-default-expanded.rs for details.
+ trait StructMustNotImplDrop {}
+ #[allow(clippy::drop_bounds)]
+ impl<T: ::pin_project::__reexport::ops::Drop> StructMustNotImplDrop for T {}
+ impl<T, U> StructMustNotImplDrop for Struct<T, U> {}
+ impl<T, U> ::pin_project::__private::PinnedDrop for Struct<T, U> {
+ unsafe fn drop(self: ::pin_project::__reexport::pin::Pin<&mut Self>) {}
+ }
+
+ // Ensure that it's impossible to use pin projections on a #[repr(packed)] struct.
+ //
+ // See ./struct-default-expanded.rs and https://github.com/taiki-e/pin-project/pull/34
+ // for details.
+ #[deny(safe_packed_borrows)]
+ fn __assert_not_repr_packed<T, U>(val: &Struct<T, U>) {
+ &val.pinned;
+ &val.unpinned;
+ }
+};
+
+fn main() {}
diff --git a/examples/project_replace.rs b/examples/project_replace.rs
new file mode 100644
index 0000000..4482625
--- /dev/null
+++ b/examples/project_replace.rs
@@ -0,0 +1,14 @@
+// See ./struct-default-expanded.rs for generated code.
+
+#![allow(dead_code)]
+
+use pin_project::pin_project;
+
+#[pin_project(Replace)]
+struct Struct<T, U> {
+ #[pin]
+ pinned: T,
+ unpinned: U,
+}
+
+fn main() {}
diff --git a/examples/struct-default-expanded.rs b/examples/struct-default-expanded.rs
new file mode 100644
index 0000000..2bf7edd
--- /dev/null
+++ b/examples/struct-default-expanded.rs
@@ -0,0 +1,157 @@
+// Original code (./struct-default.rs):
+//
+// ```rust
+// #![allow(dead_code)]
+//
+// use pin_project::pin_project;
+//
+// #[pin_project]
+// struct Struct<T, U> {
+// #[pin]
+// pinned: T,
+// unpinned: U,
+// }
+//
+// fn main() {}
+// ```
+
+#![allow(dead_code, unused_imports, unused_parens)]
+#![allow(clippy::no_effect)]
+
+use pin_project::pin_project;
+
+struct Struct<T, U> {
+ // #[pin]
+ pinned: T,
+ unpinned: U,
+}
+
+#[doc(hidden)]
+#[allow(clippy::mut_mut)] // This lint warns `&mut &mut <ty>`.
+#[allow(dead_code)] // This lint warns unused fields/variants.
+#[allow(single_use_lifetimes)]
+struct __StructProjection<'pin, T, U>
+where
+ Struct<T, U>: 'pin,
+{
+ pinned: ::pin_project::__reexport::pin::Pin<&'pin mut (T)>,
+ unpinned: &'pin mut (U),
+}
+#[doc(hidden)]
+#[allow(dead_code)] // This lint warns unused fields/variants.
+#[allow(single_use_lifetimes)]
+struct __StructProjectionRef<'pin, T, U>
+where
+ Struct<T, U>: 'pin,
+{
+ pinned: ::pin_project::__reexport::pin::Pin<&'pin (T)>,
+ unpinned: &'pin (U),
+}
+
+#[doc(hidden)]
+#[allow(non_upper_case_globals)]
+#[allow(single_use_lifetimes)]
+const __SCOPE_Struct: () = {
+ impl<T, U> Struct<T, U> {
+ fn project<'pin>(
+ self: ::pin_project::__reexport::pin::Pin<&'pin mut Self>,
+ ) -> __StructProjection<'pin, T, U> {
+ unsafe {
+ let Self { pinned, unpinned } = self.get_unchecked_mut();
+ __StructProjection {
+ pinned: ::pin_project::__reexport::pin::Pin::new_unchecked(pinned),
+ unpinned,
+ }
+ }
+ }
+ fn project_ref<'pin>(
+ self: ::pin_project::__reexport::pin::Pin<&'pin Self>,
+ ) -> __StructProjectionRef<'pin, T, U> {
+ unsafe {
+ let Self { pinned, unpinned } = self.get_ref();
+ __StructProjectionRef {
+ pinned: ::pin_project::__reexport::pin::Pin::new_unchecked(pinned),
+ unpinned,
+ }
+ }
+ }
+ }
+
+ // Automatically create the appropriate conditional `Unpin` implementation.
+ //
+ // Basically this is equivalent to the following code:
+ //
+ // ```rust
+ // impl<T, U> Unpin for Struct<T, U> where T: Unpin {}
+ // ```
+ //
+ // However, if struct is public and there is a private type field,
+ // this would cause an E0446 (private type in public interface).
+ //
+ // When RFC 2145 is implemented (rust-lang/rust#48054),
+ // this will become a lint, rather then a hard error.
+ //
+ // As a workaround for this, we generate a new struct, containing all of the pinned
+ // fields from our #[pin_project] type. This struct is declared within
+ // a function, which makes it impossible to be named by user code.
+ // This guarantees that it will use the default auto-trait impl for Unpin -
+ // that is, it will implement Unpin iff all of its fields implement Unpin.
+ // This type can be safely declared as 'public', satisfying the privacy
+ // checker without actually allowing user code to access it.
+ //
+ // This allows users to apply the #[pin_project] attribute to types
+ // regardless of the privacy of the types of their fields.
+ //
+ // See also https://github.com/taiki-e/pin-project/pull/53.
+ struct __Struct<'pin, T, U> {
+ __pin_project_use_generics: ::pin_project::__private::AlwaysUnpin<'pin, (T, U)>,
+ __field0: T,
+ }
+ impl<'pin, T, U> ::pin_project::__reexport::marker::Unpin for Struct<T, U> where
+ __Struct<'pin, T, U>: ::pin_project::__reexport::marker::Unpin
+ {
+ }
+ // A dummy impl of `UnsafeUnpin`, to ensure that the user cannot implement it.
+ //
+ // To ensure that users don't accidentally write a non-functional `UnsafeUnpin`
+ // impls, we emit one ourselves. If the user ends up writing a `UnsafeUnpin` impl,
+ // they'll get a "conflicting implementations of trait" error when coherence
+ // checks are run.
+ unsafe impl<T, U> ::pin_project::UnsafeUnpin for Struct<T, U> {}
+
+ // Ensure that struct does not implement `Drop`.
+ //
+ // If you attempt to provide an Drop impl, the blanket impl will
+ // then apply to your type, causing a compile-time error due to
+ // the conflict with the second impl.
+ trait StructMustNotImplDrop {}
+ #[allow(clippy::drop_bounds)]
+ impl<T: ::pin_project::__reexport::ops::Drop> StructMustNotImplDrop for T {}
+ impl<T, U> StructMustNotImplDrop for Struct<T, U> {}
+ // A dummy impl of `PinnedDrop`, to ensure that users don't accidentally
+ // write a non-functional `PinnedDrop` impls.
+ impl<T, U> ::pin_project::__private::PinnedDrop for Struct<T, U> {
+ unsafe fn drop(self: ::pin_project::__reexport::pin::Pin<&mut Self>) {}
+ }
+
+ // Ensure that it's impossible to use pin projections on a #[repr(packed)] struct.
+ //
+ // Taking a reference to a packed field is unsafe, and applying
+ // #[deny(safe_packed_borrows)] makes sure that doing this without
+ // an 'unsafe' block (which we deliberately do not generate)
+ // is a hard error.
+ //
+ // If the struct ends up having #[repr(packed)] applied somehow,
+ // this will generate an (unfriendly) error message. Under all reasonable
+ // circumstances, we'll detect the #[repr(packed)] attribute, and generate
+ // a much nicer error above.
+ //
+ // See https://github.com/taiki-e/pin-project/pull/34 for more details.
+ #[deny(safe_packed_borrows)]
+ fn __assert_not_repr_packed<T, U>(val: &Struct<T, U>) {
+ &val.pinned;
+ &val.unpinned;
+ }
+};
+
+fn main() {}
diff --git a/examples/struct-default.rs b/examples/struct-default.rs
new file mode 100644
index 0000000..46808a5
--- /dev/null
+++ b/examples/struct-default.rs
@@ -0,0 +1,14 @@
+// See ./struct-default-expanded.rs for generated code.
+
+#![allow(dead_code)]
+
+use pin_project::pin_project;
+
+#[pin_project]
+struct Struct<T, U> {
+ #[pin]
+ pinned: T,
+ unpinned: U,
+}
+
+fn main() {}
diff --git a/examples/unsafe_unpin-expanded.rs b/examples/unsafe_unpin-expanded.rs
new file mode 100644
index 0000000..7d8ad8e
--- /dev/null
+++ b/examples/unsafe_unpin-expanded.rs
@@ -0,0 +1,111 @@
+// Original code (./unsafe_unpin.rs):
+//
+// ```rust
+// #![allow(dead_code)]
+//
+// use pin_project::{pin_project, UnsafeUnpin};
+//
+// #[pin_project(UnsafeUnpin)]
+// pub struct Struct<T, U> {
+// #[pin]
+// pinned: T,
+// unpinned: U,
+// }
+//
+// unsafe impl<T: Unpin, U> UnsafeUnpin for Struct<T, U> {}
+//
+// fn main() {}
+// ```
+
+#![allow(dead_code, unused_imports, unused_parens)]
+#![allow(clippy::no_effect)]
+
+use pin_project::{pin_project, UnsafeUnpin};
+
+pub struct Struct<T, U> {
+ // #[pin]
+ pinned: T,
+ unpinned: U,
+}
+
+#[doc(hidden)]
+#[allow(clippy::mut_mut)] // This lint warns `&mut &mut <ty>`.
+#[allow(dead_code)] // This lint warns unused fields/variants.
+#[allow(single_use_lifetimes)]
+pub(crate) struct __StructProjection<'pin, T, U>
+where
+ Struct<T, U>: 'pin,
+{
+ pinned: ::pin_project::__reexport::pin::Pin<&'pin mut (T)>,
+ unpinned: &'pin mut (U),
+}
+#[doc(hidden)]
+#[allow(dead_code)] // This lint warns unused fields/variants.
+#[allow(single_use_lifetimes)]
+pub(crate) struct __StructProjectionRef<'pin, T, U>
+where
+ Struct<T, U>: 'pin,
+{
+ pinned: ::pin_project::__reexport::pin::Pin<&'pin (T)>,
+ unpinned: &'pin (U),
+}
+
+#[doc(hidden)]
+#[allow(non_upper_case_globals)]
+#[allow(single_use_lifetimes)]
+const __SCOPE_Struct: () = {
+ impl<T, U> Struct<T, U> {
+ pub(crate) fn project<'pin>(
+ self: ::pin_project::__reexport::pin::Pin<&'pin mut Self>,
+ ) -> __StructProjection<'pin, T, U> {
+ unsafe {
+ let Self { pinned, unpinned } = self.get_unchecked_mut();
+ __StructProjection {
+ pinned: ::pin_project::__reexport::pin::Pin::new_unchecked(pinned),
+ unpinned,
+ }
+ }
+ }
+ pub(crate) fn project_ref<'pin>(
+ self: ::pin_project::__reexport::pin::Pin<&'pin Self>,
+ ) -> __StructProjectionRef<'pin, T, U> {
+ unsafe {
+ let Self { pinned, unpinned } = self.get_ref();
+ __StructProjectionRef {
+ pinned: ::pin_project::__reexport::pin::Pin::new_unchecked(pinned),
+ unpinned,
+ }
+ }
+ }
+ }
+
+ impl<'pin, T, U> ::pin_project::__reexport::marker::Unpin for Struct<T, U> where
+ ::pin_project::__private::Wrapper<'pin, Self>: ::pin_project::UnsafeUnpin
+ {
+ }
+
+ // Ensure that struct does not implement `Drop`.
+ //
+ // See ./struct-default-expanded.rs for details.
+ trait StructMustNotImplDrop {}
+ #[allow(clippy::drop_bounds)]
+ impl<T: ::pin_project::__reexport::ops::Drop> StructMustNotImplDrop for T {}
+ impl<T, U> StructMustNotImplDrop for Struct<T, U> {}
+ impl<T, U> ::pin_project::__private::PinnedDrop for Struct<T, U> {
+ unsafe fn drop(self: ::pin_project::__reexport::pin::Pin<&mut Self>) {}
+ }
+
+ // Ensure that it's impossible to use pin projections on a #[repr(packed)] struct.
+ //
+ // See ./struct-default-expanded.rs and https://github.com/taiki-e/pin-project/pull/34
+ // for details.
+ #[deny(safe_packed_borrows)]
+ fn __assert_not_repr_packed<T, U>(val: &Struct<T, U>) {
+ &val.pinned;
+ &val.unpinned;
+ }
+};
+
+unsafe impl<T: Unpin, U> UnsafeUnpin for Struct<T, U> {}
+
+fn main() {}
diff --git a/examples/unsafe_unpin.rs b/examples/unsafe_unpin.rs
new file mode 100644
index 0000000..5ec0cd2
--- /dev/null
+++ b/examples/unsafe_unpin.rs
@@ -0,0 +1,16 @@
+// See ./unsafe_unpin-expanded.rs for generated code.
+
+#![allow(dead_code)]
+
+use pin_project::{pin_project, UnsafeUnpin};
+
+#[pin_project(UnsafeUnpin)]
+pub struct Struct<T, U> {
+ #[pin]
+ pinned: T,
+ unpinned: U,
+}
+
+unsafe impl<T: Unpin, U> UnsafeUnpin for Struct<T, U> {}
+
+fn main() {}